Manage
A collection of personal AI coding assistant configurations, specialist agents, and automated workflows optimized for Python and ML open-source development.
npx -y skills add Borda/AI-Rig --skill manageAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 23 stars23 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Create, update, or delete agents, skills, rules, and hooks with full cross-reference propagation. Trivial edits (typos, small fixes ≤10 words) applied inline without agent; `.md` content-edits delegated to foundry:curator; code file edits (`.js`, `.py`, `.ts`) delegated to foundry:sw-engineer; large cross-ref fan-outs (> 3 files) also delegate. The parent orchestrates MEMORY.md, README, audit, calibration, and the final report. Also manages settings.json permissions atomically with permissions-guide.md. NOT for: validation/quality audit of existing agents/skills (use /foundry:audit); implementing application source code changes outside `.claude/` (use develop:feature or develop:fix — requires `develop` plugin).
SKILL.md
52.7 KB, as published. Nobody here has run it
<objective>Note:
disable-model-invocation: true—/manageuser-invoked only, noSkill()chaining from orchestrators. When suggesting/manageas follow-up, invoking skill must present as user-run command, not auto step.
Manage lifecycle of agents, skills, rules, hooks in .claude/. Handles creation with rich domain content, atomic renames with cross-ref propagation, content editing (trivial edits inline; .md files → foundry:curator; code files *.js/*.py/*.ts → foundry:sw-engineer; rule edits inline), clean deletion with broken-ref cleanup. Keeps MEMORY.md inventory in sync with disk.
-
$ARGUMENTS: required, one of:
create agent <name> "description"— create new agent with generated domain contentcreate skill <name> "description"— create new skill with workflow scaffoldcreate rule <name> "description"— create new rule file with frontmatter and sectionsupdate <name> <new-name>— rename; type auto-detected from diskupdate <name> "change description"— content-edit; trivial → inline,.md→ foundry:curator, code → foundry:sw-engineer, rule → inlineupdate <name> <spec-file.md>— content-edit from spec file; trivial → inline,.md→ foundry:curator, code → foundry:sw-engineer, rule → inlinedelete <name>— delete; type auto-detected from disk (agents, skills, rules, hooks); asks user if ambiguousadd perm <rule> "description" "use case"— add permission to settings.json allow list and permissions-guide.mdremove perm <rule>— remove permission from settings.json allow list and permissions-guide.md
-
Names must be kebab-case (lowercase, hyphens only)
-
Descriptions must be quoted when containing spaces
-
Permission rules use Claude Code format:
WebSearch,Bash(cmd:*),WebFetch(domain:example.com) -
--skip-audit— optional flag: skip Step 9/auditvalidation (use insideaudit fixloop to avoid recursion) -
Spec-file paths must be quoted —
update <name> <spec-file.md>requires the spec path quoted if it contains any whitespace (e.g.update my-agent "docs/My Spec.md"); unquoted paths with spaces split into multiple arguments and trigger argument-shape mismatch. Recommended: keep spec filenames free of spaces.
Update/delete mode — name looked up across agents, skills, rules automatically:
- One match on disk → proceed with that type
- Multiple matches →
AskUserQuestion: (a) agent, (b) skill, (c) rule - No match → report error and stop
Update second-argument discrimination:
- Two bare kebab-case args (second arg no spaces, no
.mdextension) → rename mode - One name + quoted string → content-edit mode (trivial → inline;
.md: foundry:curator; code*.js/*.py/*.ts: foundry:sw-engineer; rule: inline) - One name + path ending in
.md→ content-edit mode (trivial → inline;.md: foundry:curator; code*.js/*.py/*.ts: foundry:sw-engineer; rule: inline)
Examples:
/foundry:manage create agent task-planner "Planning specialist for decomposing epics into actionable tasks"/foundry:manage update my-agent "add a section on error handling patterns"/foundry:manage update optimize docs/specs/YYYY-MM-DD-<spec-name>.md/foundry:manage delete old-agent-name/foundry:manage add perm "Bash(jq:*)" "Parse and filter JSON" "Extract fields from REST API responses"
- AGENTS_DIR:
.claude/agents - SKILLS_DIR:
.claude/skills - RULES_DIR:
.claude/rules - HOOKS_DIR:
.claude/hooks - AVAILABLE_COLORS: indigo, lime, magenta, teal, violet
Each Step 4 spawn applies the health monitoring in _shared/agent-spawn-protocol.md §8b — rely on the harness completion notification, then read the agent's output file; optional single health_sentinel.py probe per turn (no sleep loop). Substitute only its own <ID> suffix and output-file glob; do not re-paste the snippet per spawn.
Colors in use are read from the live Grep in Step 3 (authoritative) — no static used-color list to maintain. AVAILABLE_COLORS is the candidate pool for a new agent; pick the first entry not already in the Step-3 set.
</constants> <workflow>Task hygiene: call TaskList first; close orphaned tasks. Task tracking: create tasks for each major phase; mark in_progress/completed throughout.
Step 1: Parse and validate
Extract operation, type, name, optional arguments from $ARGUMENTS.
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
SKIP_AUDIT=false
[[ "$ARGUMENTS" == *"--skip-audit"* ]] && SKIP_AUDIT=true
ARGUMENTS=$(echo "$ARGUMENTS" | sed 's/\(^\|[[:space:]]\)--skip-audit\([[:space:]]\|$\)/ /g' | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')
echo "$SKIP_AUDIT" > "${TMPDIR:-/tmp}/manage-skip-audit-${CSID}" # persist (Check 41)
echo "${TMPDIR:-/tmp}/manage-skip-audit-${CSID}" > "${TMPDIR:-/tmp}/manage-skip-audit-path-${CSID}"
Unsupported flag check — after all supported flags extracted (--skip-audit), scan $ARGUMENTS for remaining --<token> tokens. If found: print ! Unknown flag(s): \--<token>`. Supported: `--skip-audit`.then invokeAskUserQuestion` — (a) Abort (stop, re-invoke with correct flags) · (b) Continue ignoring (skip unknown flags, proceed). On Abort: stop.
Validation rules:
- Name must match
^[a-z][a-z0-9-]*$(kebab-case) - For
create: name must NOT already exist on disk; description required - For
update/delete: name MUST already exist on disk - For
updaterename: new-name must NOT already exist on disk - For
add perm: rule must NOT already exist in settings.json allow list; description and use case required - For
remove perm: rule MUST already exist in settings.json allow list
Type auto-detection (for update and delete): first verify post-install context exists:
[ -d .claude/agents ] || { printf "! .claude/agents not found — run /foundry:setup first or confirm working directory is project root\n"; exit 1; } # timeout: 3000
Then run all four Glob checks in parallel:
- Agent: pattern
agents/<name>.md, path.claude/ - Skill: pattern
skills/<name>/SKILL.md, path.claude/ - Rule: pattern
rules/<name>.md, path.claude/ - Hook: pattern
hooks/<name>.js, path.claude/
Results:
- One non-empty result → resolved type; proceed
- Multiple non-empty results →
AskUserQuestion: "Multiple entities named<name>found. Which one? (a) agent (b) skill (c) rule (d) hook" — note: (d) hook valid forupdateanddeleteonly;create hooknot yet implemented (use Edit tool onhooks/<name>.jsdirectly until create-hook mode added) - All empty → report "No agent, skill, rule, or hook named
<name>found" and stop
For create, check only relevant type's path.
Delete confirmation gate — when $MODE is delete, immediately after type resolution invoke AskUserQuestion: "Delete <name> (<type>)? This cannot be undone. (a) Confirm · (b) Abort". On Abort: stop. On Confirm: proceed to Step 4.
jq -e --arg rule '<rule>' '.permissions.allow | index($rule) != null' .claude/settings.json >/dev/null 2>&1 # timeout: 5000
Update second-argument discrimination — apply after type resolved. Set shell variable MODE from the parsed operation; consumed by the delete confirmation gate above, the edit-complexity classifier below, and the per-mode workflow branches in Step 4. Recognised values: create, rename, content-edit, delete, add-perm, remove-perm.
| Argument shape | MODE |
|---|---|
create <type> <name> "..." | create |
update <name> <new-name> (two bare kebab-case args; second has no spaces, no .md) | rename (validate new-name does NOT already exist) |
update <name> "<change>" (one name + quoted string) | content-edit (validate spec non-empty; set DIRECTIVE = the quoted string) |
update <name> <spec>.md (one name + path ending in .md; must be quoted if path contains spaces) | content-edit (validate spec file exists on disk and path ends in .md; report error if not found; set DIRECTIVE = contents of the spec file via Read tool) |
delete <name> | delete |
add perm <rule> "..." "..." | add-perm |
remove perm <rule> | remove-perm |
Assign MODE in shell before the edit-complexity classification below so the [[ "$MODE" == "content-edit" ]] guard fires correctly:
# MODE="content-edit" # or "rename" / "create" / "delete" / "add-perm" / "remove-perm"
If validation fails, report error and stop.
Edit complexity classification (content-edit mode only):
Classify $DIRECTIVE as trivial when ALL conditions hold:
| Condition | Required |
|---|---|
| Word count ≤ 10 | ✓ |
Matches pattern: typo, spelling, rename X to Y, change X to Y, replace X with Y, fix (a/the)? (typo/bug/error), add missing, remove [word], correct | ✓ |
Both must hold — either failing → substantive. Trivial edits: apply inline with Edit tool — no agent spawn.
Step skip rules:
- Perm operations: skip Steps 2, 3, 5, 6, 7, 8, 9 — go Step 1 → Step 4 → Step 10
- Hook operations: skip Steps 2, 3, 6 (no color inventory, no MEMORY.md roster entry, no README table row); in Steps 5 and 7 skip cross-ref propagation (hook filenames not referenced from agent/skill markdown) — go Step 1 → Step 4 → Step 9 → Step 10
- Content-edit operations: skip Step 2 (entity already exists); skip Step 3 color inventory (no create); in Steps 5–7 only update cross-refs and README if name or description changed. Step 6 count: only update if name added or removed — content-only edits do not change agent/skill count.
- Trivial content-edits: additionally skip Steps 6–7 (no roster/description change possible); proceed Step 1 → Step 4 → Step 8 → Step 10
Step 2: Overlap review (create only)
Before creating, check if existing agents/skills already cover requested functionality:
- Read descriptions of all existing agents (use
Read(file_path=..., limit=3)on each.mdin agents/) and skills (useRead(file_path=..., limit=3)on eachSKILL.md) - Compare new description against each existing — look for domain overlap, similar workflows, redundant scope
- Present findings:
- No overlap: proceed to Step 3
- Partial overlap: name overlapping agent/skill, explain coverage vs what new one adds, use
AskUserQuestion: "Extend existing (Recommended)" / "Proceed" / "Abort" - Strong overlap: recommend against creation — suggest using or extending existing agent/skill
Skip for update, delete, perm operations.
Step 3: Inventory current state
Snapshot current roster for later comparison. Steps 2 and 3 are independent reads — issue Glob calls for both in same response.
Use Glob (pattern agents/*.md, path .claude/) for agents and Glob (pattern skills/*/, path .claude/) for skills. Use Grep (pattern ^color:, glob agents/*.md, path .claude/, output mode content) to collect colors in use.
Extract names inline from Glob results — strip .claude/agents/ prefix and .md suffix for agents; strip .claude/skills/ prefix and trailing / for skills; strip .claude/rules/ prefix and .md suffix for rules. Sort alphabetically when building roster string.
Step 4: Execute operation
Mode: Create Agent
-
Fetch latest Claude Code agent frontmatter schema:
- Resolve schema cache path (24h TTL — schema changes rarely; saves one web-explorer spawn per create):
mkdir -p .cache/manage # timeout: 3000 MANAGE_SCHEMA_FILE=".cache/manage/agent-schema.md" if [ -n "$(find "$MANAGE_SCHEMA_FILE" -mmin -1440 2>/dev/null)" ]; then MANAGE_SCHEMA_CACHED=true; else MANAGE_SCHEMA_CACHED=false; fi echo "Schema file: $MANAGE_SCHEMA_FILE (cached: $MANAGE_SCHEMA_CACHED)" # timeout: 3000 MANAGE_SCHEMA_CACHED=true→ skip the spawn and health monitoring below; Read$MANAGE_SCHEMA_FILE(limit=60) for the field list and continue at the extraction bullet.- Spawn foundry:web-explorer to fetch
https://code.claude.com/docs/en/sub-agentswith instruction: "Write your full findings (schema fields, new fields, deprecated fields) to<MANAGE_SCHEMA_FILE>(substitute resolved path from bash block above) using the Write tool. Return ONLY a compact JSON envelope on your final line — nothing else after it:{\"status\":\"done\",\"file\":\"<MANAGE_SCHEMA_FILE>\",\"fields\":N,\"new\":N,\"deprecated\":N,\"confidence\":0.N,\"summary\":\"N fields, N new, N deprecated\"}"
Health monitoring (CLAUDE.md §6): after spawning the web-explorer agent, apply the §8b boilerplate from
_shared/agent-spawn-protocol.mdwith<ID>=web-explorerand find globagent-schema.md(poll path.cache/manage).- Read returned summary; extract: valid frontmatter fields (
name,description,tools,disallowedTools,model,permissionMode,maxTurns,effort,initialPrompt,skills,mcpServers,hooks,memory,background,isolation,color), current model shorthands, new fields - Note new fields worth including. Adjust template to reflect current schema. If new field broadly useful for agent's role (e.g.
maxTurnsfor long-running agents), include with sensible default and inline comment.
- Resolve schema cache path (24h TTL — schema changes rarely; saves one web-explorer spawn per create):
-
Pick first unused color from AVAILABLE_COLORS pool (compare against Step 3 colors)
-
Choose model based on role complexity:
opusplan— plan-gated roles (solution-architect, oss:shepherd, foundry:curator)opus— complex implementation roles (foundry:sw-engineer, research:scientist, foundry:perf-optimizer)sonnet— focused execution roles (research:data-steward (requiresresearchplugin), foundry:web-explorer, foundry:doc-scribe, foundry:creator, foundry:qa-specialist, oss:cicd-steward)haiku— high-frequency diagnostics ONLY (e.g. linting-expert); NOT for analysis/auditing roles that require substantive reasoning
-
Resolve template path (cascade primary → project-local → cache scan; only the cache scan runs if neither cheaper path exists, since each candidate must satisfy
-dbefore being assigned):
MANAGE_TPL=$(python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/resolve_skill_subdir.py" manage templates) || { printf "! BREAKING: manage templates not found — run /foundry:setup first\n"; exit 1; } # timeout: 5000
- Spawn foundry:sw-engineer subagent to scaffold and write the agent file.
foundry:curatoris the wrong delegate here — its NOT-for explicitly excludes creating or scaffolding agents/skills; curator only reviews and edits existing config.foundry:sw-engineerowns scaffolding (treat agent.mdas a config artifact whose authoring is a software task — frontmatter schema, tool selection, structural completeness).
Before passing schema file path to sw-engineer: verify file exists on disk using Read tool (limit=1). If schema file path from JSON envelope does not exist, proceed with default frontmatter fields (name, description, model, color) — note omission in Step 10 report.
Run `cat "<MANAGE_TPL>/agent-scaffold.md"` via the Bash tool (substitute resolved path from bash block above — do not pass literal `$MANAGE_TPL` to the agent).
Also read the schema file at the path returned in the step 1 JSON to incorporate any new frontmatter fields (skip if schema file not found — use default frontmatter fields: name, description, model, color).
Scaffold `.claude/agents/<name>.md` with:
- Frontmatter: name=<name>, description=<description>, model=<model>, color=<color>; add any broadly-useful new fields from the schema
- Body: rich domain-specific content for the role described by the description, following all content rules and tool selection guidelines in the scaffold template
Write the file using the Write tool.
Return ONLY: {"status":"done","file":".claude/agents/<name>.md","lines":N,"confidence":0.N}
Health monitoring (CLAUDE.md §6): after spawning the foundry:sw-engineer agent, apply the §8b boilerplate from _shared/agent-spawn-protocol.md with <ID> = sw-engineer-agent and the find glob matching this agent's output files.
CRITICAL — worktree isolation copy: foundry:sw-engineer runs with isolation: worktree — scaffolded file lands in a temporary worktree, not the main tree. After agent completes: (1) read the worktree path from the agent result (returned in worktree field or as part of the result message); (2) run: cp <worktree-path>/.claude/agents/<name>.md .claude/agents/<name>.md (substitute actual paths); (3) proceed with Steps 5–9 on the main-tree copy. Without this step, Steps 5–9 Globs find nothing.
Mode: Create Skill
-
Fetch latest Claude Code skill frontmatter schema:
- Resolve skill schema cache path (24h TTL — same rationale as Create Agent step 1):
mkdir -p .cache/manage # timeout: 3000 MANAGE_SKILL_SCHEMA_FILE=".cache/manage/skill-schema.md" if [ -n "$(find "$MANAGE_SKILL_SCHEMA_FILE" -mmin -1440 2>/dev/null)" ]; then MANAGE_SKILL_SCHEMA_CACHED=true; else MANAGE_SKILL_SCHEMA_CACHED=false; fi echo "Skill schema file: $MANAGE_SKILL_SCHEMA_FILE (cached: $MANAGE_SKILL_SCHEMA_CACHED)" # timeout: 3000 MANAGE_SKILL_SCHEMA_CACHED=true→ skip the spawn and health monitoring below; Read$MANAGE_SKILL_SCHEMA_FILE(limit=60) for the field list and continue at the extraction bullet.- Spawn foundry:web-explorer to fetch
https://code.claude.com/docs/en/skillswith instruction: "Write your full findings (schema fields, new fields, deprecated fields) to<MANAGE_SKILL_SCHEMA_FILE>(substitute resolved path from bash block above) using the Write tool. Return ONLY a compact JSON envelope on your final line — nothing else after it:{\"status\":\"done\",\"file\":\"<MANAGE_SKILL_SCHEMA_FILE>\",\"fields\":N,\"new\":N,\"deprecated\":N,\"confidence\":0.N,\"summary\":\"N fields, N new, N deprecated\"}"
Health monitoring (CLAUDE.md §6): after spawning the web-explorer agent, apply the §8b boilerplate from
_shared/agent-spawn-protocol.mdwith<ID>=web-explorer-skilland the find glob matching this agent's output files.- Read returned summary; extract: valid frontmatter fields (
name,description,argument-hint,disable-model-invocation,user-invocable,allowed-tools,model,effort,shell,paths,context,agent,hooks), new fields - Note new fields worth including. Adjust template to reflect current schema. Include
modelorcontext: forkonly when skill's purpose clearly benefits.
- Resolve skill schema cache path (24h TTL — same rationale as Create Agent step 1):
-
Re-resolve
MANAGE_TPLat the start of each skill invocation; do not assume it is set from a prior step. Most/foundry:manage create skill ...invocations enter Create Skill mode directly without going through Create Agent first, so the variable will be unset. Run the resolution block from Create Agent step 4 above (cascade primary → project-local → cache scan with the-dguards) before reading any template path. -
Resolve
$_FOUNDRY_SHAREDbefore spawning — sub-agents do not inherit shell variables:
_FOUNDRY_SHARED=$(python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/resolve_shared_path.py" foundry skills/_shared 2>/dev/null || echo "plugins/cc_foundry/skills/_shared") # timeout: 5000
echo "Shared dir: $_FOUNDRY_SHARED"
Spawn foundry:sw-engineer subagent to create directory and scaffold the skill file (foundry:curator NOT-for excludes scaffolding new agents/skills — see Create Agent rationale above):
Run: `mkdir -p .claude/skills/<name>` using the Bash tool.
Run `cat "<MANAGE_TPL>/skill-scaffold.md"` via the Bash tool (substitute resolved path from bash block above — do not pass literal `$MANAGE_TPL` to the agent).
Also read the schema file at the path returned in the step 1 JSON to incorporate any new frontmatter fields.
Run `cat "<_FOUNDRY_SHARED>/bin-authoring-guide.md"` via the Bash tool (substitute resolved `$_FOUNDRY_SHARED` value from bash block above — echoed as `"Shared dir: <path>"`) and follow it — before writing any fenced code block in the new SKILL.md, apply the extraction gate. Write a bin/ script directly if verdict is MEDIUM or HIGH. Also apply the Prose over Code check (bin-authoring-guide.md §Prose over Code): if tokens(block) > tokens(equivalent prose/table/schema) at identical precision — write prose/table instead of the code block. Exempt: examples, templates, exact-syntax blocks. For any bin/ script returning 2+ values: apply §Script Output Routing — write each value to `${TMPDIR:-/tmp}/<skill>-<name>-${CSID}` file; skill checks exit code only; never `eval` stdout.
Scaffold `.claude/skills/<name>/SKILL.md` with:
- Frontmatter: name=<name>, description=<description>; add other fields per schema and scaffold guidance
- Body: rich workflow scaffold derived from the description, following all content rules in the scaffold template
Write using the Write tool.
Return ONLY: {"status":"done","file":".claude/skills/<name>/SKILL.md","lines":N,"confidence":0.N}
Health monitoring (CLAUDE.md §6): after spawning the foundry:sw-engineer agent, apply the §8b boilerplate from _shared/agent-spawn-protocol.md with <ID> = sw-engineer-skill and the find glob matching this agent's output files.
Mode: Update Agent (rename)
Atomic rename — write new file before deleting old:
-
Read
.claude/agents/<old-name>.mdusing the Read tool. -
Write new file to
.claude/agents/<new-name>.mdusing the Write tool (copy content of old file withname:line updated to<new-name>). -
Verify new file exists and is valid:
Read(file_path=".claude/agents/<new-name>.md", limit=5)
rm .claude/agents/<old-name>.md # timeout: 5000
Mode: Update Skill (rename)
Atomic rename — create new directory before removing old:
-
Create new directory:
mkdir -p .claude/skills/<new-name> # timeout: 5000 -
Read old SKILL.md, update
name:line in frontmatter, Write to new location.After updating
name:in frontmatter: also scan the new SKILL.md body for TRIGGER conditions, NOT-for lines, and example invocations that still reference the old skill name — update those inline with Edit tool before proceeding to Step 5. -
Verify new file exists:
Read(file_path=".claude/skills/<new-name>/SKILL.md", limit=5)rm -r .claude/skills/<old-name> # timeout: 5000
Mode: Delete Agent
rm .claude/agents/<name>.md # timeout: 5000
Mode: Delete Skill
rm -r .claude/skills/<name> # timeout: 5000
Mode: Update Agent/Skill (content-edit)
Before executing type-specific content-edit mode, determine approach:
File-type → agent routing:
| File extension | Agent |
|---|---|
.md (agents, skills, SKILL.md) | foundry:curator |
.js, .py, .ts, .sh (code) | foundry:sw-engineer |
Rule .md (under rules/) | inline Edit — no agent |
If EDIT_TRIVIAL=true (classified in Step 1):
- Read file using Read tool
- Apply directive directly using Edit tool — no agent spawn
- Proceed to Step 8; skip Steps 5–7 unless name or description changed in edit
If EDIT_TRIVIAL=false: proceed to type-specific mode below for full agent-delegated edit.
Mode: Content-Edit Agent
- Determine change directive:
- Quoted description → use as-is
- Spec file path → Read spec file; use content as directive
- Resolve
_FS_VAL(concrete path) before constructing spawn prompt — sub-agents do not inherit shell variables, so the prompt must contain a literal path, not a$VARreference:
_FS_VAL=$(python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/resolve_shared_path.py" foundry skills/_shared 2>/dev/null || echo "plugins/cc_foundry/skills/_shared") # timeout: 5000
echo "Shared dir for curator prompt: $_FS_VAL"
- Spawn foundry:curator subagent — substitute
<_FS_VAL>with the path from above when emitting the prompt:
Read `.claude/agents/<name>.md`.
Apply this change: <directive>
Rules:
- Preserve frontmatter fields (name, description, tools, model, color) unless the change explicitly targets them
- Preserve XML tags (<role>, <workflow>, <notes>) — targeted edits only; do not rewrite unchanged sections
- If the change modifies the agent's purpose: update the description: frontmatter field
- If the change adds any fenced code block: run `cat "<_FS_VAL>/bin-authoring-guide.md"` via the Bash tool and apply the extraction gate — write a bin/ script instead if verdict is MEDIUM or HIGH. Also apply the Prose over Code check (bin-authoring-guide.md §Prose over Code): if tokens(block) > tokens(equivalent prose/table/schema) at identical precision — write prose/table instead of the code block. Exempt: examples, templates, exact-syntax blocks. For any bin/ script returning 2+ values: apply §Script Output Routing — write each to `${TMPDIR:-/tmp}/<skill>-<name>-${CSID}` file; never `eval` stdout.
- After editing: verify XML tag balance, step numbering, cross-ref validity
Write all changes using the Edit tool.
Return ONLY: {"status":"done","file":".claude/agents/<name>.md","edits":N,"description_changed":true|false,"confidence":0.N}
Use description_changed from returned JSON to decide whether Steps 5–7 need cross-ref propagation.
Mode: Content-Edit Skill
- Determine change directive (same as Content-Edit Agent).
- Resolve
_FS_VAL(concrete path) before constructing the spawn prompt:
_FS_VAL=$(python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/resolve_shared_path.py" foundry skills/_shared 2>/dev/null || echo "plugins/cc_foundry/skills/_shared") # timeout: 5000
echo "Shared dir for curator prompt: $_FS_VAL"
- Spawn foundry:curator subagent — substitute
<_FS_VAL>with the path from above:
Read `.claude/skills/<name>/SKILL.md`.
Apply this change: <directive>
Rules:
- Preserve frontmatter fields (name, description, argument-hint, disable-model-invocation, allowed-tools)
- Preserve XML tags (<objective>, <inputs>, <workflow>, <notes>) — targeted edits only; do not rewrite unchanged sections
- If the change modifies the skill's purpose: update the description: frontmatter field
- If the change adds any fenced code block: run `cat "<_FS_VAL>/bin-authoring-guide.md"` via the Bash tool and apply the extraction gate — write a bin/ script instead if verdict is MEDIUM or HIGH. Also apply the Prose over Code check (bin-authoring-guide.md §Prose over Code): if tokens(block) > tokens(equivalent prose/table/schema) at identical precision — write prose/table instead of the code block. Exempt: examples, templates, exact-syntax blocks. For any bin/ script returning 2+ values: apply §Script Output Routing — write each to `${TMPDIR:-/tmp}/<skill>-<name>-${CSID}` file; never `eval` stdout.
- After editing: verify XML tag balance, step numbering, workflow gate completeness
Write all changes using the Edit tool.
Return ONLY: {"status":"done","file":".claude/skills/<name>/SKILL.md","edits":N,"description_changed":true|false,"confidence":0.N}
Use description_changed from returned JSON to decide whether Steps 5–7 need cross-ref propagation.
Mode: Content-Edit Rule
- Read
.claude/rules/<name>.mdusing the Read tool. - Determine change directive (same as Content-Edit Agent).
- Apply changes directly using the Edit tool:
- Preserve YAML frontmatter (description, paths) unless change explicitly targets them
- Rule files are free-form markdown with
##sections — no XML tags - Targeted edits — do not rewrite unchanged sections
- Adding new section: match heading level and style of existing sections
- If change modifies rule's scope: also update
description:andpaths:frontmatter fields - After editing: verify YAML frontmatter valid, no broken internal references
Mode: Create Rule
No schema fetch needed — rule files simpler than agents/skills (only frontmatter + free-form markdown sections).
Rule scope guidance: empty paths: = global rule (applies everywhere); populated paths: = scoped (e.g., paths: ["src/**/*.py"] for Python-only rules). Default to global unless rule is clearly language/directory-specific.
Write .claude/rules/<name>.md with this structure:
---
description: <one-line description from user>
paths:
- '<glob pattern matching the rule's scope>'
---
## <First Section Title>
[Real domain-specific rules derived from the description — not generic boilerplate. 20-60 lines total.]
Content rules:
- Generate real domain content from description (e.g., for "torch-patterns": actual PyTorch patterns, not generic "write clean code")
- Use
##sections for major topics, bullets for individual rules - Include code examples only when they carry domain-specific patterns
- Match tone and density of existing rules files (terse, imperative, no padding)
Mode: Update Rule (rename)
Atomic update — write new file before deleting old:
- Read
.claude/rules/<old-name>.mdusing the Read tool. - Rule files have no
name:frontmatter field — filename IS identifier. Write new file at.claude/rules/<new-name>.mdwith identical content. - Verify new file exists:
Read(file_path=".claude/rules/<new-name>.md", limit=5)
rm .claude/rules/<old-name>.md # timeout: 5000
Mode: Delete Rule
rm .claude/rules/<name>.md # timeout: 5000
Mode: Content-Edit Hook
Hook files are JavaScript — delegate to foundry:sw-engineer (not foundry:curator):
- Determine change directive (same as Content-Edit Agent).
- Spawn foundry:sw-engineer subagent:
Read `.claude/hooks/<name>.js`.
Apply the hook authoring standards from the `\<hook_authoring>` section in your agent definition — file-header structure, exit code semantics, stdin pattern, and anti-patterns.
Apply this change: <directive>
Rules:
- Preserve the file header block (PURPOSE, HOW IT WORKS, EXIT CODES) unless the change explicitly modifies that logic
- Preserve CommonJS require() style; do not convert to ESM
- stdin must use event-based accumulation (process.stdin.on("data"/"end")); never readFileSync("/dev/stdin")
- All subprocess calls must use execFileSync or spawnSync (args array — no execSync with shell strings)
- All logic must be wrapped in try/catch; catch always exits 0
- After editing: verify exit codes match documented cases, no shell injection surface added
Write all changes using the Edit tool.
Return ONLY: {"status":"done","file":".claude/hooks/<name>.js","edits":N,"confidence":0.N}
Mode: Delete Hook
rm .claude/hooks/<name>.js # timeout: 5000
After deleting the hook file, also remove its entry from .claude/settings.json so Claude Code does not invoke a missing script. Identify the hook's matcher pattern (the entry's matcher field, or command substring containing the deleted filename) and run jq to strip every block referencing it. Substitute <name> with the deleted hook's basename (no .js suffix):
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
# timeout: 5000
HOOK_NAME="<name>" # e.g. "rtk-rewrite" — no .js suffix
echo "$HOOK_NAME" > "${TMPDIR:-/tmp}/manage-hook-name-${CSID}"
python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/remove_hook_from_registry.py" \
--json-file .claude/settings.json \
--hook-name "$HOOK_NAME" \
--path-pattern "\\.claude/hooks/${HOOK_NAME}\\.js"
Verify the entry is gone:
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
IFS= read -r HOOK_NAME < "${TMPDIR:-/tmp}/manage-hook-name-${CSID}" 2>/dev/null || HOOK_NAME=""
jq --arg hook "$HOOK_NAME" '[.. | objects | select(.command? // "" | test($hook + "\\.js"))] | length' .claude/settings.json # timeout: 5000
# Expected output: 0
Also update plugin hooks.json registry — if the deleted hook was registered in the foundry plugin's own hooks.json, /foundry:setup would re-add it to settings.json on the next sync, resurrecting a broken reference. Strip the matching entry from the plugin registry too:
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
# timeout: 5000
IFS= read -r HOOK_NAME < "${TMPDIR:-/tmp}/manage-hook-name-${CSID}" 2>/dev/null || HOOK_NAME=""
PLUGIN_HOOKS_JSON="${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/hooks/hooks.json"
if [ -f "$PLUGIN_HOOKS_JSON" ]; then
python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/remove_hook_from_registry.py" \
--json-file "$PLUGIN_HOOKS_JSON" \
--hook-name "$HOOK_NAME" \
--path-pattern "${HOOK_NAME}\\.js"
jq --arg hook "$HOOK_NAME" '[.. | objects | select(.command? // "" | test($hook + "\\.js"))] | length' "$PLUGIN_HOOKS_JSON" # expected: 0
else
printf " (no plugin hooks.json at %s — skipping registry cleanup)\n" "$PLUGIN_HOOKS_JSON"
fi
Mode: Add Permission
Adds rule to both settings.json and permissions-guide.md atomically.
-
Determine guide category from rule prefix:
WebSearch→## WebWebFetch(domain:...)→## WebFetch — allowed domainsWebFetch(bare, no domain) →## WebFetch — allowed domainsAgent(subagent_type:*)→## Shell utilities(agent dispatch rules)mcp__*→## Shell utilities(MCP tool rules)Bash(gh ...)→## GitHub CLI — read-onlyBash(git log:*),Bash(git show:*),Bash(git diff:*),Bash(git rev-*:*),Bash(git ls-*:*),Bash(git -C:*),Bash(git branch:*),Bash(git tag:*),Bash(git status:*),Bash(git describe:*),Bash(git shortlog:*)→## Git — read-onlyBash(git add:*),Bash(git checkout:*),Bash(git stash:*),Bash(git restore:*),Bash(git clean:*),Bash(git apply:*)→## Git — local writeBash(pytest:*),Bash(python ...),Bash(ruff:*),Bash(mypy:*),Bash(pip ...)→## Python toolchainBash(brew ...),Bash(codex:*)→## macOS / ecosystem- All other
Bash(...)→## Shell utilities
-
Update
settings.json— atomic jq edit via shared helper:# timeout: 15000 python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/jq_write.py" .claude/settings.json '.permissions.allow += [$rule]' --arg rule "<rule>" -
Also append to plugin's
permissions-allow.jsonso/foundry:setupsyncs it to~/.claude/settings.jsonon reinstall:# timeout: 5000 PERM_FILE="${CLAUDE_PLUGIN_ROOT}/.claude-plugin/permissions-allow.json" if [ -f "$PERM_FILE" ]; then python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/jq_write.py" "$PERM_FILE" '. += [$rule] | unique' --arg rule "<rule>" fi -
Update
permissions-guide.md— append new row to end of correct section (before its trailing---separator). New row format:| `<rule>` | <description> | <use case> |Use Edit tool to insert row: find last table row in target section and insert after it.
-
Verify both files updated:
# timeout: 5000 python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/verify_perm.py" "<rule>" .claude/settings.json .claude/permissions-guide.md present # Exits 0 if both consistent; prints "settings: OK|MISSING" + "guide: OK|MISSING"
Mode: Remove Permission
Removes rule from both settings.json and permissions-guide.md atomically.
-
Update
settings.json— atomic jq edit via shared helper:# timeout: 15000 python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/jq_write.py" .claude/settings.json 'del(.permissions.allow[] | select(. == $rule))' --arg rule "<rule>" -
Update
permissions-guide.md— use Edit tool to remove table row containing`<rule>`. -
Verify both files clean:
# timeout: 5000 python "${CLAUDE_PLUGIN_ROOT:-plugins/cc_foundry}/bin/verify_perm.py" "<rule>" .claude/settings.json .claude/permissions-guide.md absent # Exits 0 if both consistent; prints "settings: OK|STILL_PRESENT" + "guide: OK|STILL_PRESENT"
Step 5: Propagate cross-references
Search all .claude/ markdown files for changed name and update references:
Use Grep to find all references:
- Pattern
<name>, globagents/*.md, path.claude/, output modecontent - Pattern
<name>, globskills/*/SKILL.md, path.claude/, output modecontent - Pattern
<name>, globrules/*.md, path.claude/, output modecontent - Pattern
<name>, file.claude/CLAUDE.md, output modecontent - Pattern
<name>, fileREADME.md, output modecontent
For update (rename): Count files grep returns. ≤ 3 files: apply inline with Edit tool. > 3 files: spawn foundry:curator subagent. For hook renames: also update hook entry in .claude/settings.json hooks array if hook filename referenced there by path.
Apply these cross-reference updates (<old-name> → <new-name>):
<list each file path with the required substitution>
Use the Edit tool for each file (replace_all: true where appropriate).
Return ONLY: {"status":"done","files_updated":N}
For delete: Review each reference. Deleted name in:
- Cross-ref suggestion — remove or replace with closest alternative
- Inventory list — remove entry
- Workflow spawn directive — flag for manual review
For create: No cross-ref propagation needed.
For content-edit: Run propagation only if entity's description: frontmatter changed — propagate new description to any MEMORY.md or README summary lines that quote it. Skip if only internal content changed.
Rename occurrence validation (rename mode only)
After cross-reference propagation, scan for remaining occurrences using word-boundary matching to reduce noise from short or common names:
rg --fixed-strings -n '\b<old-name>\b' plugins/ .claude/ README.md docs/ 2>/dev/null \
|| grep -rn "\b<old-name>\b" plugins/ .claude/ README.md docs/ 2>/dev/null \
| grep -v ".git/" | grep -v "__pycache__" # timeout: 10000
Grep returns zero hits: report "✓ No remaining occurrences of <old-name> found." and proceed.
Large hit set gate — hits exceed 50: invoke AskUserQuestion before classifying: "Found N occurrences of <old-name> — this name may be too generic for safe automated classification. Proceed with classification or abort?" Options: (a) Proceed · (b) Abort. On abort: stop and report to user.
Hits within limit: read a 5-line context window (2 lines before + matched line + 2 lines after) for every hit using the Read tool, assign each hit a stable integer id (1…N). Then spawn a haiku-model Agent to classify in batches of ≤30 hits — pass model="haiku" explicitly. Before spawning, resolve the entity's canonical surface forms from the rename context: slash-command form (`/foundry:<old-name>` or `/<old-name>`), subagent_type value, file-path pattern (.claude/agents/<old-name>.md, .claude/skills/<old-name>/). Include these in the prompt as <entity_context>.
Haiku agent prompt (one spawn per batch of ≤30 hits):
Classify grep hits for a rename: `<old-name>` → `<new-name>` (type: <agent|skill|rule|hook>).
Canonical surface forms for this entity: <entity_context>
For each hit output exactly one JSON object per line (no prose):
{"id":<N>,"file":"...","line":<N>,"verdict":"genuine"|"false_positive"|"ambiguous","reason":"one sentence"}
Classification rules — word match alone is NOT sufficient; read context:
- genuine: matches a canonical surface form; clearly names this specific entity (slash-command, subagent_type, NOT-for/TRIGGER cross-ref, dispatch directive, README table row)
- false_positive: generic English word used differently, unrelated comment, example string, sentence where the word means something else entirely
- ambiguous: context too short, name too generic, or evidence conflicts
Hits:
--- HIT {id} ---
file: {file}
line: {line}
context:
{line-2}: ...
{line-1}: ...
> {line}: <matched line>
{line+1}: ...
{line+2}: ...
JSON parse fallback: returned output contains malformed JSON or missing id fields → retry once with the parse error appended to the prompt. On second failure, mark all unresolved hits "ambiguous" and escalate to the user.
Collect all batch results. Classify each hit:
- Genuine reference → Apply Edit tool fix targeting the exact token at the classified line — do NOT use
replace_all: trueon the whole file; replace only the specific occurrence on that line. - False positive → Skip; log haiku's reason.
- Ambiguous → Collect for user escalation.
After all haiku fixes applied and all user-resolved fixes applied, run one final grep to confirm:
rg --fixed-strings -n '\b<old-name>\b' plugins/ .claude/ README.md docs/ 2>/dev/null \
|| grep -rn "\b<old-name>\b" plugins/ .claude/ README.md docs/ 2>/dev/null \
| grep -v ".git/" | grep -v "__pycache__" # timeout: 10000
Remaining hits must exactly equal the documented false-positive set (by file+line). Any remaining hit not in the false-positive list is an unresolved genuine reference — loop through classification once more for those, or flag in Step 10 as requiring manual review.
Collect ambiguous hits and invoke AskUserQuestion — show file + 5-line context per hit, ask: "Is this a real reference to <old-name> that should be updated, or a false positive?" Batch max 4 per call; loop if more. Apply user-confirmed fixes before the final grep.
Step 6: Update MEMORY.md roster (auto-memory)
MEMORY.md is Claude Code's auto-memory file — not stored under .claude/. Injected into conversation context at session start. Absolute path appears near top of system prompt (e.g. ~/.claude/projects/.../memory/MEMORY.md). Use that absolute path with Edit tool. If system prompt parsing fails or path absent, fall back to:
# Claude Code auto-memory: / and . → - for path slugs
MEMORY_FALLBACK=~/.claude/projects/$(pwd | sed 's|[/.]|-|g' | sed 's/^-//')/memory/MEMORY.md
[ -f "$MEMORY_FALLBACK" ] && echo "Fallback MEMORY.md: $MEMORY_FALLBACK" || echo "MEMORY.md not found at fallback path — skip roster update" # timeout: 5000
Regenerate inventory lines from disk:
Use Glob (agents/*.md, path .claude/) for agents, Glob (skills/*/, path .claude/) for skills, Glob (rules/*.md, path .claude/) for rules. Extract names inline from returned paths (strip path prefix and .md/trailing-/ suffix), join as comma-separated string.
Use Edit tool with absolute auto-memory path to update these roster lines in MEMORY.md:
- Agents: doc-scribe, foundry:sw-engineer, ...- Skills: review, research, ...- Rules (N): artifact-lifecycle, ...(update count N when rules created or deleted)
For content-edit: Skip if only internal content changed; update only if description changed.
Step 7: Update README.md
README.md (project root):
- create agent: add row to
### Agentstable — columns:| **name** | Short tagline | Key capabilities | - create skill: add row to
### Skillstable — columns:| **name** | \/name` | Description |` - update (rename): find and replace old name in table row
- delete: remove row for deleted name
.claude/README.md (config README) — Rules table only:
- create rule: add row to Rules reference table — columns:
| rule-file | Applies to | What it governs | - update rule (rename): replace old name in Rules table row
- update rule (content-edit): update "What it governs" column if rule's description changed
- delete rule: remove row for deleted rule
Keep descriptions concise (one line), consistent in tone with surrounding rows. Do not add/remove table columns.
For content-edit (agent/skill): Update README if description OR model field changed. Model changes update the Model column only; description changes update the description column.
Step 8: Verify integrity
Confirm no broken references remain:
Use Grep (pattern [a-z]+:[a-z]+(-[a-z]+)* to find cross-plugin references, or See [a-z-]+ agent for cross-references, glob {agents/*.md,skills/*/SKILL.md}, path .claude/, output mode content). Avoid broad kebab-case patterns — they match code examples and produce false positives.
Use Glob (agents/*.md, path .claude/) and Glob (skills/*/, path .claude/) for on-disk inventory; extract names inline. Use Grep to search for changed name and confirm:
- Update (rename): zero unresolved genuine references to old name; documented false positives (accepted by user in Step 5 validation) may remain and must be listed in Step 10
- Delete: zero hits for deleted name (or flagged references noted)
- Create: new file exists with valid structure
- Content-edit: target file has valid structure (XML tag balance for agents/skills; YAML frontmatter for rules)
Add rules to on-disk inventory check: Glob (rules/*.md, path .claude/), extract names inline.
For create and update (rename): verify tool efficiency — cross-check agent/skill's declared tools (tools: or allowed-tools:) against tool names in workflow body. Declared tool not referenced anywhere → flag as cleanup candidate in Step 10 report (report only — do not block operation).
Step 9: Audit and calibrate
Invoke Skill(skill="foundry:audit", args="--skip-gate") to validate created/modified files without triggering interactive follow-up gate (requires foundry plugin). Skip if invoked with --skip-audit or if current manage operation runs inside audit-initiated fix session — outer audit covers it.
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
IFS= read -r _SKIP_FILE < "${TMPDIR:-/tmp}/manage-skip-audit-path-${CSID}" 2>/dev/null || _SKIP_FILE="${TMPDIR:-/tmp}/manage-skip-audit-${CSID}"
IFS= read -r SKIP_AUDIT < "$_SKIP_FILE" 2>/dev/null || SKIP_AUDIT="false" # reload (Check 41)
[[ "$SKIP_AUDIT" == "true" ]] && { echo "[--skip-audit] skipping Step 9 audit"; }
For targeted check of only affected file, spawn foundry:curator directly:
- For
create: audit new file for structural completeness, cross-ref validity, content quality - For
update: audit renamed file, verify no stale references remain - For
delete: audit remaining files for broken references to deleted name
Include audit findings in final report. Do not proceed to sync if any critical findings remain.
Calibration — invoke Skill(skill="foundry:calibrate", args="<name>") after audit passes (requires foundry plugin). Mandatory only when the edit changes the routing surface — an agent/skill description: field, or a TRIGGER/SKIP/NOT-for line. For pure body/prose edits that leave the routing surface untouched (workflow steps, examples, <notes>, wording polish), calibration is optional — suggest it, don't force it. Routing accuracy is unaffected by non-routing edits, so the 10–30 min run rarely pays off; skipping keeps small polishes cheap.
Then, only when the routing surface changed, invoke Skill(skill="foundry:calibrate", args="routing --fast") to confirm overall routing accuracy unaffected (requires foundry plugin). Skip this for pure body/prose edits.
Skip calibration entirely for: trivial edits, renames, deletes, rule operations, perm operations.
Step 10: Summary report
- Operation: what was done (create/update/delete + type + name, or add/remove perm + rule)
- Files Changed: table of file paths and actions (created/renamed/deleted/cross-ref updated/appended/removed)
- Cross-References: count of files updated, broken refs cleaned (n/a for perm operations)
- Rename Occurrence Validation (rename mode only): three buckets — Fixed (N genuine references updated, list files) · False positives (N skipped, list file + one-line reason each) · User-resolved (N ambiguous, list file + user decision); if any genuine references could not be cleanly resolved, flag explicitly as requiring manual review
- Current Roster: agents (N) and skills (N) with comma-separated names (n/a for perm operations)
- Audit Result: audit findings (pass / issues found) (n/a for perm operations)
- Calibration Result: recall score and routing accuracy from Step 9 (n/a for trivial edits, renames, deletes, perms, and pure body/prose edits that left the routing surface untouched — note calibration was suggested-but-skipped in that case)
- Follow-up: perm ops → confirm both
settings.jsonandpermissions-guide.mdupdated; run/foundry:setupto sync~/.claude/
End response with ## Confidence block per CLAUDE.md output standards.
Challenger review gate — after emitting the summary report and Confidence block, invoke AskUserQuestion to offer adversarial review of the just-completed changes. Skip this gate entirely when: MODE is delete, add-perm, or remove-perm; OR EDIT_TRIVIAL=true; OR MODE is rename (structural change only, no content to challenge). Gate is mandatory for: create (agent, skill, rule), non-trivial content-edit (agent, skill, rule).
AskUserQuestion: "Run foundry:challenger to adversarially review the changes just made?"
(a) Skip — done [default]
(b) Challenge — spawn foundry:challenger on modified file(s)
On (b): spawn foundry:challenger inline (foreground, not background):
Agent(subagent_type="foundry:challenger", prompt="Adversarially review the changes just made to <list modified file paths>. Challenge: correctness of design decisions, completeness, potential regressions, and whether the stated goal was achieved. Read-only. Write full findings to .temp/manage-challenger-<YYYY-MM-DD>.md using the Write tool. Return ONLY: {\"status\":\"done\",\"file\":\".temp/manage-challenger-<YYYY-MM-DD>.md\",\"findings\":N,\"confidence\":0.N}")
Print challenger's findings count and confidence; note any HIGH findings that warrant a follow-up /manage update pass. On (a): print → Done. and stop.
Cycle guard: this challenger dispatch is from the orchestrator (manage skill itself), not from a sub-agent — cycle detection in <notes> does not apply here. Do NOT spawn challenger from inside foundry:curator or foundry:sw-engineer sub-agents spawned by manage.
- Atomic updates: write-before-delete prevents data loss on interruption; perm ops must update both
settings.jsonandpermissions-guide.md - settings.json format: jq with atomic tmp-file pattern (
jq ... > .tmp && mv .tmp dest) — avoids fragile sed/awk on JSON; indent=2 viajq --indent 2when formatting required - README.md tables: agent/skill tables in project
README.md; rules table in.claude/README.md— keep row format consistent with existing rows - No auto-edit for agent/skill/rule operations: skill does not mutate settings.json for non-perm operations
- Color pool: AVAILABLE_COLORS lists unused colors; if exhausted, reuse with note
- Inline bash / extraction gate + prose compression: before writing any fenced bash block directly into a
.mdfile (agent, skill, rule) via Edit/Write, apply two checks frombin-authoring-guide.md: (1) extraction gate — verdict MEDIUM or HIGH → write abin/script instead; verdict LOW → inline is acceptable; (2) Prose over Code — iftokens(block) > tokens(equivalent prose/table/schema)at identical precision → write prose/table instead. Exempt: examples, templates, exact-syntax blocks. Same rules enforced in spawn prompts to foundry:curator and foundry:sw-engineer (see Content-Edit Agent/Skill modes). This note applies to orchestrator-level inline edits. - Cycle detection: sub-tasks spawned by manage (foundry:sw-engineer, foundry:curator, foundry:doc-scribe) must not invoke manage again. Circular dispatch — manage→sw-engineer→curator→manage — causes infinite loops. If a sub-task needs manage capabilities, surface the need back to the orchestrator; never chain manage from inside a manage-spawned sub-agent.
- Follow-up chains:
- create or non-trivial update of agent/skill →
Skill(skill="foundry:audit", args="--skip-gate")→Skill(skill="foundry:calibrate", args="<name>")(mandatory) →Skill(skill="foundry:calibrate", args="routing --fast") - trivial update or rename or delete →
Skill(skill="foundry:audit", args="--skip-gate")→Skill(skill="foundry:calibrate", args="routing --fast")(if description changed) - add/remove perm → confirm both files updated; run
/foundry:setup
- create or non-trivial update of agent/skill →