agentleFS
lbdremylbdremy/phax/.claude/skills/phax-cli/SKILL.md

phax-cli

Skill2 starsChanged 5 months agoApache-2.0View on GitHub

Operate the phax CLI — its concepts, run lifecycle, and the canonical init → plan → run → review → publish flow. Use when driving phax, explaining it to a developer, or scripting against it. Defers to `phax --usage` for the exact command/flag contract.

The file

We split this skill into the rules it gives an agent

2 rules. About 0 are common, 0 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    When the operator exits, phax asks the session for the revised document, checks it, prints the body diff, and writes and commits the …

    line 188
  2. Very specific:

    When unsure about any command, read its long_help and example in phax --usage.

    line 245

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

phax CLI skill

This skill is the map, not the territory. For the exact, version-accurate command/flag/argument contract — every command, its flags, args, examples, and help — run:

phax --usage              # KDL spec, source of truth, no external dependency
phax --usage-format json  # same contract as JSON (needs the `usage` CLI)

--usage is generated from the CLI's own command tree, so it never drifts from the installed binary. Don't memorize or restate flags here — read --usage. This skill only covers what --usage can't express: the concepts, the run lifecycle, and how commands fit together.

What phax is

A deterministic, local CLI that drives an AI coding agent (Claude Code by default; also Mistral Vibe and OpenAI Codex) through isolated, gated phases. Each phase runs in its own Git worktree, executes the agent, then runs a gate profile (typecheck, tests, lint, …) with a same-session fix loop — the agent fixes gate failures in the same context before the phase may commit. The final phase worktree stays open for human review. phax pushes the branch and opens a PR only when phax.json sets publish.auto, or when you run phax publish-pr.

Run lifecycle — the command you reach for depends on the state

Runs live in a local registry (~/.phax/runs/), are addressed by a short-name (e.g. usage-cli), and move through:

created → running → review_open → archived → (prune) gone
                 ↘ failed
  • created / running — phases executing. After an interruption, continue with resume.
  • failed — a phase failed and the loop stopped. Inspect with session-info (or enter-phase to attach to the uncommitted worktree), then reset-phase to clear it and resume to re-run from there.
  • review_open — all phases committed; the final worktree is open and waiting for a human. This is where you enter / shell / open to review, optionally review-compliance, then publish-pr and finally archive.
  • archived — the run folder and worktrees are moved under ~/.phax/archive, and the name stays held. phax prune deletes the run for real and frees its name and disk space. Archived is no longer terminal: prune is the step that removes it.

Most review commands have a …-last variant that targets the most recent review_open run, so you can drop the short-name (see --usage).

Canonical end-to-end flow

phax init                          # scaffold phax.json
# author plan.md  → use the `phax-planning` skill for its format (status: Approved)
phax plans lint plan.md            # check structure, planned files, run readiness
phax run my-feature --plan plan.md # extract plan + run every phase → review_open
phax enter my-feature              # review/iterate in the kept-open agent session
phax publish-pr my-feature         # push branch + open a PR (needs gh)
phax archive my-feature            # finish
phax prune my-feature              # optional: delete the archived run and free its name

phax run extracts the plan inline; phax plans lint <plan> checks a plan's structure, planned files and run readiness without running it. Each phase requests a model + effort that phax resolves to a concrete provider — inspect routing under phax agent (see --usage).

Plans that touch .claude/skills/ files need phax run --allow-skill-edits; without it the preflight refuses (exit 11). phax resume inherits the consent, and the grant is recorded per phase in security.json (skillEditGrants). See --usage for the flag contract.

Inside a phase worktree — the phase guard

A phase worktree is a linked Git worktree whose root holds .phax-context/. Run from anywhere inside one, phax refuses every command that acts on phax state or on an artifact's lifecycle, before the command runs, and names the main checkout as the place to run it. That covers run, resume, archive, publish-pr, review-*, artifact approve/new/decide/…, plans status --apply, and also enter, shell and open. What still runs inside:

  • phax brief [path…];
  • phax architecture [path…];
  • the read-only commands: validate, ls, path, session-info, completions, plans lint, plans overview, plans status, artifact status, artifact schema, records explain, records status, records list, security status;
  • schema upgrade, which writes only the working tree's local schemas.

The guard has no flag or environment variable to turn it off, and it catches people too: in phax shell or the kept-open final phase, leave the worktree to run review-compliance or publish-pr. It is accident-proofing, not a security boundary; the sandbox's write scope is the boundary.

Gate steps, briefs and records

