Skip to content

feat(skill-writer): add skill-writer CLI (test / ask / clean) #28

@pixelastic

Description

@pixelastic

Problem Statement

When developing or updating a skill, the skill-writer agent needs to run isolated subagents to observe failures and verify compliance. Today there is no scripted way to do this — the agent must manually manage git worktrees, session continuity, and output capture, which is error-prone and not reproducible.

Solution

A skill-writer zsh script with three subcommands (test, ask, clean) that automates the lifecycle of a test scope: creating an isolated environment, running a fresh subagent, continuing the conversation for diagnosis, and cleaning up when done.

User Stories

  1. As a skill-writer agent, I want to run a fresh subagent in an isolated worktree with a named scope, so I can observe failure firsthand during RED phase.
  2. As a skill-writer agent, I want each test call to start with a fresh subagent (no inherited context, no memory of previous runs), so previous iterations don't contaminate the baseline.
  3. As a skill-writer agent, I want to inject a skill file into the subagent's prompt via --skill, so the subagent receives the exact skill content without relying on path resolution.
  4. As a skill-writer agent, I want all subagent output recorded in history.jsonl, so I have a source of truth for what happened in the scope.
  5. As a skill-writer agent, I want to continue the conversation with the subagent from the last test run, so I can ask it why it didn't follow the skill.
  6. As a skill-writer agent, I want ask output appended to history.jsonl, so the full interaction history (test + follow-up questions) is in one place.
  7. As a skill-writer agent, I want the scope path to be predictable from the scope name, so I don't need to parse script output to find the worktree or history.
  8. As a skill-writer agent, I want test to recreate the scope cleanly if it already exists, so I can rerun without manually cleaning up first.
  9. As a skill-writer agent, I want to clean up a scope explicitly when done, so the worktree, branch, and scope directory are fully removed.
  10. As a skill-writer agent, I want the worktree created from a specific repo (--dir), so tests run against the right codebase.
  11. As a skill-writer agent, I want the script to clean up the worktree automatically if test crashes, so no orphaned worktrees accumulate.
  12. As a user, I want the SKILL.md to reference the correct --scope flag and updated paths, so the instructions remain accurate.
  13. As a skill-writer agent, I want no model specified, so test and ask use the same default model and reason consistently.
  14. As a skill-writer agent, I want the subagent to run without --bare, so the test reflects real usage conditions (CLAUDE.md loaded, hooks active).

Implementation Decisions

  • Single zsh script at config/ai/claude/claudecode/skills/skill-writer/skill-writer, with three subcommands dispatched internally.

  • Scope directory structure:

    ~/local/tmp/claude/skill-writer/<scope>/
      worktree/        ← git worktree (isolated repo)
      history.jsonl    ← stream-json output, created by test, appended by ask
    
  • Git branch name: skill-writer/<scope> — namespaced to avoid collisions.

  • skill-writer test behavior:

    1. If ~/local/tmp/claude/skill-writer/<scope>/ exists: clean it (worktree remove, branch delete, rm -rf) before recreating.
    2. Create ~/local/tmp/claude/skill-writer/<scope>/worktree/ as a git worktree from --dir (default: cwd), branch skill-writer/<scope>.
    3. If --skill <path>: build prompt as @/absolute/path/to/SKILL.md\n\n<prompt>. The @filepath syntax is processed by the claude CLI and injects the file content. Validated: works in --print mode.
    4. Run claude --dangerously-skip-permissions --print --output-format stream-json "<prompt>" in the worktree.
    5. Write stdout to history.jsonl (create/overwrite).
    6. Trap on EXIT/INT/TERM to clean up the worktree if the script crashes.
    7. No output on stdout — the parent agent derives the history path from the scope name.
  • skill-writer ask behavior:

    1. Run claude --dangerously-skip-permissions --continue --print --output-format stream-json "<prompt>" in the worktree.
    2. Append stdout to history.jsonl.
    3. No output on stdout.
  • skill-writer clean behavior:

    1. git worktree remove --force ~/local/tmp/claude/skill-writer/<scope>/worktree/
    2. git -C <dir> branch -D skill-writer/<scope>
    3. rm -rf ~/local/tmp/claude/skill-writer/<scope>/
  • Shared internal function _run_claude handles the common claude invocation + redirect. test passes no --continue; ask passes --continue.

  • No --model flag on either test or ask — uses the configured default so both subcommands reason with the same model.

  • No --bare flag — tests run under real conditions (CLAUDE.md loaded, hooks active).

  • SKILL.md update: replace --name with --scope, fix worktree path from ~/local/tmp/claude/skill-writer/<name> to ~/local/tmp/claude/skill-writer/<scope>/worktree/, update all command references.

Testing Decisions

No automated tests. The skill-writer script is itself validated through the TDD cycle it enables — if it works correctly, the RED/GREEN/PRESSURE loop produces reliable results.

Out of Scope

  • --output-format stream-json parsing or pretty-printing — the parent agent reads history.jsonl as-is.
  • Interactive mode — always non-interactive.
  • Multi-repo support — --dir targets a single repo per scope.
  • Listing active scopes — the parent agent can ls ~/local/tmp/claude/skill-writer/ directly.

Further Notes

  • @filepath syntax in --print mode was validated: claude --print "@/path/to/file\n\nprompt" correctly injects file content. No need to embed skill content manually.
  • --continue targets the most recent session in the worktree directory. Since each scope has its own worktree, there is no ambiguity.
  • Domain glossary: config/ai/claude/claudecode/skills/skill-writer/CONTEXT.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentReady to be picked up by an agent

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions