This repository is the root of the compound-engineering coding-agent plugin and the marketplace/catalog metadata used to distribute it.
It also contains:
- the Bun/TypeScript CLI that converts Claude Code plugins into other agent platform formats
- shared release and metadata infrastructure for the CLI, marketplace, and plugin
AGENTS.md is the canonical repo instruction file. Root CLAUDE.md is a symlink to AGENTS.md so Claude Code and other tools that look for CLAUDE.md still find it at the expected path. Keep that symlink (do not replace it with a regular file): a real root CLAUDE.md makes claude plugin validate --strict fail because this checkout is also the plugin root.
bun install
bun run test # full test suite (also runs in CI; `--parallel` across worker processes)
bun run release:validate # plugin/marketplace consistency (also runs in CI)
bun run plugin:validate # Claude marketplace + plugin schema (also runs in CI; needs `claude` on PATH)When testing current skill files in Codex, run the repository workflow from the checkout or worktree you intend to test:
bun run codex:dev -- local # link this worktree's skills and remove CE plugin installs
bun run codex:dev -- status # show local/remote state and checkout provenance
bun run codex:dev -- remote # restore the official marketplace-backed plugin
bun run codex:dev -- remove # remove both supported CE installation surfacesrefresh is an idempotent alias for local. Local mode manages only the exact $CODEX_HOME/skills/compound-engineering-local symlink and Compound Engineering plugin IDs; it must not alter unrelated user skills. The symlink includes modified and untracked files from the selected worktree. Start a new Codex session after switching installation modes. Current Codex versions detect direct skill edits automatically; restart only if an edit does not appear. For live local testing, use this workflow instead of adding the repository as a marketplace: a marketplace install caches a snapshot, while local mode links the current skill files.
- Branching: Create a feature branch for any non-trivial change. If already on the correct branch for the task, keep using it; do not create additional branches or worktrees unless explicitly requested.
- Merge policy: All changes to
maingo through pull requests. Direct pushes and direct merges are not allowed; branch protection onmainenforces this by requiring theteststatus check to pass. The direct path bypassesrelease:validate, the test suite, and PR title validation — past direct merges have caused version drift requiring multi-PR recovery (seedocs/solutions/workflow/release-please-version-drift-recovery.md). - Contribution gate (non-maintainers): If you are not a repository maintainer or admin, do not open a PR without a linked issue — file the issue first and reference it from the PR. Adding a new skill has a stricter gate: non-maintainers and non-admins must raise a discussion in an issue and get explicit maintainer approval before starting the work; do not open a new-skill PR that has not been approved this way. Maintainers and admins are exempt from both gates but still follow the merge policy above.
- PR disclosure:
.github/pull_request_template.mdends with## Security Disclosureand## Agent Disclosuresections. Fill both when opening a PR — including PRs authored viagh pr create --body/--body-file, which bypass the template so nothing pre-fills them. State any security-relevant changes (or "No security-relevant changes"), and the model that did the bulk of the work — your harness plus the most specific model identity your own context gives you, e.g.Claude Code · claude-opus-4-8orCodex CLI · GPT-5. Copy an exact model ID verbatim when your harness states one; when it exposes only a generic family, report the family and stop. Measured 2026-07-24: Codex and Cursor agents cannot see their running model at all (Codex's "based on GPT-5" is fixed boilerplate), so do not upgrade a family to a version, and do not read config files for one — the configured default is often not the model actually running. Never invent a version or variant. The body above those sections stays freeform — add whatever sections best explain the change. - Safety: Do not delete or overwrite user data. Avoid destructive commands.
- Testing: Run
bun run testafter changes that affect parsing, conversion, output, skill conventions, or other mechanical guards. Localbun run testis the same suite CI runs — there is no separate local-only unit-test lane. Prefer it over barebun test: the package script carries--parallel, which is where the suite's speed comes from. Barebun test <file>is still the right tool for iterating on one file. The suite uses disposable fixtures and has no production access. Run it, fix failures caused by the requested change, and rerun affected tests without asking for approval at each step. - Compounding learnings: After a solved, verified problem, automatically invoke the
ce-compoundskill withmode:non-interactiveat the completion checkpoint only when the work produced durable project reasoning that is not readily recoverable from the final code, tests, types, comments, or existing documentation, and losing it would plausibly cause recurrence, material risk, or substantial rediscovery. Apply this counterfactual: if the learning document disappeared, would a future engineer reading the final implementation still be likely to repeat the mistake or redo substantial investigation? If not, do not invoke it. Completion, effort, and diff size alone are not enough. Capture at the checkpoint so a qualifying learning can ship in the PR that produced it, and only where the repository treats captured learnings as tracked, committed knowledge. This repository does:docs/solutions/is tracked (see Repository Docs Convention). Ifce-compoundis not callable in the current harness (a checkout without the plugin installed or linked), do not block and do not skip silently: say in the completion report that a qualifying learning was left uncaptured, so the author can run it from a plugin-enabled session. - Release versioning: Releases are prepared by release automation, not normal feature PRs. The repo has one root plugin/package release component (
compound-engineering) plus marketplace components (marketplace,cursor-marketplace). GitHub release PRs and GitHub Releases are the canonical release-notes surface for new releases; rootCHANGELOG.mdis only a pointer to that history. Use conventional titles such asfeat:andfix:so release automation can classify change intent, but do not hand-bump release-owned versions or hand-author release notes in routine PRs. - Output Paths: Keep OpenCode output at
opencode.jsonand.opencode/{agents,skills,plugins}. For OpenCode, commands go to~/.config/opencode/commands/<name>.md;opencode.jsonis deep-merged (never overwritten wholesale). - Scratch Space: Default to OS temp. Use
.context/only when the artifact is repo-bound and user-curated, branch-inseparable, or the path is core UX. Copy the scratch-root preamble from any shipped skill (for exampleskills/ce-code-review/SKILL.md); do not re-derive it. Durable outputs belong indocs/. Layout,/tmpprobe, and Windows notes:docs/solutions/developer-experience/always-on-agents-md.md. - Character encoding:
- Identifiers (file names, agent names, command names): ASCII only -- converters and regex patterns depend on it.
- Markdown tables: Use pipe-delimited (
| col | col |), never box-drawing characters. - Prose and skill content: Unicode is fine (emoji, punctuation, etc.). Prefer ASCII arrows (
->,<-) over Unicode arrows in code blocks and terminal examples.
src/ CLI entry point, parsers, converters, target writers
skills/ Compound Engineering plugin skills
docs/guides/ User-facing plugin guides (catalog and configuration)
.claude-plugin/ Claude plugin manifest and marketplace catalog metadata
.codex-plugin/ Codex plugin manifest
.cursor-plugin/ Cursor plugin manifest and marketplace catalog metadata
.opencode/ OpenCode package entrypoint and install docs
.pi/ Pi extension entrypoint
tests/ Converter, writer, and CLI tests + fixtures
docs/ Requirements, plans, solutions, and target specs
CONCEPTS.md Shared domain vocabulary (glossary of project-specific terms)
Changes in this repo may affect one or more of these surfaces:
- root plugin content under
skills/,AGENTS.md,README.md, and platform manifests - marketplace catalogs under
.claude-plugin/,.cursor-plugin/, and.agents/plugins/ - the converter/install CLI in
src/andpackage.json - the docs site under
site/(a Jekyll build layer overREADME.md,docs/guides/, anddocs/install/) and its workflow.github/workflows/pages.yml
Do not assume a repo change is "just CLI" or "just plugin" without checking which surface owns the affected files.
When changing plugin content:
- Update substantive docs like
README.mdwhen the plugin behavior, inventory, or usage changes. - When adding a user-facing skill, document it: create a
docs/guides/<skill-name>.mdpage (purpose, novel mechanics, when to use, chain position — follow the shape of the existing pages), add a catalog row under the right category indocs/guides/README.md, and bump the skill count intests/release-metadata.test.ts.docs/guides/README.mdis the only place a skill's prose description is maintained. The rootREADME.mdcarries a grouped overview that lists skill names under a category, so a new skill also needs its name added to the right group row and the three stated skill counts bumped (badge, intro, section lead).tests/release-metadata.test.tsenforces that every skill name appears in that overview exactly once, that no unknown name appears, and that the three counts match the skill directories underskills/(each with aSKILL.md) — so the suite catches a missing name, a stale count, or a name left behind during a move. Choosing the right group is yours; a test that knew the correct category per skill would be the second inventory this arrangement exists to avoid — the previous three-way sync of full descriptions was unenforced and had already drifted, which is why descriptions now live in exactly one place. Every current user-facing skill has a page, includinglfgandce-dogfood. - When adding, removing, renaming, or changing the meaning/default/consumer of a
.compound-engineering/config.yamloption, updateskills/ce-setup/references/config-template.yaml, its byte-identical.compound-engineering/config.example.yamlcopy, the centralizeddocs/guides/configuration.mdreference, and the affected consumer skill docs in the same change. Ordinary keys may also live in optional checkout-localconfig.local.yaml(overrides the repo file).docs_rootbelongs only inconfig.yaml. Durable team instructions still belong in the project's normal agent-instructions mechanism. - Do not hand-bump release-owned versions in plugin or marketplace manifests.
- Do not hand-add release entries to
CHANGELOG.mdor treat it as the canonical source for new releases. - Run
bun run release:validateif agents, commands, skills, MCP servers, or release-owned descriptions/counts may have changed. - When removing a skill, agent, or command, add its name to both cleanup registries so stale flat-install artifacts are swept on upgrade:
STALE_SKILL_DIRS/STALE_AGENT_NAMES/STALE_PROMPT_FILESinsrc/utils/legacy-cleanup.tsEXTRA_LEGACY_ARTIFACTS_BY_PLUGIN["compound-engineering"]insrc/data/plugin-legacy-artifacts.ts
Useful validation commands:
bun run release:validate
cat .claude-plugin/marketplace.json | jq .
cat .claude-plugin/plugin.json | jq .AGENTS.md, CLAUDE.md (symlink to AGENTS.md), and GEMINI.md are authoring context for this source repository. Skills are installed into end-user environments, where they run against the user's local instruction files, not this repo's. Behavioral rules that must affect a skill at runtime belong in that skill's SKILL.md or files under its own references/ directory.
This repository authors each skill once and distributes it across multiple agent models and harnesses. A skill is a set of goals, not a state machine: it hands the agent the goal, the done condition, the safe failure direction, and the facts it cannot derive from the repo in front of it, then gets out of the way. docs/solutions/skill-design/portable-agent-skill-authoring.md is the standard; the rules in this file supplement it and take precedence where more specific.
Before creating, editing, reviewing, or acting on review feedback for anything under skills/**, invoke the repo-local ce-skill-work skill (.agents/skills/ce-skill-work/, which Codex and Cursor discover directly; .claude/skills is a symlink to .agents/skills for Claude Code). It carries the procedures for each of those four activities, the audit questions, the provenance rule for removals, and the validation contract. The same routing applies when a skill-authoring best practice itself changes or is newly learned — a prompt-guide lesson, a tuning that demonstrably worked, a standard-level correction: invoke ce-skill-work and record the practice in docs/solutions/skill-design/portable-agent-skill-authoring.md (and here when it must be always-loaded), never only in one skill's prose. This file states only what must be always-loaded; when the two disagree, fix the disagreement rather than following the shorter one.
Three rules that hold regardless of whether the skill was invoked:
- State conditions, not procedures or cases. When a block keeps absorbing "add the case we just found" — in authoring, in a review round, or in your own fix to a finding — the representation is wrong. Delete the additions and restate the goal, then re-verify against every path the additions served; a restatement that no longer names a path is a new defect, not a simplification.
- Prescribe a mechanism only where it is owned. A delegating skill states the condition, the safe failure direction, and the non-derivable callee facts, never a re-derivation of the callee's commands (
docs/solutions/skill-design/skill-gates-state-conditions-not-prescribed-git-commands.md). - Bring the block you touch up to the standard; leave untouched blocks alone and name them as follow-up. Skills predate the standard and evolve toward it.
Keep agent-to-agent or skill-to-skill routing semantic: format formal skill names as inline code (for example, ce-plan) and invoke the named skill through the active harness's callable skill mechanism. When a skill prints or copies a user-runnable invocation, default to /skill-name; use $skill-name only when the active harness is Codex or explicitly documents dollar-prefixed skill invocation. On oh-my-pi (omp), keep the default form for model-visible targets; use native /skill:<name> only when the target is not model-visible because it declares disable-model-invocation or hide (for example, /skill:ce-polish). In prose, render only the invocation as inline code; use a fenced block only when the command stands alone. Output exactly one form. Do not apply this rendering rule to built-in commands such as /goal.
At runtime, put the smallest self-contained rendering rule immediately before the smallest section that contains all affected user-copy seams. Do not repeat it in every step; repeat it only in a separately loaded reference that independently owns output.
Review bots read this file when reviewing a PR here. On skills/**:
- A finding is a gap in the goal, the done condition, or the safe failure direction; over-prescription that degrades degrees of freedom; or a mechanism at the wrong owning layer — commands prescribed in a skill that delegates that work, repeated command blocks where one parameterized recipe would decide the same behavior, a model-invoked description that opens with identity boilerplate or catalogs one branch, a category opener that omits the distinctive mechanism, a quoted-utterance catalog on a model-invoked skill, per-step done checks not protecting a fragile gate, repeated ask-first gates not marking a different external/destructive/scope/user-only boundary, a rule placed where it will not fire, a Claude-only construct in a cross-host skill, a rendering that breaks on another harness.
- A case a stated condition already covers is not a finding. Before filing "what if X" against a rule, check whether the rule's condition decides X. If it does, do not file; if the condition is wrong or missing, file that.
- State the requested fix as a condition or an owning-layer move, never as a case to add. "Command X fails in state Y" against a delegating skill is a finding about the representation; the fix is to drop the command and state the condition, not to correct the command.
- A block restated to the standard is the expected shape of an edit, not scope creep, when the restatement covers every path the old text served.
- Ordinary code under
src/,tests/, andscripts/gets ordinary code review; these rules are about instruction prose.
This governs any agent or tool that acts on review feedback in this repository — ce-resolve-pr-feedback, another vendor's resolver, or a person — and on skills/** it takes precedence over the tool's own "default to fixing". Skill prose is not code: a natural-language instruction can always be made more specific, so a reviewer can produce a valid-looking edge case against any condition indefinitely, and patching each one dilutes the instruction (#1397: 24 findings over nine rounds on a two-condition step). A case the stated condition already decides is answered with the condition, not patched; only a wrong or missing condition, or a mechanism at the wrong owning layer, is a fix. On the second round against the same block, restate it rather than qualify it. The full procedure — Evidence, Owning layer, Mechanism, Reconcile, Stop the accretion loop — is ce-skill-work's respond mode.
When a skill needs to discover a project convention at runtime — the issue tracker, coding standards, commit format, lint command, scope constraints, etc. — describe what to look for in the agent's existing context, not which file to open.
On the read path, do not name instruction files (AGENTS.md / CLAUDE.md / GEMINI.md / .cursor/rules). Phrase it as "the project's active instructions and conventions already in your context." Three reasons:
- Redundant. Every major harness auto-injects the project's root instruction file into context at session start (Claude Code loads
CLAUDE.md, CodexAGENTS.md, GeminiGEMINI.md). Telling the agent to "readAGENTS.md" asks it to re-open content it already has. - Brittle / not portable. The filename differs per harness, and this plugin is authored once and converted to all of them. A hardcoded "read
AGENTS.md(orCLAUDE.md)" silently finds nothing on a harness that uses a different name. - Security smell. Instructing an agent to go read named instruction dotfiles is the exact shape that prompt-injection defenses in some agent frameworks (e.g., Hermes) flag. Referencing context rather than filenames avoids tripping those guards.
Name a concrete file only where the skill must do something a context reference can't express:
- Writing a convention back (e.g., persisting
project_tracker: linear) needs a target — name it minimally and as an example ("the project's root agent-instructions file, e.g.,AGENTS.md; if it@-includes another, write to the substantive one"). - Reading content that is genuinely not auto-loaded — a subdirectory-scoped instruction file governing the area being changed, an optional project doc like
STRATEGY.md/CONCEPTS.md/README.md, or any file a fresh subagent (which does not inherit the parent's loaded instructions) must open to do its job. Auditing tools that must enumerate every criteria file are a legitimate exception — they review the files, they don't re-read them for context.ce-code-review's project-standards reviewer globsCODING_STANDARDS.md, the designated criteria source, and readsCLAUDE.md/AGENTS.mdonly as criteria for changed files that noCODING_STANDARDS.mdgoverns.
Describe the capability, not the tool. Pair this with naming the category of thing rather than a closed set: "the project's issue tracker (e.g., GitHub Issues, Linear, Jira)" and "whatever interface that tracker exposes (connector/MCP, documented API, or a documented CLI)" — never assume a specific CLI exists, and never treat a missing binary / env var / MCP server as proof the capability is unavailable.
Behavioral changes to a plugin skill or skill-local persona (anything under skills/) need a different validation path than mechanical code changes, because of how Claude Code loads plugins.
-
Test prose changes by injecting the current on-disk skill into a fresh agent. Plugin skills cache at session start, so invoking the edited skill in the authoring session tests stale content. This repository does not ship an eval skill. The portable path is the host CLI you already have, against a skill dir extracted from a ref:
bun run test:skill-eval-cell. Named scenarios (pre-change contract vs current tree) run withbun run test:skill-eval-pack -- --skill <name> --arm ab. That usesclaude/codex/grokon PATH and bills those products, not a separate API key. Anthropic'sskill-creatoris an optional Claude-hosted helper, not required, and does not replace the cell. -
Plugin agent and skill definitions both cache at session start. Once a Claude Code session is open, dispatching a typed plugin agent runs the in-memory copy that was loaded when the session began. The same applies to skills: invoking a skill goes through the cached skill loader, so edits to skill scripts are also not tested via that path. File edits to either layer after session start do not propagate within the same session. Any iteration loop built around typed-agent dispatch or Skill-tool invocation in the same session is testing pre-edit content, not your changes.
-
Do NOT edit
~/.claude/plugins/cache/or~/.claude/plugins/marketplaces/to try to force a reload. Those paths are user machine state, not repo-managed. Modifying them does not reliably bypass the in-session cache (it didn't, in observed behavior), risks being silently overwritten by plugin updates, and is the wrong layer to test from. Inject current disk content into a fresh agent instead; if you genuinely need fresh-loaded behavior of the typed-agent dispatch path, restart the session. -
Mechanical changes do not have this restriction. Skill scripts (e.g.,
extract-metadata.py), parser logic, conversion code, and anythingbun testexercises always run the current source. The caching issue only affects LLM-driven skill prose behavior dispatched through the plugin loader. Confirm a version-matched cache by content, not by version — seedocs/solutions/developer-experience/always-on-agents-md.md.
PR CI (.github/workflows/ci.yml) is the merge gate. It runs, in order: PR-title lint (PRs only), bun run release:validate, bun run plugin:validate, and bun run test. Do not invent a parallel local-only mechanical suite — if a check is deterministic and should block merges, put it in one of those steps (usually bun run test).
The test script is scripts/run-tests.ts: one bun test --parallel pass (implies --isolate), then, only if every first-pass failure is a TimeoutError, one serial re-run of those files in a fresh bun process. An assertion failure or error anywhere keeps the first result with no re-run. Do not add retry counts for this signature — a retry runs inside the same worker. A test file may not depend on another file's leftovers, and any test that writes outside its own mktemp directory is a latent flake. A test that runs a bundled script which inspects the repository must point that script at a throwaway repo, never this checkout. Do not pin a worker count. Size a test file by its measured time, not its line count. CI wall-time measurements and the per-file timing recipe: docs/solutions/developer-experience/always-on-agents-md.md. The TimeoutError re-run exists because bun can lose a child-exit inside a worker (oven-sh/bun#34069); details: docs/solutions/developer-experience/bun-parallel-worker-loses-subprocess-exit.md.
| Kind of check | Where it lives | Notes |
|---|---|---|
| Deterministic invariants (frontmatter, parity, path safety, script behavior, converter/writer output, greppable skill contracts) | bun test / release:validate / plugin:validate |
Must pass in CI |
| Skill prose behavior (routing judgment, restraint, cross-model peer outcomes) | Fresh-agent eval (on-disk skill injected), local / PR evidence | Not a CI job; non-deterministic and needs a model |
That split is intentional. See docs/solutions/skill-design/portable-agent-skill-authoring.md ("Evaluate proportionally"). Mechanical checks belong in CI; behavioral agent evals are best-effort evidence, not an exhaustive CI matrix.
When a review bot or human finds a greppable invariant that bun test missed:
- Prefer tightening an existing guard over adding a new suite (e.g. widen a regex that already documents the rule).
- Pin the smallest falsifiable unit — a token, enum, path, heading, or one fixture that would have failed on the regressing diff. Do not snapshot whole skill bodies or pin incidental wording.
- If the failure needs an LLM to judge, keep it as a behavioral eval; do not fake it as a brittle string test.
package.jsonplugin:validatemust validate both the marketplace catalog and the plugin manifest, with--stricton each. Paths:.claude-plugin/marketplace.jsonand.claude-plugin/plugin.json. Do not useclaude plugin validate .— that resolves this repo as a marketplace only (because.claude-plugin/marketplace.jsonexists withsource: "./") and skips plugin-root checks.- CI pins
@anthropic-ai/claude-codefor reproducible schema rules. Bump the pin deliberately when adopting new upstream rules; do not float@latest. - Root
CLAUDE.mdmust remain a symlink toAGENTS.md(path stays at the repo root where contributors expect it). Upstream warns on a regular-file plugin-rootCLAUDE.mdbecause it is not loaded as end-user project context; the symlink avoids that warning so--strictcan stay on. Do not replace the symlink with a regular@AGENTS.mdshim or relocate the file just for validators. - If
--strictstarts failing again onCLAUDE.mdafter an upstream bump, check whether the symlink was materialized into a regular file (Windows/core.symlinks=falsecheckouts) or whether the validator started following symlinks — fix the layout or pin, do not silently drop--strict.
If CI claims a deferred warning or a missing gate, reproduce with the pinned claude version against .claude-plugin/plugin.json before treating the comment as current. Marketplace-only validation can hide plugin warnings.
- Prefer explicit mappings over implicit magic when converting between platforms.
- Keep target-specific behavior in dedicated converters/writers instead of scattering conditionals across unrelated files.
- Preserve stable output paths and merge semantics for installed targets; do not casually change generated file locations.
- When adding or changing a target, update fixtures/tests alongside implementation rather than treating docs or examples as sufficient proof.
- Prefix is based on intent, not file type. Use conventional prefixes (
feat:,fix:,docs:,refactor:, etc.) but classify by what the change does, not the file extension. Files underskills/and plugin manifests are product code even though they are Markdown or JSON. Reservedocs:for files whose sole purpose is documentation (README.md,docs/,CHANGELOG.md). - Type selection — classify by intent, not diff shape. Where
fix:andfeat:could both seem to fit, default tofix:: a change that remedies broken or missing behavior isfix:even when implemented by adding code, and net additions do not turn a fix into afeat:. Reservefeat:for capabilities the user could not previously accomplish where nothing was broken. Other conventional types (chore:,refactor:,docs:,perf:,test:,ci:,build:,style:) remain primary when they describe the change more precisely than either. Heuristic: if a regression test you could write today would have failed before the change, it'sfix:. The user may override this default for a specific change. - Include a component scope. The scope appears verbatim in the changelog. Pick the narrowest useful label: skill/agent name (
document-review,learnings-researcher), CLI or marketplace area (cli,marketplace), or shared area when cross-cutting (review,research,converters). Never usecompound-engineering— it's the entire plugin and tells the reader nothing. Omit scope only when no single label adds clarity. - Never use
!or aBREAKING CHANGE:footer without explicit user confirmation. These markers trigger release-please's automatic major version bump — a decision the user may not want even when a change is technically breaking. If a change appears breaking, surface that to the user and let them decide whether to apply the marker.
When adding a --to / --also target provider, follow the checklist in docs/solutions/developer-experience/always-on-agents-md.md.
The compound-engineering plugin no longer ships standalone agent definitions under agents/. When a skill needs a specialist persona, store it inside that skill directory, usually under references/agents/ or references/personas/, and have the calling skill dispatch a generic subagent with that file's contents in the prompt.
Internal prompt asset file names should be descriptive and unprefixed because they are not externally exposed agent names.
Example:
references/agents/learnings-researcher.md(correct)references/agents/ce-learnings-researcher.md(wrong for an internal prompt asset)
These prompt assets must not include YAML frontmatter. Model selection, tool constraints, and dispatch policy belong in the calling skill's SKILL.md, not in the prompt asset.
Each skill directory is a self-contained unit. A SKILL.md file must only reference files within its own directory tree (e.g., references/, assets/, scripts/) using relative paths from the skill root. Never reference files outside the skill directory — whether by relative traversal or absolute path.
Broken patterns:
../other-skill/references/schema.yaml— relative traversal into a sibling skill/home/user/compound-engineering-plugin/skills/other-skill/file.md— absolute path to another skill~/.claude/plugins/cache/marketplace/compound-engineering/1.0.0/skills/other-skill/file.md— absolute path to an installed plugin location
Why this matters:
- Runtime resolution: Skills execute from the user's working directory, not the skill directory. Cross-directory paths and absolute paths will not resolve as expected.
- Unpredictable install paths: Plugins installed from the marketplace are cached at versioned paths. Absolute paths that worked in the source repo will not match the installed layout, and the version segment changes on every release.
- Converter portability: The CLI copies each skill directory as an isolated unit when converting to other agent platforms. Cross-directory references break because sibling directories are not included in the copy.
If two skills need the same supporting file, duplicate it into each skill's directory. Prefer small, self-contained reference files over shared dependencies.
Note (March 2026): This constraint reflects current Claude Code skill resolution behavior and known path-resolution bugs (#11011, #17741, #12541). If Anthropic introduces a shared-files mechanism or cross-skill imports in the future, this guidance should be revisited with supporting documentation.
Use the project's active instructions already in the main agent's context, then go directly to task-specific current evidence. Pass fresh subagents the relevant project and task context, or have them read the applicable current instruction source when operational rules affect their work. If a task cannot be scoped from that context, use one targeted probe. Do not create a reusable generic repo profile or run a default root, stack, or layout scan.
This plugin is authored once and converted for multiple agent platforms (Claude Code, Codex, Gemini CLI, etc.). Do not use platform-specific environment variables or string substitutions (e.g., ${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_SKILL_DIR}, ${CLAUDE_SESSION_ID}, CODEX_SANDBOX, CODEX_SESSION_ID) in skill content without a graceful fallback that works when the variable is unavailable or unresolved.
Read-time references stay relative to the skill root. Executed bundled scripts use the model-filled SKILL_DIR anchor with a trailing ; on the assignment line:
SKILL_DIR="<absolute path of the directory containing the SKILL.md you just read>";
bash "$SKILL_DIR/scripts/my-script.sh" ARG
Keep the ;. Avoid ${CLAUDE_SKILL_DIR} in this cross-host plugin. Do not use ! load-time pre-resolution in skills (tests/skill-shell-safety.test.ts). Gather context at runtime with one argv-style command per shell tool call. Tier details, flatten-safety, and the permission caveat: docs/solutions/developer-experience/always-on-agents-md.md.
- Guides live in
docs/guides/— the user-facing skill catalog and configuration reference. Keep them here, not underskills/, so they do not ship inside the plugin package. - Plans live in
docs/plans/— unified plan artifacts. Newce-brainstormoutputs are requirements-only unified plans;ce-planadds implementation planning in place. Consumers assess contents and unresolved blockers rather than a readiness field. Historicaldocs/brainstorms/*-requirements.*files remain readable legacy inputs and should not be migrated just because a new plan is created. - Brainstorm evidence / legacy requirements may live in
docs/brainstorms/— historical requirements docs and specialized analysis artifacts such asdocs/brainstorms/riffrec-feedback/. Do not treat this as the canonical output path for newce-brainstormartifacts. - Solutions live in
docs/solutions/— documented solutions to past problems (bugs, best practices, workflow patterns), organized by category with YAML frontmatter (module,tags,problem_type). Relevant when implementing or debugging in documented areas. - Specs live in
docs/specs/— target platform format specifications.
This repo builds a plugin for developers. Categorize solutions from the perspective of the end user (a developer using the plugin), not a contributor to this repo.
developer-experience/— Issues with contributing to this repo: local dev setup, shell aliases, test ergonomics, CI friction. If the fix only matters to someone with a checkout of this repo, it belongs here.integrations/— Issues where plugin output doesn't work correctly on a target platform or OS. Cross-platform bugs, target writer output problems, and converter compatibility issues go here.workflow/,skill-design/— Plugin skill and agent design patterns, workflow improvements.
When in doubt: if the bug affects someone running bun install compound-engineering or bun convert, it's an integration or product issue, not developer-experience.