-
Notifications
You must be signed in to change notification settings - Fork 0
system prompt
Status: proposed, not yet implemented. This guide documents the target design from
docs/research/cross-harness-identity-and-rules.md— written before the code, as a way to sanity-check the design by describing it the way a user would experience it. Nothing below works today. See that spec for the research this is based on, anddocs/research/harness-rules-directory-support.mdfor the per-harness native-support findings.
Everything in this guide serves one rule: your conversations, usage, and stats must persist and
stay coherent no matter which stack (tool configuration) you ran — switching from
claude_dev-core to claude_dev-methodology shouldn't fragment your Claude history into two
silos, because both mount the same host history, keyed by project path, not by stack name. The
same idea makes team-shared configurations possible: a stack (its recipes, rules, and the
instructions: file this guide introduces) is the shareable, version-controlled unit a team
standardizes on — your auth and history stay strictly personal and host-linked, never baked into
that shared config. instructions:/rules: isolate what tools and identity this stack gives the
agent; they never touch where your conversations live.
If you're authoring a stack, watch for
state.session_state: volume. It's a valid sibling of the defaulthostin the schema, but it does the opposite of everything above — it isolates session state per-stack instead of sharing your host history. Fine if you deliberately want a throwaway, non-continuous stack; a real footgun if it ends up in a team-shared config by accident (e.g. copy-pasted from an example). See the stacks guide for the full field.
Two different things get configured here, owned by two different authors:
- Identity — "what is this assembled agent, as a whole." One per stack, written once by whoever builds the stack. This is CLAUDE.md's role today; the goal is the same thing for every harness.
-
Rules — topic-scoped, composable instructions. Contributed by whichever recipes are in the
stack, N per stack. Already shipped as the
rules:recipe field — this guide extends it to more harnesses, it doesn't replace it.
flowchart TD
subgraph recipes["Recipes in the stack"]
R1["beads recipe<br>rules/bd-usage.md"]
R2["superpowers recipe<br>rules/workflow.md"]
end
subgraph stack["Stack author"]
SI["stack.yaml<br>instructions: identity.md"]
end
R1 --> Compose["Composed rules<br>.claude/rules/*.md"]
R2 --> Compose
SI --> Identity["Stack identity<br>.claude/CLAUDE.md"]
Compose --> Build["harnessed build"]
Identity --> Build
Build --> Derived["Per-harness derived files<br>(one path per target harness)"]
classDef recipe fill:#dfe6e9,stroke:#636e72
classDef stack fill:#d4edda,stroke:#28a745
class R1,R2,Compose recipe
class SI,Identity stack
Trying to solve both with one mechanism is what caused the original design confusion — "just append everything to CLAUDE.md" breaks down the moment two recipes want to append to it. Rules compose (fail-fast on name collision); identity doesn't — it's one file, one owner.
A new instructions: field on the stack manifest, pointing at one markdown file relative to the
stack's own directory:
# catalog/stacks/claude_superpowers/stack.yaml
name: claude_superpowers
harness: claude
recipes: [superpowers]
instructions: identity.md<!-- catalog/stacks/claude_superpowers/identity.md -->
You are a focused pair-programmer for this repo. Prefer small, reviewable diffs. Always run the
test suite before declaring a task done. When in doubt about scope, ask rather than guess.This is deliberately a single file, not a list — identity isn't composable the way rules are. If
you need different identities for different harnesses of the "same" stack, author separate stack
manifests (claude_myproject, omp_myproject, ...) each with their own instructions:.
Unchanged in shape from today's rules: field — a recipe ships flat .md files, each one a
composable topic:
# catalog/recipes/beads/recipe.yaml
rules:
- {path: rules/bd-usage.md}(This guide also covers the fix to how these fan out — see Known limitations below for the flat-file correction.)
Not every harness has a literal "modify the system prompt" primitive. Where one exists that adds to the default behavior, it's used directly. Where the only option replaces the harness's built-in behavior wholesale, that's treated as an opt-in escape hatch, not the default — the same caution a stack author should apply themselves before reaching for it.
flowchart LR
Start{"Does the harness have a<br>system-prompt hook?"}
Start -->|"No hook exists"| Fallback["Append into the harness's<br>own global instructions file"]
Start -->|"Yes — additive"| Additive["Use it directly"]
Start -->|"Yes — but full-replace"| Replace["Opt-in escape hatch only,<br>not the default target"]
Fallback --> Claude["claude → .claude/CLAUDE.md<br>(the only surface it has)"]
Fallback --> CodexD["codex → ~/.codex/AGENTS.md<br>(default)"]
Additive --> Omp["omp → ~/.omp/agent/APPEND_SYSTEM.md<br>(guarded, shared host file)"]
Replace --> CodexR["codex → model_instructions_file<br>(only if explicitly requested)"]
Start -->|"Requires a launch-time change"| OC["opencode → custom agent + --agent flag"]
Start -->|"Bake alongside existing MCP config"| AG["antigravity → gemini.md / settings.json"]
classDef additive fill:#d4edda,stroke:#28a745
classDef caution fill:#fff3cd,stroke:#ffc107
classDef fallback fill:#dfe6e9,stroke:#636e72
class Additive,Omp additive
class Replace,CodexR caution
class Fallback,Claude,CodexD,OC,AG fallback
| Harness | Identity target | Rules target | Notes |
|---|---|---|---|
| claude | .claude/CLAUDE.md |
.claude/rules/*.md (native, conditional via paths:) |
The reference implementation — everything else approximates this |
| omp |
~/.omp/agent/APPEND_SYSTEM.md (guarded append) |
~/.omp/agent/RULES.md (guarded append) |
Shared across every omp stack on this host, not stack-scoped — see limitations |
| codex |
~/.codex/AGENTS.md (default) |
Same file, concatenated in |
model_instructions_file available but not default (full-replace) |
| opencode | Custom agent in opencode.json, launched via --agent <name>
|
instructions: glob at an absolute container path |
Confirmed safe — a custom agent with only a prompt field inherits default permissions |
| antigravity |
gemini.md / settings.json's context.fileName
|
.agents/rules/*.md (native, flat files) |
Baked alongside the existing mcp_config.json, same mechanism |
Everything except omp's guarded append happens at harnessed build — generated once, written into
the stack's profile, no container involved yet:
sequenceDiagram
participant Author as Stack author
participant CLI as harnessed build
participant Assembler
participant Profile as Profile dir (host, per-stack)
Author->>CLI: harnessed build my-stack
CLI->>Assembler: load stack.yaml + every recipe
Assembler->>Assembler: fan recipe rules -> .claude/rules/*.md
Assembler->>Assembler: render stack instructions -> .claude/CLAUDE.md
alt harness is codex
Assembler->>Profile: write ~/.codex/AGENTS.md (identity + concatenated rules)
else harness is opencode
Assembler->>Profile: merge a custom agent into opencode.json
else harness is antigravity
Assembler->>Profile: bake settings.json + a flat identity.md
end
Assembler->>Profile: write the rest of the profile tree
CLI-->>Author: build complete
omp's target files (~/.omp/agent/{APPEND_SYSTEM,RULES}.md) aren't profile-scoped — they're the
real host directory, shared with your native host omp and every other omp-harness stack
(_omp_agent_mount). Writing them can't happen at build time into a per-stack profile; it happens
at launch, directly on the host, guarded so repeated launches don't duplicate content:
sequenceDiagram
participant User
participant CLI as harnessed <stack>
participant Host as Host filesystem (~/.omp/agent/)
participant Container
User->>CLI: harnessed my-omp-stack
alt harness is omp
CLI->>Host: check for this stack's delimiter block
alt block already present
CLI->>Host: no-op
else block missing or stale
CLI->>Host: write/replace the block, markers intact
end
Note right of Host: <!-- harnessed:stack:my-omp-stack --><br/>...content...<br/><!-- /harnessed -->
end
CLI->>Container: mount the profile's .claude/, compose the pod
Container-->>User: attach
These are accepted tradeoffs, not bugs to file later:
-
No conditional rule loading outside Claude. Claude Code rules can carry
paths:frontmatter to load only when a matching file enters context. Every other harness gets the concatenated rules always-on — a rule scoped to*.pyfiles becomes globally active forcodex/omp/etc. This is a deliberate, permanent limitation. -
omp's identity/rules are host-shared, not per-stack. Multiple omp-harness stacks (and your
native host omp) all read the same
~/.omp/agent/{APPEND_SYSTEM,RULES}.md. The guarded-append markers keep different stacks' blocks from clobbering each other, but the content still lives in one shared file — there's no container-level isolation the way.claude/CLAUDE.mdhas. -
Codex has a 32 KiB instruction budget (
project_doc_max_bytes), shared between identity and concatenated rules if both land inAGENTS.md. A stack with a long identity file and many recipe-contributed rules can silently truncate — files closer to the cap get cut, not warned about. -
The Claude Code
rules:fan-out had a real bug this design also fixes: rules are flat.mdfiles (.claude/rules/<name>.md), not one directory per rule — the originalrules:implementation copy-pasted theskills:directory-fan pattern without checking the shape. Fixed as part of landing this design, independent of everything else here.
Starting from the existing claude_superpowers stack, adding an identity file and a second
harness:
# catalog/stacks/claude_superpowers/stack.yaml — unchanged shape, one new field
name: claude_superpowers
harness: claude
recipes: [superpowers]
instructions: identity.md# catalog/stacks/omp_superpowers/stack.yaml — same identity content, different harness
name: omp_superpowers
harness: omp
recipes: [superpowers]
instructions: identity.mdBuilding both:
harnessed build claude_superpowers # writes .claude/CLAUDE.md into this stack's profile
harnessed build omp_superpowers # writes .claude/CLAUDE.md into this stack's profile too
harnessed omp_superpowers # LAUNCH TIME: guarded-appends identity.md's content into
# ~/.omp/agent/APPEND_SYSTEM.md, then attachesNote the asymmetry: claude_superpowers's identity is fully self-contained in its own profile.
omp_superpowers's identity only actually reaches the agent at launch, and lands in a file
shared with every other omp stack you run — that's the tradeoff called out above, made concrete.
-
docs/research/cross-harness-identity-and-rules.md— the full design spec, including the research this guide simplifies for a user-facing audience. -
docs/research/harness-rules-directory-support.md— per-harness native rules-directory research. -
Recipe-authoring guide — the
rules:field, recipe-side. -
Stacks guide — the
stack.yamlschema this addsinstructions:to.
Start Here
Guides
- Recipe authoring
- Service authoring
- Stacks
- Extending stacks (proposed)
- Recipe catalog
- System prompt & rules (proposed)
- Secrets
- AWS SSO
- Pulumi (host login forwarding)
- Egress & exposing services
- Container filesystem
- Git hooks
- Troubleshooting
- Pin management (harnessed update)
Codebase Map
Planning & Roadmap
- open work: GitHub Issues
Research & Prompts
- research/ (home-folder requirements per harness, browse in-repo)
- prompts/ (reusable prompt templates, browse in-repo)