setup

Configures a repo once for the compost skills, recording its issue tracker, domain doc layout, core docs, test convention, verify gates, and observability st...

npx skills

npx skills add JoshuaOliphant/compost --skill setup

Works for Codex, Cursor and other harnesses. Use -a <agent> to target one, e.g. -a codex.

Claude Code

/plugin marketplace add JoshuaOliphant/compost
/plugin install compost@compost

Setup

The other compost skills assume a few facts about the repo: where issues live, where the glossary and ADRs live, which docs are core, how tests are written, which gates must pass before anything counts as done, and how to read what the running code emits. Setup finds those facts, confirms the ones that branch, and writes them to docs/agents/, where every skill reads them. It also points the repo's instructions file at those docs and offers to consolidate the instructions into AGENTS.md.

Setup is idempotent. Running it again updates what changed and keeps everything else, including edits the user made by hand.

Steps

  1. Explore. Read what exists; assume nothing.
  2. git remote -v: GitHub, GitLab (gitlab.com or a self-hosted host), or none.
  3. Instruction files in the repo root and in every directory above it: CLAUDE.md, .claude/CLAUDE.md, CLAUDE.local.md, AGENTS.md, .claude/AGENTS.md. Note any existing ## Agent skills block and whether a CLAUDE.md is an @AGENTS.md import or a symlink.
  4. docs/agents/: the output of an earlier run.
  5. CONTEXT.md, CONTEXT-MAP.md, docs/adr/, and any */docs/adr/ in subpackages.
  6. .scratch/: a sign a local tracker is already in use.
  7. Markdown outside the core docs (docs/, architecture notes, plan files), files that are product rather than prose (skill or prompt files, templates), and a published docs site (mkdocs.yml, docusaurus.config.*).
  8. Monorepo signals: pnpm-workspace.yaml, a workspaces field in package.json, [tool.uv.workspace] in pyproject.toml, a Cargo [workspace], go.work, or a populated packages/* whose members have their own sources.
  9. Tests and gates: the test layout and framework in use, coverage configuration, linters, type checkers, formatters, .pre-commit-config.yaml, Makefile or justfile targets, package scripts, the commands CI runs in .github/workflows/ or .gitlab-ci.yml, and mutation testing config (cosmic-ray.toml, [tool.mutmut], stryker.config.*, .cargo/mutants.toml, a pitest plugin).
  10. Telemetry: .claude/harness/observability/, and Logfire, Sentry, or OpenTelemetry in the dependencies or the app's startup code.

  11. Present findings and ask only where the answer branches. Summarize what is present and what is missing, then take the sections below in order, one answer each. Lead with the recommendation so it can be accepted in a word. Skip a section entirely when exploration settled it. On a rerun, show what would change against the existing files instead.

  12. Issue tracker. Recommend GitHub when a remote points there, GitLab when one points there, and otherwise offer GitHub, GitLab, local markdown under .scratch/, or other (Jira, Linear: the user describes the workflow in a paragraph and you record it as prose). Before recording GitHub or GitLab, confirm the tracker has issues turned on: GitLab, glab api projects/:id reports issues_enabled: true; GitHub, gh api repos/{owner}/{repo} reports has_issues: true. When issues are off, record nothing and create no labels yet; ask whether to enable them (GitLab: Settings > General > Visibility, project features and permissions; GitHub: Settings > General > Features) or pick another tracker. When the check can't run (no auth, host unreachable), say so and ask; don't record on a guess. Otherwise the disabled tracker only surfaces when compost:spec fails to post. Write docs/agents/issue-tracker.md from the matching template: GitHub, GitLab, or local. Each carries the label vocabulary compost uses; if the tracker already has labels for the same roles, map them in the table rather than creating duplicates. For GitHub or GitLab, list the tracker's labels (gh api repos/{owner}/{repo}/labels --paginate --jq '.[].name' / glab label list) and create every label in the table that it lacks (the template's label command / glab label create) now, so the first issue labelled spec doesn't fail.

  13. Domain docs. Default to a single context: one CONTEXT.md and docs/adr/ at the root. Write that without asking. Offer a CONTEXT-MAP.md with one CONTEXT.md per context only when exploration found monorepo signals, and confirm the layout then (ubiquitous language). Write docs/agents/domain.md from domain. Don't create CONTEXT.md or docs/adr/ now; compost:spec creates them when the first term or decision settles.

  14. Core docs. Write docs/agents/docs.md from docs: the core docs that exist, any the repo needs beyond the defaults, and the patterns that are product rather than documentation. Don't ask; the user edits the file if a default is wrong. Then run uv run ${CLAUDE_PLUGIN_ROOT}/scripts/doc_refs.py scan with those patterns. If it lists non-core docs, tell the user how many, how many name paths that no longer exist or files that changed since, and that compost:prune will check them against the code, move what is worth keeping into names, types, tests, and comments, and delete the rest. Offer it as the next move after setup; pruning is its own change, never part of this commit (core docs).

  15. Test convention and gates. Work out the convention with the detection ladder in testing: adopt the pattern already in use, default by stack when there are no tests, and ask only for a greenfield repo with no clear stack. Then list the gates compost:verify will run: the suite command, the coverage command and threshold (100% line coverage unless the project already sets one), linters, type checkers, and anything CI treats as required. Run each gate once. Record the ones that pass as gates; record a gate that fails or doesn't run as broken, with its output's first error, rather than dropping it. Record the mutation tool the same way: adopt one already configured, or offer the stack's default from mutation testing, and run it once over the last commit that changed source. Write docs/agents/testing.md from the template in the same reference.

  16. Observability. Find the telemetry the repo's running code emits with the detection ladder in observability: the observability harness, another stack already wired, or, with nothing found, one question offering the harness, the user's own stack, or none. Run one query against what you record, and record a stack you cannot read as broken with its first error. Write docs/agents/observability.md from the template in the same reference (read the running system). Another skill that finds the file missing runs this step on its own: then also add the ### Observability entry to the ## Agent skills block (step 8) and commit both as chore: record the observability stack, so the next skill finds them.

  17. Instructions file and the AGENTS.md migration. Claude Code reads AGENTS.md natively only when no CLAUDE.md, .claude/CLAUDE.md, or CLAUDE.local.md exists in the working directory or above it; ~/.claude/CLAUDE.md doesn't count and still loads alongside. Follow instruction files for each combination you found. In short:

  18. A project CLAUDE.md and no AGENTS.md: offer to move it into AGENTS.md with git mv, so both are never present. Personal preferences in it belong in ~/.claude/CLAUDE.md; show which lines and move them only with the user's yes.
  19. Both present: offer to fold CLAUDE.md into AGENTS.md and remove it.
  20. Neither present: ask which to create, recommending AGENTS.md.
  21. Never create one file while the other exists without offering first.

Then add or update the ## Agent skills block in whichever file holds the project instructions. Replace an existing block in place; leave the surrounding sections alone.

  1. Check the Jev key. Run uv run ${CLAUDE_PLUGIN_ROOT}/scripts/jev.py status. It looks for a TypeSafe key (TYPESAFE_API_KEY, then the macOS Keychain item typesafe) and builds the client, but sends no request; its line names the model and server. When the user would rather keep diffs on their machine or has no key, offer Ollaya, a local server with TypeSafe's wire format: compost's README, "Running on Ollaya instead", has the variables to export (including NO_PROXY for a machine behind a system proxy). Tell them its thresholds were measured on Jev and that a model with a small option budget falls back on the asks it cannot fit. With TYPESAFE_BASE_URL set, status says "configured (not contacted)": it cannot tell whether that server is running, so say so. Exit 0 with "ready" means the Jev tools will answer. Exit 3 means every Jev step will fall back to your own judgment: tell the user what they lose (cheaper test placement, review triage, the Stop guard in unattended runs) and pass on the fix its one line names. With no key, that is a command for them to run themselves, for example as ! security add-generic-password -s typesafe -a "$USER" -w; when the client could not start, it is the key's format or the proxy setting it quotes. Never ask for the key in chat or write it anywhere. The key belongs to the machine, not the repo, so record nothing.

  2. Switch off what compost replaces. Run uv run ${CLAUDE_PLUGIN_ROOT}/scripts/pile.py replaced. It reads the [replaces] table in compost's pile.toml and reports which superseded plugins and skills are still active on this machine; it changes nothing. Leaving them on gives Claude two answers to every request. Show the user the report and, with their yes, run it again with --apply: it disables the plugins through claude plugin disable and sets the skills to "off" in skillOverrides in ~/.claude/settings.json, keeping everything else there. Plugins synced from claude.ai can only be turned off in the user's claude.ai settings, so pass those on. None of this deletes anything: re-enabling a plugin or removing an override turns it back on.

    compost itself can be enabled twice, as compost@compost and compost@oliphant-plugins, which loads every skill twice. The report marks the id that isn't running this script as compost itself wherever it lists it (to disable, to turn off on claude.ai if synced, or to uninstall if orphaned), and never lists the one that is. It lists neither when it can't tell which copy runs (a checkout run with --plugin-dir, or a copy already disabled earlier in this session) or when the running copy is itself orphaned, since the other is then the one to keep.

    The report also lists, under its own heading, orphaned installs: plugins still installed whose marketplace's clone no longer lists them, enabled or not. They load stale copies and fail every marketplace update. --apply uninstalls them through claude plugin uninstall, keeping their data directories, and unlike disabling this cannot be undone, since the marketplace no longer offers them. Ask about them as a separate yes: if the user wants the superseded ones turned off but the orphans kept, run --apply --keep-orphans. This is per machine, so on a second repo the report usually says nothing is active.

  3. Check and commit. Re-read every file you wrote. List the directories above the repo that still hold a CLAUDE.md, since any of them stops AGENTS.md from loading. Run git check-ignore -v on every file you wrote in the repo: each docs/agents/*.md, the instructions file, and any CONTEXT-MAP.md or CONTEXT.md. It prints a source:line:pattern line for each ignored path, and a broad rule (agents/ also matches docs/agents/) leaves a file out of the commit without a word. For each hit, show the user the rule and offer to anchor it (/agents/) or narrow it, editing the file it came from only with their yes; if they keep it, say which files the commit leaves out. Commit the changes as one chore: configure agent skills commit. Tell the user which compost skills now read these files, that they can edit docs/agents/*.md directly, and, after a migration, to look for the AGENTS.md loaded line at the start of their next session. Also tell them that in manual permission mode the /compost:review-changes workflow asks for permission on every run until they pick "Yes, and don't ask again", or until they add Workflow(compost:review-changes) to their allow rules.

Next moves

  • compost:prune when the core-docs step found docs outside the core, so the repo starts with docs the code backs.
  • compost:spec when there is a feature or change to define.
  • compost:slice when a spec already exists as an issue or doc.
  • compost:diagnose when a gate came back broken and the repo should be green before other work.

← compost