These are phax.json keys (brief, architecture, assignments, …) rather than commands, so --usage does not show them. The README (sections Gate report steps, Gate request, Brief provider, Architecture provider, Plan auditor) holds the exact formats.

  • "output": "gate-report" on a gate step: the step prints a gate report on stdout, and phax reads the verdict from it, not from the exit code. A checked report carries findings (rule, location, message, related locations, and a guide file the agent reads) and review notes; any finding fails the step, and the findings are what the agent is asked to fix. Review notes fail nothing and go to the review handoff, never the agent. A refused report (reason and remedy) stops the phase with exit 4 and no fix attempt; phax resume runs the gate again. Each readable report is saved as checks-attempt-NN.report-SS.json.
  • "input": "gate-request" on a gate step: the step gets {$schema, phase, base, terminal, phases} on stdin, the facts it needs to decide what is due now and what a later phase is planned to bring. Each attempt's request is saved as checks-attempt-NN.request.json; phax records explain <commit> --gates prints it after its log.
  • brief (command and push, both required): the provider answers with a brief report, the rules over some paths and the findings there with their due. It is pushed into a phase's first prompt and pulled with phax brief [path…], which prints the whole report, from inside a phase or from your own checkout. push chooses what the first prompt lists: "findings" (the findings due in this phase) or "findings-and-rules" (those findings, then the rules over the phase's planned files). A brief never blocks; the gate still decides. In secure mode the phase agent is granted phax brief (source brief in security.json). Each brief is recorded as brief-NN.json; phax records explain <commit> --briefs prints them.
  • architecture (command, required): a provider that answers phax architecture [path…] with an architecture report (body plus parts: id, name, description, globs) that phax renders to Markdown. The command lists the assignment bounds after the parts. With none configured, it prints one line telling the agent to read the code and its documentation, followed by the bounds when they are declared, and exits 1. It writes nothing, and a headless plan session is granted it when a provider or bounds are configured.
  • assignments (phax.json only, never the user overlay): the owner's ordered bounds, each a part (an architecture-report part id) or globs bound with one model and an effort range. The first bound matching any file a phase plans to touch governs it; a departure needs an **Assignment reason:**. phax plans lint and the run's start preflight hold plans to the bounds (exit 11 on a refusal); phax validate checks the bounds against the routing catalog (exit 2).
  • planAuditor (a provider command): advisory findings for phax plans lint, never during a run.

Artifact lifecycle — specs and plans carry an enforced status

Specs (docs/specs/) and plans (docs/plans/) each carry a status key in their YAML frontmatter block, drawn from a fixed per-kind set (specs: Draft, Approved, Abandoned, Completed; plans add Stale). phax enforces the one gate that matters: only an Approved plan can run — phax run refuses a Draft, Stale, or retired (Abandoned/Completed) plan, naming the status and the remedy, before extraction. Extraction itself stays ungated, so you can still preview a draft's phax-plan.json.

