Claude Code / Codex / other agents -- determine your context before proceeding:
Source repo test: If
bootstrap/bootstrap.sh,bootstrap/bootstrap.ps1, andskills/all exist at the repo root, you are in theanywhere-agentssource repo (or a fork with the same layout). Skip the bootstrap block below and proceed directly to## Session Start Check. Do not execute the bootstrap script in the source repo; it would try to bootstrap itself.Consumer repo path: Otherwise, you are in a project that consumes the shared config. You MUST execute the matching bootstrap block below at the start of every session, before responding to any user request or running session checks. Use the PowerShell block on Windows and the Bash block on macOS/Linux. Bootstrap is idempotent: run it every session even if
.agent-config/already exists, so shared config, skills, and settings are refreshed from upstream before any work begins. Do not treat the block below as reference documentation -- it is a required runtime command. After running, report the refresh result in one line (for example, "bootstrap: refreshed AGENTS.md, skills, settings").
This file is the shared agent configuration hosted at https://github.com/yzhao062/anywhere-agents.
Project repos should include the following bootstrap block in their own AGENTS.md so that agents automatically pull the latest shared defaults and skills before starting any task. Because bootstrap rewrites the consumer's root AGENTS.md from this source on every run, the block below ends up serving two roles in consumer repos: it is both the embedded reference for how the setup works and the runtime command the agent executes each session (see the top-of-file note for the source-vs-consumer test that decides which role applies in the current repo).
Copy the block below into the top of each project repo's AGENTS.md. Because bootstrap rewrites AGENTS.md on every run, put project-local overrides in AGENTS.local.md.
## Shared Agent Config (auto-fetched)
Before starting any task, fetch the shared agent configuration and skills. Use the block for your shell.
PowerShell (Windows):
```powershell
New-Item -ItemType Directory -Force -Path .agent-config, .claude, .claude/commands | Out-Null
Invoke-WebRequest -UseBasicParsing -Uri https://raw.githubusercontent.com/yzhao062/anywhere-agents/main/bootstrap/bootstrap.ps1 -OutFile .agent-config/bootstrap.ps1
& .\.agent-config\bootstrap.ps1
```
Bash (macOS/Linux):
```bash
mkdir -p .agent-config .claude/commands
curl -sfL https://raw.githubusercontent.com/yzhao062/anywhere-agents/main/bootstrap/bootstrap.sh -o .agent-config/bootstrap.sh
bash .agent-config/bootstrap.sh
```
This bootstrap flow rewrites the consuming repo's root `AGENTS.md` on every run. By default it composes the shared upstream copy with the `agent-style` rule pack, which needs Python 3 and PyYAML. Bootstrap attempts a best-effort `pip install --user pyyaml` when PyYAML is missing. With composition disabled (`rule_packs: []` in `agent-config.yaml`), the root `AGENTS.md` is written verbatim from the shared upstream copy. One case leaves the file alone: if packs are configured but composition cannot run, an existing composed `AGENTS.md` is preserved rather than replaced by the bare shared copy. That run warns on stderr and records `completed: false`. If a project later needs repo-local overrides, put them in `AGENTS.local.md`.
Read and follow the rules in `.agent-config/AGENTS.md` as baseline defaults. Any rule in `AGENTS.local.md` overrides the shared default.
When a skill is invoked, resolve its `SKILL.md` using this order, first hit wins: `skills/<skill-name>/SKILL.md` (project-local), then `.claude/skills/<skill-name>/SKILL.md` (pack-deployed by `anywhere-agents pack install`; `.claude/` prefix is a historical Claude Code convention but the contents are agent-agnostic), then `.agent-config/repo/skills/<skill-name>/SKILL.md` (bootstrapped from upstream).
Copying `.agent-config/repo/.claude/commands/*.md` only overwrites command files with the same name as the shared repo and does not delete unrelated project-local commands.
Merge shared Claude project defaults (e.g., `permissions`, `attribution`) from `.agent-config/repo/.claude/settings.json` into the project `.claude/settings.json`. Shared keys are updated on every bootstrap run; project-only keys are preserved. The merge runs `scripts/merge_settings.py`, so the Bash entry point needs Python and leaves the file untouched without it. The PowerShell entry point falls back to an in-script merge.
Add `.agent-config/` and `agent-config.local.yaml` to the project's `.gitignore` so fetched files and machine-local overrides are not committed. The three generated files, `AGENTS.md`, `CLAUDE.md` and `agents/codex.md`, are added as well. Their bytes depend on which packs this machine resolved and on whether composition ran, so two machines that are both current produce different content and each sees the other's as a diff to commit. A repo that already tracks one of them is left alone, because `.gitignore` does not untrack a path git already follows; moving it out of the index is an operator decision, since the resulting commit removes the file for every other clone. Set `AGENT_CONFIG_TRACK_GENERATED` to keep all three out of `.gitignore`.
Bootstrap also sets up user-level config: it copies `scripts/guard.py` to `~/.claude/hooks/` (a PreToolUse hook that guards against destructive commands) and `scripts/statusline.py` to `~/.claude/statusline.py` (a statusLine renderer showing Claude Max + Codex 5h / weekly quota), and merges `user/settings.json` into `~/.claude/settings.json` (shared permissions, hook wiring, statusLine command, and the `CLAUDE_CODE_EFFORT_LEVEL=max` env entry that sets the default effort level). Remove the user-level section from the bootstrap script if this is not wanted.
Every run also writes `.agent-config/last-run.json`, a machine-readable record of the phases this bootstrap completed and the files each one wrote; `completed: false` means the run stopped early, and `last_phase` names where. It covers the bootstrap script only, not the wheel-side `pack verify` heal pass, which is recorded in `.agent-config/pack-lock.json`.
| Content | Source | How fetched |
|---|---|---|
| User profile, writing defaults, formatting rules, environment notes | AGENTS.md (this file) |
curl raw file |
Per-agent rule files (CLAUDE.md, agents/codex.md) |
Generated from AGENTS.md by scripts/generate_agent_configs.py |
Regenerated locally on every bootstrap; hand-authored files preserved + warned |
Shared skills (implement-review, my-router, ci-mockup-figure, prun, readme-polish) |
skills/ directory (committed only) |
sparse git clone |
| Claude pointer commands for shared skills | .claude/commands/ |
sparse git clone plus non-destructive copy into the project .claude/commands/ |
Claude project defaults (permissions, attribution, etc.) |
.claude/settings.json |
sparse git clone plus key-level merge into the project .claude/settings.json on every run |
User-level scripts (guard.py, session_bootstrap.py, statusline.py) + settings |
scripts/ + user/settings.json |
Hooks copied to ~/.claude/hooks/, statusline to ~/.claude/statusline.py; settings merged into ~/.claude/settings.json (shared permissions, PreToolUse guard, SessionStart bootstrap hook, statusLine command, CLAUDE_CODE_EFFORT_LEVEL=max) |
- If
AGENTS.local.mdexists in the project root, read and follow it afterAGENTS.md. Rules inAGENTS.local.mdoverride the shared defaults. - Rules in
AGENTS.local.mdalways win over shared defaults. Do not edit the rootAGENTS.mdfor local overrides, as bootstrap will overwrite it. - Project-local
skills/<name>/SKILL.mdalways wins over pack-deployed and bootstrapped copies of the same skill. - Shared keys in
.claude/settings.jsonare updated on every bootstrap run. Project-only keys are preserved. To override a shared key locally, use.claude/settings.local.json. - If no project-local copy exists, use
.claude/skills/<name>/SKILL.mdwhen present; otherwise use the fetched shared copy from.agent-config/repo/skills/.
Three independent configuration layers, each with its own precedence rules. When two rules conflict, the more specific source wins.
1. Agent rule files (Markdown) — most specific wins:
| Layer | File | Scope |
|---|---|---|
| 1 | CLAUDE.local.md / agents/codex.local.md |
Per-agent + project-local. Hand-authored; never touched by bootstrap. |
| 2 | AGENTS.local.md |
Cross-agent + project-local. Hand-authored; never touched by bootstrap. |
| 3 | CLAUDE.md / agents/codex.md |
Per-agent, generated from AGENTS.md by scripts/generate_agent_configs.py. |
| 4 | AGENTS.md |
Cross-agent, synced from upstream on every bootstrap. |
The generated CLAUDE.md and agents/codex.md carry a GENERATED FILE header. If a consumer project has a hand-authored CLAUDE.md (or agents/codex.md) without that header, the generator preserves it and warns loudly — it never silently overrides user work. To adopt upstream rules in that case, rename the hand-authored file to CLAUDE.local.md (which still wins via layer 1).
2. Claude Code settings (settings.json) — follow Claude Code's own precedence: managed policy > command-line arguments > .claude/settings.local.json > .claude/settings.json > ~/.claude/settings.json. Bootstrap only writes to the project-shared and user-level layers, and merges shared keys while preserving project-only keys.
3. Environment variables — for effort level specifically: managed policy > CLAUDE_CODE_EFFORT_LEVEL env var > persisted effortLevel > default.
Bootstrap maintains this layout on every run, so a new project inherits it on its first session rather than by copying files from an older one.
| Path | State | Who writes it |
|---|---|---|
AGENTS.md, CLAUDE.md, agents/codex.md |
untracked, gitignored | regenerated by bootstrap every run |
AGENTS.local.md, CLAUDE.local.md, agents/codex.local.md |
tracked | hand-authored; bootstrap never touches them |
agent-config.yaml |
tracked | the project's pack selection |
agent-config.local.yaml |
untracked, gitignored | machine-local override |
.agent-config/ |
untracked, gitignored | fetched upstream copy |
todo/README.md |
tracked | seeded by bootstrap when absent |
todo/ contents |
untracked, gitignored | whatever a person drops in |
Three of these are worth stating as rules rather than as a table row.
The three generated files are not tracked. Their bytes depend on which packs the
machine resolved and on whether composition ran, so two machines that are both current
produce different content and each sees the other's as a diff to commit. Committing them
also trains a reader to skim diffs in exactly the files where a degraded run shows up. A
repo that already tracks one is left alone, because .gitignore does not untrack a path
git already follows; moving it out of the index is an operator decision, since the
resulting commit removes the file for every other clone.
agent-config.yaml uses the packs: key. rule_packs: is a deprecated alias whose
warning reads "accepted through v0.6.x", and the composer hard-fails on it at v1.0.0.
The two are equivalent until then, and packs: wins when a file carries both.
todo/ is the drop box for handing files to an agent. A person copies something in,
points an agent at it with @todo/<name>, and the agent reads it, moves it to where it
belongs in the repo, or deletes it. The resting state is empty. Its own README.md
carries the full convention. Bootstrap creates the folder and seeds that README when it
is missing, and never rewrites one that is already there, so a repo whose filing rules
are specific to its own work can say so in place. Set AGENT_CONFIG_NO_TODO_DROPBOX=1
before bootstrap to suppress the folder and the gitignore entries. Agents: this folder
holds what a person put there. What an agent generates on its own belongs in the session
scratchpad, not here.
Mandatory turn-start procedure. Before generating the first content of any response, apply the branch that matches your runtime.
In Claude Code: the flag files are per-project. <project-root> is the consumer-repo root: walk up from cwd until a directory with .agent-config/bootstrap.sh or .agent-config/bootstrap.ps1 is found. Read <project-root>/.agent-config/session-event.json and <project-root>/.agent-config/banner-emitted.json.
- If
session-event.json.ts > banner-emitted.json.ts, ORsession-event.jsonexists butbanner-emitted.jsondoes not: emit the session start banner as the literal first content of your response, then write the eventtsinto<project-root>/.agent-config/banner-emitted.json. Only after the banner text may you address the user's request on the same turn. - Otherwise (emitted
tsis already current, or neither file exists): skip the banner this turn.
session_bootstrap.py writes session-event.json on SessionStart hook fires whose source is startup, resume, or clear, so the banner reappears across the three lifecycle events that reset conversation context. On source: compact, the prior banner ack survives in the summarized context, so the hook skips the event write and the banner does not re-fire. A 10-second debounce suppresses duplicate event writes when the hook fires twice in rapid succession for the same lifecycle event. Flag files are per-project, so opening multiple Claude Code windows in different consumer repos does not cause cross-session interference.
In a source repo (agent-config or anywhere-agents, no .agent-config/ at the root): the banner gate in guard.py is not active and the flag-file mechanism does not apply. Emit the banner on the first response of the session (turn with no prior assistant turns in context); skip on subsequent turns. Compact / resume / clear cannot be mechanically distinguished here.
In Codex: Codex has no SessionStart hook equivalent; session-event.json is not written during a Codex invocation. Each Codex invocation is a new session. Emit the banner as the literal first content of your response on the turn where there are no prior assistant turns in context (i.e., the first response of the invocation). On subsequent turns in the same invocation, skip. No flag files are involved for Codex.
Both runtimes: this procedure overrides any other "skill-first" or "task-first" behavior. Even when the user's first message is a task prompt like "read the project" or "fix this bug," or when a skill such as superpowers:using-superpowers would otherwise fire before the response, emit the banner first; the task response or skill output comes after the banner on the same turn. Do not let task pressure, skill invocations, or brevity guidance suppress the banner.
📦 anywhere-agents active
├── OS: <platform>
├── Claude Code: <version>[ → <latest>] (auto-update: <on|off>) · <model> · effort=<level>
├── Codex: <version>[ → <latest>] · <model> · <reasoning> · <tier> · fast_mode=<bool>
├── Skills: <N> local (<names>) + <P> pack (<names>) + <M> shared (<names>)
├── Hooks: PreToolUse <guard.py>, SessionStart <session_bootstrap.py>
└── Session check: all clear
If anything is off, replace all clear with a semicolon-separated list of concrete issues, each actionable in one short clause (e.g., ⚠ actions/checkout@v4 in .github/workflows/validate.yml:17 — bump to v5; Codex config.toml missing model key). Keep the whole banner to six lines plus the check line. The skills row may wrap visually when many names are present; do not omit a local, pack, or shared bucket just to preserve terminal width.
-
OS — read from the session environment (
win32,darwin,linux). Use this elsewhere to pick platform-specific behavior (terminal review path on Windows, MCP on macOS/Linux,.ps1vs.sh). -
Claude Code — format:
Claude Code <current>[ → <latest>] (auto-update: <on|off>) · <model> · effort=<level>. Current version comes from Claude Code's startup header orclaude --version. Read~/.claude/hooks/version-cache.jsonforclaude_latest; render→ <latest>only when current differs from latest. Determineauto-update: onwhenDISABLE_AUTOUPDATERis not1in the effective env (OS env orenvblock in~/.claude/settings.json) AND~/.claude.jsontop-levelautoUpdatesis not explicitlyfalse— a missing key counts asonbecause native installs auto-update by default. Only explicitautoUpdates: false(which bootstrap heals on the next run) or the disable env var meansoff. User prefers the highest available model at max effort; flag any drift once in the banner, not every turn. -
Codex — format:
Codex <current>[ → <latest>] · <model> · <reasoning> · <tier> · fast_mode=<bool>. Current version fromcodex --version. Latest from~/.claude/hooks/version-cache.jsoncodex_latest(render→ <latest>only when current differs). Config from~/.codex/config.toml(or%USERPROFILE%\.codex\config.tomlon Windows):model·model_reasoning_effort·service_tier·[features].fast_mode. Expected policy (intent, not a frozen pin): the highest-capability generally available Codex model for the account, currentlygpt-5.6-sol, where a newer successor is equally valid;model_reasoning_effort = "max"for maximum single-agent reasoning;ultrais an opt-in mode (GPT-5.6 Sol and Terra only) that keeps maximum reasoning and additionally enables automatic task delegation, so it is not simply "more effort";service_tier = "fast"with[features] fast_mode = trueas the intended default (latency is the scarce resource and the account absorbs the 2.5x rate), withstandard(or the key omitted) an equally valid dial-down for a big task. Report the tier as rendered and do NOT flag eitherfastorstandardas drift; the banner already shows<tier>andfast_mode=<bool>every session, which is the whole reminder needed. GPT-5.6 requires Codex CLI 0.144.0 or newer: 0.142.5 and 0.143.0 return an upgrade-required HTTP400. Flag an old CLI paired with a 5.6 model as an actionable issue. If the binary is not on PATH, showCodex: not installed. If the binary exists butconfig.tomlis missing, show version +not configuredin place of the config summary. -
Skills — list all active skill buckets. Count directories under
skills/(project-local),.claude/skills/(pack-deployed byanywhere-agents pack install), and.agent-config/repo/skills/(bootstrapped from upstream). Apply the lookup precedence from "Local Skills Precedence" when counting: exclude pack-deployed names that are shadowed by a project-local skill, and exclude bootstrapped names that are shadowed by either a project-local or a pack-deployed skill. Format:<N> local (<names>) + <P> pack (<names>) + <M> shared (<names>). Omit empty buckets (e.g.,2 pack (...) + 4 shared (...)when the consumer has no project-local skills, or4 shared (...)when only the bootstrapped bucket is non-empty). -
Hooks — check
~/.claude/hooks/forguard.py(PreToolUse) andsession_bootstrap.py(SessionStart). If one is missing, include it in the Session check line as an issue. -
Session check — scan
.github/workflows/*.ymlfor action version pins below the minimums in the GitHub Actions Standards section. Combine with any Codex-config or hook drift detected above. Emitall clearonly when nothing needs attention. -
Pack deployment — compute two counts:
a. user_packs: read
%APPDATA%\anywhere-agents\config.yaml(Windows) or$XDG_CONFIG_HOME/anywhere-agents/config.yaml/~/.config/anywhere-agents/config.yaml(POSIX); empty list if absent.AGENT_CONFIG_PACKSenv var is excluded.b. project_packs: read
agent-config.yamlthen mergeagent-config.local.yamlby name; if both are absent, use an empty list. Local entries win on duplicates.c. gap_count: for each
uin user_packs, normalize(name, normalize_pack_source_url(url), ref). Increment if no matchingpin project_packs by case-sensitive name, OR ifp's normalized tuple differs fromu's.d. update_count: for each entry in
.agent-config/pack-lock.jsondata.packs, increment when bothlatest_known_headandresolved_commitare non-empty AND they differ. (Lock entries predating v0.5.2 lack these fields and contribute zero.)e. emit: each non-zero count contributes a half-clause to the Session check line (semicolon-separated;
all clearwhen both zero):- gap_count > 0 →
⚠ <gap_count> user-level pack(s) not deployed (run `anywhere-agents pack verify --fix`) - update_count > 0 →
ℹ <update_count> pack update(s) available (run `anywhere-agents pack verify --fix`)
- gap_count > 0 →
- These are user-level defaults that can be reused across projects unless a local repo rule or task-specific instruction is stricter.
- Customize this section in your fork of
anywhere-agentsto describe your role, domain, and common task types. Agents read this to tailor their work (e.g., a researcher vs. a backend engineer vs. a data scientist will get different defaults). - If your fork serves multiple use cases, keep the description general ("developer working on infrastructure and research tooling") rather than overspecifying.
- Claude Code is the primary workhorse: drafting, implementation, research, and heavy-lifting tasks.
- Codex is the gatekeeper: review, feedback, and quality checks on work produced by Claude Code or the user.
- When both agents are available, default to this division of labor unless the user overrides it.
- The default routing (Claude Code primary, Codex gatekeeper) is a default, not a hard requirement. Two scenarios must remain workable: (1) absence, when one agent is unavailable (service outage, regional block, quota exhaustion, hardware-induced refusal); (2) reversal testing, when the user deliberately swaps primary and gatekeeper roles to evaluate quality drift.
- Principle: not 1:1 replication. Core functions must work when either agent is absent or when roles are reversed. Where an ergonomic helper exists for one agent only (e.g., a hand-crafted slash command), the function must still be reachable via underlying primitives. Define "core function" by user value (review loop, structured dispatch, health check), not by surface convenience.
- How to apply when designing or refactoring agent-facing skills, scripts, or docs:
- Default routing is fine; just make the alternative reachable.
- A skill, hook, or script that hard-codes one agent's CLI (
codex exec,claude -p) should document or wire the other side's equivalent at the same time, even if the implementation is deferred. - Docs that name one agent in step instructions should call out the cross-vendor equivalent at least once near the top, so a session reading the doc under role reversal can still proceed.
- When the deferred half ships later, the principle is satisfied; do not block the primary half on simultaneous parity.
- This configuration targets multi-agent use (Claude Code, Codex, and others). A single agent's private memory is therefore not a reliable home for durable context: one agent's per-account memory is not readable by the other agents, and it does not travel across accounts or machines.
- Prefer version-controlled local files for anything that must persist across agents, sessions, accounts, or machines: the project
README, adocs/note, aPLAN-*.mdor notes file, aCHANGELOG, orAGENTS.local.md. Version control is the portable, agent-independent memory. - Use an agent's built-in memory only for short, agent-local convenience, and treat the version-controlled copy as authoritative. Do not record project state, decisions, or records solely in agent memory.
- Before starting a task, read the router skill to determine which domain skill to use. Look for it in this order:
skills/my-router/SKILL.md(repo-local), then.claude/skills/my-router/SKILL.md(pack-deployed), then.agent-config/repo/skills/my-router/SKILL.md(bootstrapped from shared config). - The router inspects prompt keywords, file types, and project structure to dispatch automatically. Do not ask the user which skill to use when the routing table provides a clear match.
- If the
superpowersplugin is active, the router operates during the execution phase. Superpowers handles the outer workflow (brainstorm, plan, execute, verify); the router handles inner dispatch to the right domain skill. - If routing is ambiguous (multiple skills could apply), state the detected context and proposed skill, then ask the user to confirm.
- Codex can run as an MCP server callable from Claude Code. Register at user scope (NOT project scope; project-scoped entries do not propagate across directories):
Writes to
claude mcp add codex -s user -- codex mcp-server -c approval_policy=never~/.claude.jsonmcpServers; session restart required for/mcpto pick it up. Available MCP tools after registration:codex(new prompt) andcodex-reply(continue an existing session). - Prerequisites: Node.js + Codex CLI (
npm install -g @openai/codex) +OPENAI_API_KEY. - Recommended Codex defaults (added to
~/.codex/config.tomlon POSIX or%USERPROFILE%\.codex\config.tomlon Windows; the MCP server reads the same file as interactive sessions):GPT-5.6 requires Codex CLI 0.144.0 or newer. The GPT-5.6 family (model = "gpt-5.6-sol" model_reasoning_effort = "max" service_tier = "fast" [features] fast_mode = true [desktop] conversationDetailMode = "DEFAULT"
gpt-5.6-solflagship,gpt-5.6-terramid,gpt-5.6-lunacheapest) is rejected by older builds with a hard400:The 'gpt-5.6-sol' model requires a newer version of Codex.Verified live: 0.142.5 and 0.143.0 fail, 0.144.0 and 0.144.1 work. If the model errors, runnpm install -g @openai/codex@latestfirst.gpt-5.6-solis Codex's own recommended default and suits the gatekeeper role; usegpt-5.6-terrafor high-fan-out work (e.g.prundispatch) where throughput beats peak capability.service_tierbuys latency, never quality. It selects the serving queue only: the model, its weights, andmodel_reasoning_effortare identical across tiers, sostandardreturns the same answerfastwould, just generated more slowly. The three tiers areflex(lower-priority queue, roughly half rate, availability not guaranteed),standard(the tier used when the key is unset, at normal priority and rate), andfast(about 1.5x faster generation). For ChatGPT auth,fastbills at 2.5x the standard credit rate on GPT-5.6 and GPT-5.5, and 2x on GPT-5.4 (API-key auth pays standard API pricing). Earlier revisions of this file said 2x for all models, which was wrong for the 5.6 family. Default tofast; dial down tostandardonly for an unusually large hands-on task.fastbills 2.5x for about 1.5x speed, which is worth it when a human is waiting on the tokens and the account has quota to spare (for example a second Codex account absorbs the rate). Here the latency saved is worth more than the extra credits. For a rare large task where the 2.5x would bite, dial down with astandardV2 profile (~/.codex/std.config.toml, selected bycodex -p std) or/fast offmid-session. By default the two background dispatchers stay on standard independently of this policy:implement-reviewandprunpass--ignore-user-configto theircodex execworkers for MCP isolation (agent-config#1), so the configured tier does not reach them;CODEX_DISPATCH_ISOLATE_MCP=offlifts the isolation and restores the full user config, tier included. The fast default therefore governs interactive and MCP sessions, exactly where the latency is worth paying for. Hardcodingfastinto the isolated dispatch path is deliberately avoided, because it would fail every round for a consumer whose account lacks the tier.fastis the current config spelling and maps to the request valuepriority; a config already readingpriorityis the same tier. Codex does not validatemodel_reasoning_effortclient-side. An unknown value reaches the service, which rejects the first turn with HTTP400and exits nonzero, so a typo fails loudly rather than degrading silently. Do not treat that error's enumerated list as complete: it names onlynone/minimal/low/medium/high/xhigh, yetmaxandultraare also accepted on GPT-5.6.ultrais not simply more reasoning thanmax. For GPT-5.6 Sol the single-agent reasoning ladder ends atmax;ultrakeeps that same maximum reasoning and additionally switches the harness into automatic task delegation (the rollout recordsmulti_agent_mode: proactiveforultraversusexplicitRequestOnlyformax). GPT-5.6 Terra also exposesultra; GPT-5.6 Luna tops out atmax. Usemaxas the shared default, and chooseultraonly when proactive delegation is actually wanted. Confirm which mode landed by reading~/.codex/sessions/**/rollout-*.jsonl(payload.model,payload.effort, and the collaboration-mode fields) rather than trusting the config file.service_tieris not recorded there. Theimplement-reviewdispatcher keepsxhigh(CODEX_DISPATCH_REASONING) as a deliberate cross-model compatibility default, because models older than GPT-5.6 rejectmaxandultra; that is a compatibility floor, not a claim thatxhighis full strength.conversationDetailMode = "DEFAULT"keeps Codex terminal output concise; avoidSTEPS_PROSE/ Coding mode unless you explicitly want command-level progress shown during turns. - Windows PATH note: Claude Code launches MCP servers through bash, not cmd or PowerShell, so
.cmdwrappers and$env:APPDATAdo not work. Ifcodexis not on bash PATH, register with the full path using forward slashes and NO.cmdextension (e.g.,C:/Users/<you>/AppData/Roaming/npm/codex). Runwhere codex(cmd) orGet-Command codex(PowerShell) to find it. approval_policy=neverrationale: without it, MCP shell commands trigger "MCP server requests your input" dialogs in Claude Code. With it, failures return to Codex/Claude as tool errors. Claude Code's PreToolUse hooks still gate the outer MCP tool call. For interactive Codex terminal sessions (NOT MCP), preferapproval_policy = "on-request"inconfig.toml.- Windows recommendation: prefer the terminal path over MCP. On Windows (11 Build 26200+), MCP has residual rough edges (approval prompts, AV false positives). The terminal path (Codex interactive window for reviews) avoids both. Prefer terminal on Windows; MCP is smoother on macOS/Linux.
- Use scientifically accessible language.
- Do not oversimplify unless the user asks for simplification.
- Keep meaningful technical detail.
- Keep factual accuracy and clarity high in scientific contexts.
- Use consistent terms. If an abbreviation is defined once, do not define it again later.
- If citing papers, verify that they exist.
- When paper citations are requested, provide BibTeX entries that can be copied into a
.bibfile. - Provide code only when necessary. Confirm that the code is correct and can run as written.
- Avoid the following words and close variants unless the user explicitly asks for them (a default AI-tell list; trim or extend in your fork):
encompass,burgeoning,pivotal,realm,keen,adept,endeavor,uphold,imperative,profound,ponder,cultivate,hone,delve,embrace,pave,embark,monumental,scrutinize,vast,versatile,paramount,foster,necessitates,provenance,multifaceted,nuance,obliterate,articulate,acquire,underpin,underscore,harmonize,garner,undermine,gauge,facet,bolster,groundbreaking,game-changing,reimagine,turnkey,intricate,trailblazing,unprecedented.
- Preserve the original format when the input is in LaTeX, Markdown, or reStructuredText.
- Do not convert paragraphs into bullet points unless the user asks for that format.
- Prefer full forms such as
it isandhe wouldrather than contractions. e.g.,andi.e.,are fine when appropriate.- Do not use Unicode character
U+202F. - Avoid heavy dash use. Do not use em dashes (
—) or en dashes (–) as casual sentence punctuation. Prefer commas, semicolons, colons, or parentheses instead. En dashes in numeric ranges (e.g.,1–3,2020–2025), paired names, or citations are fine. Normal hyphenation in compound words and technical terms (e.g.,command-line,co-PI,zero-shot) is fine and should not be avoided. - Break extremely long or complex sentences into shorter, more readable ones. If a sentence has multiple clauses or nested qualifications, split it.
- Vary sentence length and structure. Prefer not to start several consecutive sentences with the same word or phrase. Avoid overusing transition words like "Additionally" or "Furthermore." Not every paragraph needs a tidy summary sentence at the end. Mix short, direct sentences with longer ones to keep the writing natural.
- Do not stage claims as "X, not Y" antithesis for emphasis (also "not just X, but Y"; "it is not X, it is Y"). State the claim directly. Keep the negation only when the rejected alternative is specific and the contrast informs the reader (e.g., "the bottleneck is disk I/O, not CPU").
- Some text you show the user is meant to be copied into an external destination: an email reply, a chat message, a spreadsheet or table cell, a document. Present that text in a fenced code block, which keeps it copyable and stops the client from rendering the markup away. This applies to copy-paste-destined drafts, not to ordinary explanatory answers. Inside such a block, treat hard line breaks as semantic. One paragraph, or one list item, is a single unbroken line however long it runs. Do not wrap to a display width, and do not indent continuation lines. The block looks wide while you compose it, and that is correct. Each destination applies its own wrapping, so a newline added for terminal readability becomes a permanent break there. Keep a blank line between paragraphs, and keep the breaks that carry meaning, such as the lines of a postal address or a signature block.
- A draft long enough to be a document, such as an email, a letter, or a passage of prose, goes in a
.mdfile rather than in the terminal. Give the path in your reply and say what the file holds. A terminal block that size is awkward to select and easy to truncate. The same semantic-line-break rule applies inside the file. Markdown source pasted as plain text arrives in Outlook or Gmail as literal**and-characters, because neither client renders markdown. When the formatting matters, say so and point the user at a rendered view of the file to copy from. An artifact serves the same purpose: copying from the rendered page carries bold, lists, and links onto the clipboard.
- Never run
git commitorgit pushwithout explicit user approval. Always show the proposed action and ask for confirmation before executing. - This rule is non-negotiable and applies to all projects that consume this shared config.
- This includes any variant:
git commit -m,git commit --amend,git push,git push --force,gh pr create(which pushes), etc.
Bootstrap deploys scripts/guard.py to ~/.claude/hooks/guard.py and wires it as a PreToolUse hook in ~/.claude/settings.json. The hook runs before every tool call and mechanically enforces the following:
| Gate | Tool scope | Trigger | Action |
|---|---|---|---|
| Writing-style | Write, Edit, MultiEdit on .md / .tex / .rst / .txt |
Outgoing content contains a banned AI-tell word (see Writing Defaults list) | deny with hit list and inline Suggested rewrite: line naming concrete alternatives |
| agent-style advisory | Same tools and extensions as the row above | agent_style is importable and its mechanical detectors report findings (RULE-05, 06, 12, B, D, I) |
advisory only, reporting up to 5 findings and a count of any withheld to both the model and the user without setting a permission decision |
| Banner emission | Any tool except Read, Grep, Glob, Skill, Task, TodoWrite, BashOutput, WebFetch, WebSearch, ToolSearch, LS, NotebookRead; plus Write/Edit/MultiEdit whose target path exactly equals <project-root>/.agent-config/banner-emitted.json after absolute-path normalization and Windows case folding |
<project-root>/.agent-config/session-event.json.ts > <project-root>/.agent-config/banner-emitted.json.ts. <project-root> is found by walking up from cwd until .agent-config/bootstrap.{sh,ps1} is present. Source repos (no .agent-config/) and unrelated directories skip the gate entirely |
first arm (banner-emitted.json absent): deny with instruction to emit banner + write acknowledgment to the per-project ack file. Re-arm (ack file exists but ts is stale, including malformed JSON): pass-through with a [banner-gate] SessionStart re-fire detected ... advisory line on stderr. The agent should still re-emit the banner on its next textual response per the rule in § "Session Start Check", but tool calls are not blocked (issue anywhere-agents#7). |
Compound cd |
Bash |
Command contains cd <path> && <cmd> or cd <path>; <cmd> |
deny with inline Suggested rewrite: line (e.g. git -C <path> <cmd> for git, or pass the path as an argument) |
| Destructive git | Bash + PowerShell |
git push, git commit, git merge, git rebase, git reset --hard, git clean, git branch -d/-D, git checkout --, git tag -d, git stash drop/clear |
ask (user confirms) |
| Destructive / publish gh | Bash + PowerShell |
gh pr create/merge/close, gh repo delete, gh release create/delete/upload/edit |
ask (user confirms) |
| Publish | Bash + PowerShell |
npm publish, npm unpublish, twine upload, python -m twine upload |
ask (user confirms) |
| File / device destruction | Bash + PowerShell |
Bash rm -rf/-fr/-r -f, dd, mkfs*, shred; PowerShell Remove-Item (+ aliases rm/del/rd/rmdir) with -Recurse/-r//s |
ask (user confirms) |
Mandatory risk classification (tool-agnostic): the four ask rows above are one classifier that runs for the Bash AND PowerShell tools (legacy payloads count as Bash). It keys on the EXACT leading token of each sub-command (split on ; / && / || / |), never a substring scan, so quoted strings like echo "rm -rf" or Write-Output "Remove-Item -Recurse" pass. It strips transparent prefix runners (sudo, doas, env, command, nohup, setsid, inline VAR=VALUE) and sees through built-in command-carrying wrappers (ssh, bash/sh/zsh -c, docker exec/run, pwsh/powershell -Command, Windows cmd /c//k, timeout, xargs) up to MAX_WRAPPER_DEPTH, asking when nesting exceeds it. python -c, the low-frequency prefixes nice/ionice/stdbuf/time, and custom/private wrappers (a personal job-runner, etc.) are treated as opaque documented non-goals: their argument semantics are not inferable from the command text, and substring-scanning arbitrary arguments would reintroduce false-positive alarm fatigue. The user-level allow-list pairs Bash(*) with PowerShell(*), so the native permission layer is allow-by-default and this hook is the sole risk arbiter on both shells.
The agent-style advisory reports; it does not block. The banned-word gate denies because every hit has a one-word substitution, so an agent can reroute in a single turn. The mechanical rules have no such reroute. RULE-12 fires on any sentence over thirty words, which is a mechanical fix while an agent drafts and a judgement call while a person types. A gate that denied on it would be switched off within a day, so it reports through the hook's JSON response and leaves the permission flow alone. The findings are capped at five with a count of the remainder, because a wall of them is one the reader learns to skip. It runs only when the banned-word gate did not deny, so a blocked write produces one message rather than two, and it shares AGENT_STYLE_HOOK rather than adding an env var. A missing or broken agent_style degrades silently, since this hook runs in every repository and most have no reason to carry the package.
Two details were settled by measurement rather than by reading the docs. The findings travel in hookSpecificOutput.additionalContext and in systemMessage, because probing Claude Code 2.1.229 showed those reach the model and the user respectively while stderr on an exit-0 hook reached neither. RULE-G, which asks for title-case headings, is left out. Over the 155 markdown files here it produced 1018 of 2561 findings, and it flagged the sentence-case headings this corpus writes on purpose. It would fill the cap with nothing to act on. The style-review skill still runs it.
Round 6 noise audit (v0.7.0): Deny messages embed a concrete Suggested rewrite: line so an autonomous agent (/implement-review auto, headless claude -p, any unattended loop) can lift the reroute in one model turn instead of inferring it. Destructive operations stay ask because they have no agent-side reroute; human approval is the contract.
Escape hatches: set the corresponding env var in the env block of ~/.claude/settings.json. Disable values: off / 0 / disabled / false / no.
| Env var | Disables |
|---|---|
AGENT_STYLE_HOOK=off |
Writing-style gate and its agent-style advisory |
AGENT_COMPOUND_CD_HOOK=off |
Compound-cd gate only |
AGENT_CONFIG_GATES=off |
Legacy blanket: writing-style + banner only (BC-preserved) |
The mandatory risk set (destructive git, destructive/publish gh, package publishes, file/device destruction) is NOT bypassable by ANY env var. No escape hatch turns the ask prompt into pass-through. The guards have no automatic reroute; human approval is the contract. The advertised env-var set lives in scripts/guard.py:_ESCAPE_HATCH_ENV_NAMES; a static literal-scan test enforces that no future hook env var can be added without registering it there.
Set a per-guard escape env when a legitimate write has a banned word in meta-discussion context (a style-guide document that quotes banned words as examples; a CHANGELOG entry that cites one). Prefer the narrowest env that unblocks (AGENT_STYLE_HOOK=off over AGENT_CONFIG_GATES=off) so the other gates stay live. Remove the override after the write.
- Avoid compound
cd <path> && <command>chains. Claude Code's hardcoded compound-command protection prompts for approval on these even when both commands are individually allowed. Use alternatives that keep each tool call to a single command:- For git in another repo: use
git -C <path> <subcommand>instead ofcd <path> && git <subcommand>. - For non-git commands: pass the target path as an argument (e.g.,
ls <path>,python <path>/script.py) or use separate tool calls.
- For git in another repo: use
- Examples of read-only invocations that should not require approval:
git status,git diff,git log,git branch(no flags),git show,git stash list,git remote -v,git submodule status,git ls-files,git tag --list. Filesystem reads (ls,cat) and benign local operations (mkdir) are also fine. - Examples of invocations that always require explicit approval:
git commit,git push,git reset,git checkout,git rebase,git merge,git branch -d,git remote add/remove,git tag <name>(creating/deleting),git stash drop. - Filesystem commands like
cpandmvare fine for scratch and temporary files. Moves or renames that affect git-tracked files should be reviewed before executing. - Do not wrap PowerShell inside PowerShell with inline
-Commandwhen the payload contains$variables. In a PowerShell shell, run the PowerShell body directly, or write a temporary.ps1and invoke it with-File. Forms likepwsh.exe -Command "foreach($f in ...) { ... }"cause the outer shell to expand$f,$_, and$cutoffbefore the inner shell runs, producing broken commands. - Avoid inline Python with
#comments in quoted arguments. Claude Code flags "newline followed by#inside a quoted argument" as a path-hiding risk and prompts for approval. Instead, write the code to a.pyfile and runpython <script>.py.
- Treat a tool's "cannot open / encrypted / unreadable / unsupported" report on a file as a possible false positive, not a final verdict. PDFs are the common case: a read may report a PDF as encrypted when it actually opens fine. Before telling the user a file cannot be read, retry once and try an alternate read path (re-read with a page range,
pdftotext, render to an image, or a different tool). Report failure only after an alternate path also fails, and say which paths were tried. - The same caution applies to other transient-looking tool failures: a single failed attempt is weak evidence. Prefer one retry or an alternate route over reporting a blocked result, unless the failure is clearly deterministic.
GitHub is deprecating Node.js 20 actions. Runners begin using Node.js 24 by default on June 2, 2026, and GitHub's public changelog currently says Node.js 20 removal will happen later in fall 2026. Keep workflow action pins at or above the first Node.js 24 major for the GitHub-maintained actions below:
| Action | Minimum version (Node.js 24) | Replaces |
|---|---|---|
actions/checkout |
v5 | v3, v4 |
actions/setup-python |
v6 | v5 |
actions/setup-node |
v5 | v4 |
actions/upload-artifact |
v6 | v4, v5 |
actions/download-artifact |
v7 | v4, v5, v6 |
When the session start check (item 4) detects older versions, list the affected files and suggest the minimum Node.js 24 version from this table. If a repository intentionally wants the latest major instead of the minimum compatible major, flag that as a separate manual upgrade because later majors can include behavior changes. If a workflow pins a SHA instead of a tag (e.g., actions/checkout@abc123), flag it for manual review rather than auto-suggesting a tag. For self-hosted runners, also remind the user that these Node.js 24 actions require an Actions Runner version that supports Node.js 24.
- Do not conclude that Python is unavailable just because
python,python3, orpyfails inPATH; those may resolve to shims, store aliases, or the wrong interpreter. Inspect common environment managers (Miniforge/Conda, pyenv, uv, venv) before reporting Python as missing. - If the user's fork sets a preferred Python interpreter path in
AGENTS.local.md, use that first. - GitHub CLI (
gh) is used for PR and issue workflows. Ifghis not found, remind the user to install it (winget install GitHub.clion Windows,brew install ghon macOS,ghfrom the distro package manager on Linux) and authenticate withgh auth login. - Console windows flashing during Windows test runs: a process launched as a background task owns no console. Every console child it spawns therefore asks Windows for one, and that one is shown. A suite that spawns shells continuously flashes a window roughly once a second across whatever else is on screen. The owner varies by depth, so a capture may name
powershell.exe,pwsh.exeorcmd.exe. Two measures, both measured against this repository's suite:- Give the runner process a hidden console, which every descendant inherits so none of them allocates: launch the suite through
Start-Process -WindowStyle Hidden -Wait -RedirectStandardOutput <file>. Measured: about one window per second before, zero after. This covers the whole tree and is the one that matters. - Keep
CREATE_NO_WINDOWon the shells the suite spawns, whichtests/_quiet_spawn.pyinstalls by patchingsubprocess.runandsubprocess.Popen. Measured on an isolated shell-to-cmd.exechain: three windows over three runs before, zero after. It reaches only the process it is applied to, so it is a second layer rather than a substitute for the first. Setting the Windows default terminal application to Windows Console Host is worth doing as well. Windows Terminal turns each allocation into a full terminal window and does not honorSW_HIDEon it, whereasconhostdoes. That changes how loud the problem is rather than removing it. Settings, System, For developers, Terminal, or setDelegationConsoleandDelegationTerminalunderHKCU:\Console\%%Startupto{B23D10C0-E52E-411E-9D5B-C09FDF709C7D}. Opening Windows Terminal yourself is unaffected.
- Give the runner process a hidden console, which every descendant inherits so none of them allocates: launch the suite through
- Claude Code installation: Prefer the native installer. Migrate off npm and winget when possible.
- macOS:
curl -fsSL https://claude.ai/install.sh | sh - Windows (PowerShell, no admin):
irm https://claude.ai/install.ps1 | iex(requires Git for Windows) - To migrate from npm:
npm uninstall -g @anthropic-ai/claude-codefirst. From winget:winget uninstall Anthropic.ClaudeCodefirst. - Native installs auto-update in the background by default. Use
/configinside Claude Code to set the release channel (latestorstable). Runclaude doctorto inspect updater status, andclaude updateto force an immediate update check. - To disable auto-updates, set
DISABLE_AUTOUPDATER=1in the environment or add"env": {"DISABLE_AUTOUPDATER": "1"}to~/.claude/settings.json. The env var takes precedence regardless of other flags.
- macOS:
- Claude Code effort level: As of Claude Code v2.1.111, the
/effortslider exposes five levels:low,medium,high,xhigh,max. The persistedeffortLevelkey insettings.jsonacceptslow,medium,high, andxhigh(v2.1.111 addedxhighas a valid persisted value).maxremains session-only: selectingmaxvia/effortsilently does not persist. To getmaxas a persistent default across every project and session, set the env varCLAUDE_CODE_EFFORT_LEVEL=maxin~/.claude/settings.jsonunder"env". The shareduser/settings.jsonin this repo sets the env var, and bootstrap merges it into~/.claude/settings.json, so running bootstrap once on any consuming project lands the user-level default. Runtime precedence: managed policy >CLAUDE_CODE_EFFORT_LEVELenv var > persistedeffortLevel(local > project > user) > Claude Code's built-in default. When the env var is set, it outranks--effortat launch and/effortinside a session; the slash command prints a warning that the env var is overriding the live effort. When the env var is unset,--effort <level>at launch is a session-only override,/effort low|medium|high|xhighupdates the persisted user setting, and/effort maxis session-only.
- If the workspace contains a
skills/directory, treat repo-local skills as the default source of truth for that project. - Skill lookup order for every agent (Claude Code, Codex, or any future agent): when resolving a skill by name, try paths in this order, first hit wins:
skills/<skill-name>/SKILL.md: project-local, hand-authored or vendored..claude/skills/<skill-name>/SKILL.md: pack-deployed byanywhere-agents pack install. The.claude/prefix is a historical Claude Code convention; the SKILL.md contents are agent-agnostic. A v1.0 architecture pass is the right place to revisit the directory name..agent-config/repo/skills/<skill-name>/SKILL.md: shared config bootstrapped from upstream. This is the same lookup order encoded in the Claude Code slash-command pointers at.claude/commands/<name>.md(per the issue #6 fix), so an agent reading either the pointer file or this rule resolves the same skill the same way.
- When using a repo-local skill, read
skills/<skill-name>/SKILL.mdand its localreferences/,scripts/, andassets/before falling back to any globally installed copy. - Do not modify a globally installed skill when a repo-local skill of the same name exists, unless the user explicitly asks to update the global copy too.
- If a repo-local skill overrides a global skill, state briefly that the local project copy is being used.
- Skills under
skills/are shared between coding agents (Codex, Claude Code, and any future agent). skills/<skill-name>/SKILL.mdis the single source of truth for each skill. Agent-specific config files (e.g.,agents/openai.yaml) are thin wrappers and must not duplicate or override the logic inSKILL.md.- Claude Code has an ergonomic helper: slash-command pointers in
.claude/commands/<name>.md. Each pointer file references the correspondingSKILL.mdrather than duplicating its content. Codex and other agents reach the sameSKILL.mdcontent via the documented "Local Skills Precedence" lookup order above; no slash-command equivalent is required. - Pack-deployed skills (third-party packs installed by
anywhere-agents pack install) land under.claude/skills/<name>/as a cross-agent location. The directory name carries a historical Claude Code prefix; the SKILL.md contents are agent-agnostic and resolvable by Codex through the same lookup order. A future plan-review pass onpack-architecture.mdis the right place to consider renaming the location to a vendor-neutral path. - Bootstrap sync should copy only the shared repo's
.claude/commands/*.mdfiles into the project.claude/commands/directory and should not delete unrelated project-local commands. - When editing a skill, modify
SKILL.mdand itsreferences/orscripts/directly. Do not create agent-specific forks of the same content. - If a new skill is added, create both the
skills/<skill-name>/SKILL.mdstructure and a matching.claude/commands/<skill-name>.mdpointer so Claude Code's slash-command surface stays in sync; Codex reaches the same skill through the lookup order without needing a pointer.