manage

SkillAI & models

Manage Codex agents, skills, or config entries: create, update, or remove with guardrails.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the manage skill

What this skill tells your AI

The instructions your AI receives, as published by borda/ai-rig in plugins/codex-rig/skills/manage/SKILL.md and read by ahel’s review.

Note: disable-model-invocation: true/manage user-invoked only, no Skill() chaining from orchestrators. When suggesting /manage as 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 content
    • create skill <name> "description" — create new skill with workflow scaffold
    • create rule <name> "description" — create new rule file with frontmatter and sections
    • update <name> <new-name> — rename; type auto-detected from disk
    • update <name> "change description" — content-edit; trivial → inline, .md → foundry:curator, code → foundry:sw-engineer, rule → inline
    • update <name> <spec-file.md> — content-edit from spec file; trivial → inline, .md → foundry:curator, code → foundry:sw-engineer, rule → inline
    • delete <name> — delete; type auto-detected from disk (agents, skills, rules, hooks); asks user if ambiguous
    • add perm <rule> "description" "use case" — add permission to settings.json allow list and permissions-guide.md
    • remove 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 /audit validation (use inside audit fix loop to avoid recursion)

  • Spec-file paths must be quotedupdate <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 .md extension) → 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 .mdcontent-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.

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 invoke AskUserQuestion — (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 update rename: 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 for update and delete only; create hook not yet implemented (use Edit tool on hooks/<name>.js directly 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 shapeMODE
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:

ConditionRequired
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:

  1. Read descriptions of all existing agents (use Read(file_path=..., limit=3) on each .md in agents/) and skills (use Read(file_path=..., limit=3) on each SKILL.md)
  2. Compare new description against each existing — look for domain overlap, similar workflows, redundant scope
  3. 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

  1. 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-agents with 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 §8b: <ID> = web-explorer, glob agent-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. maxTurns for long-running agents), include with sensible default and inline comment.
  2. Pick first unused color from AVAILABLE_COLORS pool (compare against Step 3 colors)

  3. 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 (requires research plugin), 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
  4. Resolve template path (cascade primary → project-local → cache scan; only the cache scan runs if neither cheaper path exists, since each candidate must satisfy -d before 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
  1. Spawn foundry:sw-engineer subagent to scaffold and write the agent file. foundry:curator is the wrong delegate here — its NOT-for explicitly excludes creating or scaffolding agents/skills; curator only reviews and edits existing config. foundry:sw-engineer owns scaffolding (treat agent .md as 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 §8b: <ID> = sw-engineer-agent, 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

  1. 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/skills with 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 §8b: <ID> = web-explorer-skill, 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 model or context: fork only when skill's purpose clearly benefits.
  2. Re-resolve MANAGE_TPL at 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 -d guards) before reading any template path.

  3. Resolve $_FOUNDRY_SHARED before 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"` (Bash tool; substitute resolved `$_FOUNDRY_SHARED`, echoed as `"Shared dir: <path>"`) and follow it — before any fenced code block in the new SKILL.md: extraction gate (verdict MEDIUM/HIGH → bin/ script instead), §Prose over Code check, §Script Output Routing for multi-value bin/ scripts.
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 §8b: <ID> = sw-engineer-skill, glob matching this agent's output files.

Mode: Update Agent (rename)

Atomic rename — write new file before deleting old:

  1. Read .claude/agents/<old-name>.md using the Read tool.

  2. Write new file to .claude/agents/<new-name>.md using the Write tool (copy content of old file with name: line updated to <new-name>).

  3. 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:

  1. Create new directory:

    mkdir -p .claude/skills/<new-name>  # timeout: 5000
    
  2. 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.

  3. 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 extensionAgent
.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):

  1. Read file using Read tool
  2. Apply directive directly using Edit tool — no agent spawn
  3. 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

  1. Determine change directive:
    • Quoted description → use as-is
    • Spec file path → Read spec file; use content as directive
  2. 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 $VAR reference:
_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"
  1. 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
- Fenced code block added → run `cat "<_FS_VAL>/bin-authoring-guide.md"` (Bash tool), apply extraction gate (verdict MEDIUM/HIGH → bin/ script instead), §Prose over Code check, §Script Output Routing for multi-value bin/ scripts (all in guide just loaded)
- 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}

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
27
Forks
4
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
manage
Source
github.com/borda/ai-rig