The phax artifact command group inspects and moves lifecycle status through its legal transitions (see --usage for the exact subcommands and flags):

  • phax artifact status <path> — report an artifact's kind, current status, and legal transitions. It also prints a Questions: line when the artifact has question sections: the count, the open questions with their ids, and the arbitrated ones with how many are lifted (Questions: 4 — open 2 (Q3, Q4) · arbitrated 2 (1 lifted)). A headless spec with a valid sidecar always prints it, a plan only when it has questions; a hand-authored §9 that departs from the §9 format prints the first departing line instead, and status still exits 0. A headless sidecar stamped below its format's current shape, or written before $schema, is not compared: the Authored: line names its stamped shape and phax artifact migrate-documents.
  • phax artifact approve [--by <arbiter>] <path> — the Draft → Approved gate; run it on a plan under docs/plans/ before phax run. Approving stamps approved: { date, baseline } into the frontmatter and writes the artifact's own record file (docs/plans/approvals/<plan file name>.json for plans, docs/specs/approvals/<spec file name>.json for specs). --by operator or --by machine:<grant> (a kebab-case slug) says who approves; the record file's approvedBy names them. From a terminal, --by defaults to the operator, named as git commits (GIT_COMMITTER_NAME, else user.name); with no terminal and no --by, approve refuses with exit 12, so a loop or script must pass --by machine:<grant>. An operator approval with neither name set also refuses with exit 12 (git config user.name). A record written before attribution reads as unattributed and is never rewritten by a read. Re-approving an already-Approved artifact is legal — it re-records the approval against the current content, the correct way to log an in-place revision (don't hand-edit the stamp). Approving a plan whose Source-Spec is an Approved spec that is unrecorded or edited since its approval is refused with exit 12 — re-approve the spec first.
  • phax artifact stale / reopen — mark a plan Stale, or reopen an Approved spec or plan, or a Stale plan, back to Draft. Reopen clears the approved stamp, deletes the record file, takes --by like approve (same terminal default and no-terminal refusal), and writes a Reopened-By: machine (<grant>) / operator (<name>) trailer in its commit. Reopening a spec names its bound plans and leaves them unchanged. A Draft, Completed or Abandoned artifact is refused with exit 12.
  • phax artifact decide [--question <id>] [--doctrine <file>] [--model <m>] [--effort <e>] <path> — decide a Draft spec's or plan's open questions in an interactive Claude Code session (the verdicts form is below). The agent raises the framing questions F1–F5, then presents the open questions; the operator decides. When the operator exits, phax asks the session for the revised document, checks it, prints the body diff, and writes and commits the artifact and its sidecar only after the operator accepts (a declined diff writes nothing and exits 0). --question <id> presents one question alone, open or arbitrated; a new verdict keeps the old one in its history. The flow is status → decide → approve, and to revisit a decision reopen → decide --question <id>. decide needs a terminal (exit 12 without one), a Draft artifact (an Approved one names phax artifact reopen), and a Claude model; it is refused inside a phase worktree, and never runs inside a run. The doctrine is the phax-decide-spec or phax-decide-plan skill (a copy under .claude/skills/ wins), with --doctrine appended. The approval lock: approve refuses with exit 12 while any question is open, naming the ids and phax artifact decide; a loop cannot approve past an open question. See docs/arbitration.md. Verdicts form: phax artifact decide <path> --verdicts <file|-> [--by operator] [--doctrine <file>] [--model <m>] [--effort <e>] [--json] decides from a file of choices a person already made (phax artifact schema verdicts prints its format): { question, chosen, note } per question, chosen an option id or the reserved other, a note required when the verdict departs from the recommendation. No terminal is needed with --by operator; --by machine:<grant> is refused. One headless writer (default claude-sonnet-5-5 at medium, routed to a provider) records the verdicts; phax checks its answer, sets why, by and at, commits without asking and leaves the artifact Draft, so read the printed report (or the --json object) before approve. --question is refused with --verdicts; --json and --by need it.
  • phax artifact abandon / complete — terminal transitions; phax moves the file into the matching archive/ directory and deletes its record file as part of the transition. Reopen deletes the artifact's record file the same way. No transition touches another artifact's record file.
  • phax artifact migrate-approvals — the one-time upgrade from the old shared ledgers (docs/plans/approvals.json, docs/specs/approvals.json) to per-artifact record files under docs/plans/approvals/ and docs/specs/approvals/, in one commit. Exits 0 when migrated or when there is nothing to migrate; exits 12, writing nothing, on an unreadable ledger, an entry that is not a live artifact path, an uncommitted change to a path it would write, or an existing record file holding a different record. While a ledger exists, every other approval command exits 12 and names this command.
  • phax artifact migrate-documents — the one-time upgrade of headless sidecars. It rewrites every live spec and plan sidecar (a .json directly under docs/specs/ or docs/plans/ beside its .md) stamped below its format's current shape, or written before $schema, and re-renders its body, keeping the frontmatter byte for byte. A spec question whose rationale opens with Decided by the author on <YYYY-MM-DD> becomes arbitrated, lifted and unattributed; every other question stays open. A plan stamped 0.20.0 lifts with empty question arrays and keeps its body. It refuses (exit 12, nothing written) on an invalid sidecar (a plan stamped 0.17.0–0.19.x stays refused), on a body that is not the sidecar's own rendering (a hand edit would be overwritten), or on an uncommitted change to a path it would write; the remedy is to re-author it headless, or delete its sidecar to demote it to hand-authored. It names every Approved artifact it leaves edited since approval (with its open question ids and phax artifact reopen <path> when it has any, else phax artifact approve <path>) and every plan it leaves stale with spec-changed, then commits exactly what it wrote in one commit. With nothing to migrate it says so and exits 0. Until it has run, approve and reopen exit 12 and name it; complete, abandon and run completion carry an older sidecar as before. Archived and hand-authored artifacts and approval record files are never touched. The phase guard refuses it inside a phase worktree: run it in the main checkout.

Transitions are validated: an illegal one is refused and names the legal set, and a terminal status must live under archive/ (status and location must agree). A loose plan.md outside docs/specs/|docs/plans/ is still gated on status, but its status line is edited by hand — phax artifact targets repo-tracked artifacts.

When unsure about any command, read its long_help and example in phax --usage.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.