forge install deploys rules/*.md into every provider's directory (~/.claude/rules/, ~/.codex/rules/, ~/.gemini/rules/, ~/.opencode/rules/), but only Claude Code reads a rules/ directory natively. The other three harnesses never load the deployed files, so every rule silently applies to Claude only.
Observed
Probing each harness with "quote a loaded rule about X, else print NOT LOADED" (rule deployed to all four providers):
- Claude Code: rule quoted (native
~/.claude/rules/ loading)
- codex:
NOT LOADED — codex reads only $CODEX_HOME/AGENTS.md; nothing references rules/
- opencode:
NOT LOADED — opencode reads global AGENTS.md and the instructions array in opencode.json; neither mentions rules/
- gemini: no
~/.gemini/GEMINI.md exists at all, so ~/.gemini/rules/ is inert
Expected
Install wires loading per provider, using each harness's own mechanism:
- codex: maintain a marker-delimited generated block in
~/.codex/AGENTS.md that inlines rule content. Codex has no import directive (config schema offers only model_instructions_file, which replaces rather than extends).
- gemini: maintain
~/.gemini/GEMINI.md with rule content inlined. gemini-cli supports absolute-path @ imports (import docs), but Antigravity (agy) reads GEMINI.md literally, so inlining is the portable form. Caveat: headless agy -p currently loads no file-based context at all (verified with sentinel files, workspace and global, trusted and untrusted); its "Global rules" appear to be an app-internal store. GEMINI.md wiring covers gemini-cli and any future agy support; the agy gap is upstream.
- opencode: ensure the global
opencode.json instructions array contains the rules glob (globs supported, rules docs).
Idempotency matters: the codex and gemini blocks must be regenerated on every install (marker-delimited replace), or rule changes deploy without taking effect, which is the current failure mode in a subtler form.
Workaround
forge-provision now carries scripts/configure/harness-rules.sh regenerating the codex and gemini blocks from the deployed rules; opencode is wired via the chezmoi-managed instructions key. Both belong in forge install proper so the wiring travels with the deploy instead of a per-machine configure step.
forge installdeploysrules/*.mdinto every provider's directory (~/.claude/rules/,~/.codex/rules/,~/.gemini/rules/,~/.opencode/rules/), but only Claude Code reads arules/directory natively. The other three harnesses never load the deployed files, so every rule silently applies to Claude only.Observed
Probing each harness with "quote a loaded rule about X, else print NOT LOADED" (rule deployed to all four providers):
~/.claude/rules/loading)NOT LOADED— codex reads only$CODEX_HOME/AGENTS.md; nothing referencesrules/NOT LOADED— opencode reads globalAGENTS.mdand theinstructionsarray inopencode.json; neither mentionsrules/~/.gemini/GEMINI.mdexists at all, so~/.gemini/rules/is inertExpected
Install wires loading per provider, using each harness's own mechanism:
~/.codex/AGENTS.mdthat inlines rule content. Codex has no import directive (config schema offers onlymodel_instructions_file, which replaces rather than extends).~/.gemini/GEMINI.mdwith rule content inlined. gemini-cli supports absolute-path@imports (import docs), but Antigravity (agy) reads GEMINI.md literally, so inlining is the portable form. Caveat: headlessagy -pcurrently loads no file-based context at all (verified with sentinel files, workspace and global, trusted and untrusted); its "Global rules" appear to be an app-internal store. GEMINI.md wiring covers gemini-cli and any future agy support; the agy gap is upstream.opencode.jsoninstructionsarray contains the rules glob (globs supported, rules docs).Idempotency matters: the codex and gemini blocks must be regenerated on every install (marker-delimited replace), or rule changes deploy without taking effect, which is the current failure mode in a subtler form.
Workaround
forge-provision now carries
scripts/configure/harness-rules.shregenerating the codex and gemini blocks from the deployed rules; opencode is wired via the chezmoi-managedinstructionskey. Both belong inforge installproper so the wiring travels with the deploy instead of a per-machine configure step.