- Python 61.5%
- Shell 23.7%
- JavaScript 14.8%
| .claude | ||
| centralised_sync | ||
| issues | ||
| marketplace | ||
| README.md | ||
Generalised Claude source — skills, MCP & workflows, assembled per repo
This repository is the single private source for reusable Claude Code skills, MCP servers, and workflows, plus a pipeline that assembles them into a separate, per-repo Claude home. Distribution is plain git (self-hosted Forgejo) — no public catalog, no plugin-registration step. You publish by pushing here; a consumer sets up a brand-new Claude home for their repo by fetching one bootstrap script, filling in their repo-specific values, and running the marker builder, which injects those values into a generalised base to produce ordinary skills in that new home.
This template targets a separate repo + a new Claude home — never itself. Setup writes only into the new per-repo home you name; it does not modify, install into, or delete this repository, and it removes nothing of yours. See Safety invariant.
This README is the overview + exact step-by-step. The detailed how-tos live in the sub-docs below — this page links to them rather than repeating them.
Documentation map
| Doc | Use it for |
|---|---|
| this README | The big picture + the exact, copy-pasteable step-by-step for a new home. |
marketplace/USAGE.md |
The detailed user guide — consume, customise, the flat custom-file format, migration, "what to expect", and a worked walkthrough (§1–§9). |
marketplace/README.md |
The marketplace / plugin structure & format (what each file is). |
marketplace/scripts/README.md |
The git/hub-* script reference + lifecycle. |
marketplace/pipeline/hooks.README.md |
Auto-run options (home settings.json hook / direnv). |
centralised_sync/marker-pipeline-spec.md · division.md |
Design & rationale — the marker model, conventions, and platform build-rules. |
Repo layout (overview)
marketplace/ # the active structure — what you publish & a consumer assembles from
├── .claude-plugin/marketplace.json # plugin manifest (also drives `claude plugin validate`)
├── plugins/<concern>/ # one plugin per concern (skills + MCP + workflow seeds)
├── pipeline/marker-builder.py # the builder: injects your [section]/[var] values into a base
├── pipeline/PIPELINE.base.md # the build-literacy guide rendered into each home as PIPELINE.md
├── pipeline/hooks.json # optional Setup/SessionStart auto-run of `all`
└── scripts/ # bootstrap.sh + hub-* git helpers (clone/pull/push/install)
centralised_sync/ # design docs (marker-pipeline-spec.md, division.md, plan.md)
Full per-file breakdown: marketplace/README.md. Plugins come in types —
skills, agents (subagents rendered to the home's agents/<name>.md; e.g. subagents),
MCP, hook plugins (a hooks/hooks.json + hooks/*.sh pair the builder materialises into the
home and registers in its settings.json — enforcement the harness evaluates, not prose a model must
read), and first-class workflow plugins (e.g. session-orchestration / plan-implementation:
dynamic workflows + their own recipes/rules, customised via one flat marker custom file; see
marketplace/USAGE.md §6b/§6f/§6g). Consumption is the git + marker-builder flow
below: artifacts ship as generalised bases that the builder assembles/materialises locally into the new home.
Current pipeline version
Pipeline 10 · grammar 2 (PIPELINE_VERSION / GRAMMAR_VERSION in
marketplace/pipeline/marker-builder.py; recorded into every
home's .marker-builder/manifest.json and enforced by the compat gate). The engine version is the
single source of truth — surface it in the commit message and update this line whenever it is bumped
(see §B). Pipeline 10 = hooks as a rendered enforcement surface
(+ the per-home PIPELINE.md guide); 9 = unlaunchable MCP servers skipped, ungrammatical
${user_config.KEY} flagged as a plugin bug; 8 = agents as a first-class component;
7 = !@FORCELOAD; 5 = per-MCP build-time deps. Grammar 2 = local/.exclusions gains the
hook class.
The model in 30 seconds
- The hub is this git repo (public to clone, no plugin catalog). Publish =
git push; set up a new home = fetchbootstrap.shfrom the public hub → it places the template + pipeline inside the new home (.hub-src/) and seeds the per-skill custom files (no prior clone, no key). You then fill your values and build into that home. Already have a checkout?hub-install.sh --source .does the same. - Each skill ships a generalised base —
SKILL.base.mdand everyreferences/*.md— carrying in-place markers:[section X](a single whole-line site) and[var X](an inline token that may recur). The builder injects your values at those markers and renders one completeSKILL.md(+ itsreferences/) into the home. A per-artifactversion/<N>/ledger drives non-destructive migration. - You author values; the structure wires them. Per skill you fill one home file —
$CLAUDE_CONFIG_DIR/local/<skill>.custom.md(flat:[section …]blocks + a bottom@@VARIABLES@@list). Format detail:marketplace/USAGE.md§3.
Safety invariant — template vs target
This repo is a read-only template; the new per-repo Claude home you name ($CLAUDE_CONFIG_DIR)
is the only write target. Concretely:
- The builder writes only under
--home, and only its own trees/files there —<home>/local/…,<home>/skills/…,<home>/agents/…,<home>/workflows/…,<home>/rules/…,<home>/hooks/…, plus<home>/.claude.json,<home>/CLAUDE.md,<home>/PIPELINE.md— and it merges into<home>/settings.jsonrather than replacing it (only the hook entries whose command resolves under<home>/hooks/; every other key, including hooks you wrote, is preserved byte-for-byte). It never writes intomarketplace/plugins/, so it cannot overwrite the template or "run inside" it. - Setup refuses to touch an unintended home.
bootstrap.shtargets only the explicit, setup-scopedSETUP_CLAUDE_CONFIG_DIRand refuses to run if it is unset — so a stray run (wrong cwd, direnv not allowed) can't scribble into your real/global Claude home. - Nothing of yours is removed. Re-running bootstrap only refreshes the home's own
.hub-src/copy; seeding/building never clobber an already-filledlocal/*.custom.md. The template repo and the hub cache are left intact. Setup is not self-targeting and not self-removing. - Always keep the template and the home as separate directories. The
.hub-src/copy inside the home makes this automatic — every build reads the home's own copy, never this repo.
Note: the builder does not enforce directory separation with a hard overlap check (it simply only ever writes under
--home). The real guard isbootstrap.sh's requiredSETUP_CLAUDE_CONFIG_DIR. If you invokemarker-builder.pydirectly, pass a--homethat is its own directory, distinct from the plugins root.
A. Set up a brand-new Claude home for a repo (consumer) — exact steps
This is the path the whole project is built for: create the dirs → pin the home in the repo's .envrc
→ bootstrap → fill your values → build → use. You do not clone this repo first; the bootstrap
script is the only thing you fetch, and it makes the home self-contained (.hub-src/) so every later
build runs from the home itself. No hub SSH key is needed (the hub is public to clone).
Throughout, substitute your-repo for your project's name. Two directories are involved and they are
always separate: the repo dir (~/your-repo, your actual code) and the new Claude home
(~/claude-your-repo, where the assembled skills land and where Claude Code reads them).
Step 1 — Create the two new directories
mkdir -p ~/your-repo ~/claude-your-repo
~/your-repo— your repository working directory (its.envrcwill point Claude at the home).~/claude-your-repo— the dedicated Claude home for this repo. Nothing else writes here.
Step 2 — Write the repo's .envrc so the repo dir is tied to its Claude home
The repo's .envrc is the single knob that binds ~/your-repo to ~/claude-your-repo. It sets two
variables, for two phases:
SETUP_CLAUDE_CONFIG_DIR— used once, bybootstrap.sh, to know which new home to build into. It is deliberately notCLAUDE_CONFIG_DIR, so a misfire can never hit your real/global home.CLAUDE_CONFIG_DIR— used every day after setup, so that whenever youcd ~/your-repo, Claude Code reads the assembled skills from~/claude-your-repo.
cat >> ~/your-repo/.envrc <<'EOF'
export SETUP_CLAUDE_CONFIG_DIR=$HOME/claude-your-repo # one-time: where bootstrap builds
export CLAUDE_CONFIG_DIR=$HOME/claude-your-repo # daily: where Claude Code reads skills
EOF
direnv allow ~/your-repo
No direnv? Skip the
.envrcand justexport SETUP_CLAUDE_CONFIG_DIR=$HOME/claude-your-repoin the shell you run Step 3 in (and laterexport CLAUDE_CONFIG_DIR=$HOME/claude-your-repoto use the home).
Step 3 — Bootstrap from the public hub (seeds only; does not build yet)
Run from the repo dir so direnv loads SETUP_CLAUDE_CONFIG_DIR:
cd ~/your-repo
curl -fsSL https://git.isaklandin.com/isakadmin/generalised-skill-claude/raw/branch/main/marketplace/scripts/bootstrap.sh | bash
What this does (and only this):
- Clones the public hub once into
~/.cache/claude-hub(overrideHUB_URL=…/HUB_REF=…). - Copies the template + pipeline into
$SETUP_CLAUDE_CONFIG_DIR/.hub-src/(the home's self-contained copy — re-placed fresh on each bootstrap, never yourlocal/files). - Seeds one
$SETUP_CLAUDE_CONFIG_DIR/local/<skill>.custom.mdper skill/workflow and prints the required sections/vars you must fill. Nothing is installed/assembled yet.
Already have a checkout of this repo? Skip bootstrap and seed+build in one shot:
CLAUDE_CONFIG_DIR=$HOME/claude-your-repo bash marketplace/scripts/hub-install.sh --source . --all.
Step 4 — Fill your repo-specific values in the new home
cd ~/claude-your-repo
Edit each local/<skill>.custom.md (one flat file per skill/workflow). In each file:
- Replace the guidance under every
[section X]with your content (a section that does not apply → put@@---@@as its only content). - Set every value after
[var X] =in the bottom@@VARIABLES@@block.
Build-ignored guidance is @@# … or @@ … @@; the version is !@VERSION N on line 1. Workflow plugins
(e.g. session-orchestration) use the same grammar with typed blocks ([section rule X] /
[section rule path X] / [section recipe X]). Full format: .hub-src/USAGE.md §3 (and §6 / §6b).
Step 5 — Build the home (inject your values → real skills)
cd ~/claude-your-repo
# assemble the WHOLE home — skills + agents + MCP merge + hooks + workflows + PIPELINE.md + routing:
python3 .hub-src/pipeline/marker-builder.py all --home "$PWD" --plugins-root .hub-src/plugins
# build one skill only:
# python3 .hub-src/pipeline/marker-builder.py build --home "$PWD" --plugins-root .hub-src/plugins --skill <name>
# ( add --plugins a,b to scope the mcp/workflows stages; --force to rewrite up-to-date skills )
Because cwd is the home, $PWD is the unambiguous, safe target. The builder blocks any skill whose
required [section]/[var] is still empty (each reported as a precise CHANGE THIS: … line) and
assembles the rest — fill what it names and re-run. Outputs land in
~/claude-your-repo/skills/<skill>/SKILL.md (+ references/) and agents/<agent>.md, with MCP merged
into .claude.json, hooks materialised into hooks/<plugin>/ and registered in settings.json,
workflows materialised, the home's PIPELINE.md guide rendered, and CLAUDE.md routing wired.
Step 6 — Use the new home
CLAUDE_CONFIG_DIR from Step 2 already points Claude Code at ~/claude-your-repo whenever you're in the
repo dir. So:
cd ~/your-repo # direnv loads CLAUDE_CONFIG_DIR=$HOME/claude-your-repo
# in Claude Code: /reload-plugins (or restart) → the assembled skills + workflows are live
→ Full detail — selection flags, the flat custom-file format, workflow plugins, migration, and a worked
walkthrough: marketplace/USAGE.md §3, §5, §6, §6b, §8, §9.
B. Publish a change (maintainer)
- Edit or add a plugin under
marketplace/plugins/<name>/— edit the generalised base + its in-place[section]/[var]markers (conventions:centralised_sync/division.md, marker model:centralised_sync/marker-pipeline-spec.md). - When you change a base's markers (add/rename/remove), bump the artifact and record it so existing
homes migrate non-destructively:
python3 marketplace/pipeline/marker-builder.py capture --plugins-root marketplace/plugins \ --skill <name> --version <N> # then edit …/skills/<name>/version/<N>/changes.md, e.g.: # rename var datastore = primary_store # add section retention-policy # remove section legacy-flag - Validate:
claude plugin validate ./marketplace/plugins/<name>. - If you bumped the engine (
PIPELINE_VERSION/GRAMMAR_VERSIONinmarker-builder.py), make the version visible in git and the README: name the new version in the commit message (e.g.feat(pipeline): … (pipeline v8)) and update the "Current pipeline version" line above. The version is otherwise invisible in the commit log — surfacing it is how forgejo/readers see what changed. (Per-artifact!@VERSION Nledger bumps are separate, recorded inversion/<N>/changes.md.) - Publish (commit + push to Forgejo):
bash marketplace/scripts/hub-push.sh . "your message".
→ Detail & adding a new plugin to the catalog: marketplace/USAGE.md §4.
C. Keep a home current & auto-run
- Update — one shot:
./build.sh(lives at the home's top level). Self-contained: a top section fetches the latest hub withcurl, then (a) self-updates — if its own copy differs from the hub'sscripts/build.shit atomically replaces itself and STOPS (re-run; it never runs stale logic), else (b) replaces the pipeline scripts + plugin bases in.hub-src(the pipeline is updated here, externally — it never updates itself), then runsmarker-builder.py all, letting the pipeline update the skills: a structural base change (e.g. a new reference md adding a[section]/[var]) is reconciled into your custom file as a blank@@FILL@@, your filled values migrate forward, the gate runs, and a self-update or any new/unfilled marker STOPS the whole run (set -e, non-zero) with nothing rendered — re-run, or fill it inlocal/*.custom.mdand re-run.
Equivalent long form (whatcd ~/claude-your-repo && ./build.sh # self-update if needed, else fetch bases, reflect, gate, render ./build.sh --no-update # build against the existing .hub-src (skip ALL network)build.shreuses): re-runbootstrap.sh(re-places.hub-src), thenmarker-builder.py sync(migrate + build).build.shadds no pipeline logic of its own beyond the self-contained fetch.syncsnapshots the home to.hub-cache/<timestamp>/(permanent), carries your values across renames, inserts genuinely new markers blank (the gate forces a fill), and re-assembles. Detail: USAGE.md §8. - Safe for a persistent, product-tailored home. A home is long-lived and holds irreplaceable work, so
every build is non-destructive by construction:
- Drops survive refresh. Concerns your product doesn't have go in
local/.exclusions(marker-builder.py exclude --skill|--agent|--plugin|--mcp|--rule|--recipe|--hook <id>); the builder honors them at discovery and GC quarantines their customs. Because the file lives inlocal/,build.sh's wholesale.hub-srcrefresh can never silently resurrect them. (USAGE §6c.) - Atomic.
allsnapshots the whole home up front and rolls back on any mid-render failure — never a half-assembled home; a gate block writes nothing. - Version-aware. A stale
.hub-srcbuilder refuses to run against a home a newer builder built (compat gate), rather than mis-migrate your values. The builder only ever writes its owned trees (local,skills,agents,workflows,rules,hooks) and files (.claude.json,CLAUDE.md,PIPELINE.md, plus only its own hook entries insidesettings.json— your control keys and your own hooks are preserved byte-for-byte) — never your project/session files. - The home explains itself. Every build renders
PIPELINE.md: this home's real authored→rendered inventory, the marker grammar, and the build commands,@-imported byCLAUDE.md. It exists because a rendered home's most likely failure is a model editing build output instead of thelocal/*.custom.mdbehind it — an edit that looks fine and silently reverts. (USAGE §6h.)
- Drops survive refresh. Concerns your product doesn't have go in
- Auto-run (optional): wire a
SessionStarthook in the home'ssettings.json(or a direnv step) to runmarker-builder.py all— no plugin install. Options:marketplace/pipeline/hooks.README.md.
→ What each pipeline run does (assemble / gate / materialise / MCP-merge / migrate):
marketplace/USAGE.md §7 and centralised_sync/division.md.