qstack
Agent skills for planning work, executing it against the plan, and proving the
result. QStack installs 23 skills into Claude Code, Codex, and any harness that
reads ~/.agents/skills, from one checkout that stays the source of truth.
What this helps with
Coding agents are good at writing code and bad at everything around it. They agree with a plan and then quietly build something else. They report success from a clean compile. They rediscover, on every feature, a decision the team already made six weeks ago and wrote down.
QStack answers those three failures with skills that leave evidence on disk:
A plan you can review and cite. /qstack-plan-to-html turns a Markdown
draft, or the chat you just had, into a numbered HTML document: a high-level
half for whoever is approving the work, a low-level half for the agent doing it.
Every clause has a § number, so review feedback is "§4.2 is wrong" rather than
"the second bit about caching". The document freezes when execution starts.
Execution that cannot silently drift. Both loops work the plan card by card,
keep a running execution.md, and ask how much independent adversarial review
to run before they change anything. Pick /qstack-loop-no-nonsense when the
plan is the contract, or /qstack-loop-trequartista when the agent may adapt as
long as it says so in writing. /qstack-plan-adherence-review then scores the
outcome from 0 to 5 against the plan, the execution record, and the actual diff.
Memory that survives the session. /qstack-plan-close writes what the work
actually cost into outcome.md, and /qstack-plan-prior-art reads that folder
before the next plan in the same area is drafted. None of it goes into
CLAUDE.md. An always-loaded instruction file that grows with every shipped
plan stops being read; a rule strong enough to bind everywhere belongs in a
check, which is what /qstack-encode-lessons-in-structure builds.
Alongside the lifecycle there are ten engineering-practice skills, adapted from Lauren Tan's PStack, that fire on their own when the conversation calls for them: diagnose before patching, prove the real artifact runs, separate ownership before reaching for a lock.
The skills are also deliberately conservative about authority. A diagnosis skill diagnoses; it does not fix, commit, push, or deploy. Read-only skills say so in their own text.
The plan lifecycle
plan.md, or just the chat a written draft, or the shape you talked through
↓
/qstack-plan-to-html prior art, render, ask the open questions, cut the board
↓ (plan.html is authoritative from here; no Markdown is maintained)
/qstack-loop-no-nonsense choose review depth, work the cards,
/qstack-loop-trequartista keep execution.md current
↓
/qstack-plan-adherence-review score the result against the plan, 0 to 5
↓
/qstack-plan-close write outcome.md, stand the board down
↓
the next plan's prior-art pass reads all of it
You do not need a draft file. If you would rather talk the work through with
the agent than write Markdown first, do that and run /qstack-plan-to-html
straight after. It extracts the plan from the conversation, shows you what it
captured, and renders only once you confirm. Anything you discussed but never
settled lands as an open clause rather than a decision the agent made for you.
A Markdown draft still works, and /qstack-plan-prior-art still runs standalone
before either.
The conversion is one command. /qstack-plan-to-html reads the prior art,
renders the document, runs /qstack-ask-plan-open-questions against the
authoritative HTML so material decisions are settled and recorded before anyone
starts, then breaks the frozen plan into board cards with points and
dependencies. It never re-renders a plan that already exists, and it adds a
board to an HTML plan that lacks one.
Boards are a static board-events.js beside the plan, so plan.html#board
works from disk with no server. /qstack-serve-plans adds a stable localhost
URL when you want one.
Either loop then works that board in waves rather than one card at a time. The
depends_on and files on each card say which cards do not need each other, so
the loop claims every ready card whose files nobody else holds, gives each one
its own subagent, and isolates each card's writes and validation. Four
cards at once by default. Use --parallel N to change it, or --parallel 1 for
the old serial run.
Before a new board execution starts, the loop asks for final review, full
review, or none. final, the recommended choice, launches one fresh reviewer
after all cards close. full also reviews every card against its own diff.
none relies on validation and launches no reviewer. Without a board, the
question combines final and full into one whole-plan-review choice because
their cost is identical. Plan or repository review requirements remove any
weaker choices. The Review board column remains visible and stays empty when
per-card review is omitted. For automation, --review full|final|none supplies
the mode without a prompt and is rejected when it violates those requirements.
Skills
Automatic skills are offered by the agent when the description matches what you are doing. Explicit skills run only when you type them.
Plan lifecycle
| Skill | Invocation | Purpose |
|---|---|---|
qstack-plan-prior-art |
Automatic | Rank earlier plans by overlap with what you are about to write, then report what was decided, deferred, learned, and superseded, plus live board cards touching the same files. Writes nothing. |
qstack-plan-to-html |
Explicit | Render a plan as a numbered HLD/LLD document, resolve its open questions, and break it into the cards of its execution board. Takes a Markdown draft or the working agreement reached in the conversation. |
qstack-ask-plan-open-questions |
Automatic | Ask the questions whose answers change what gets built, one at a time in plain language, and write each decision and its consequences straight into the plan. |
qstack-loop-no-nonsense |
Explicit | Execute the plan exactly. Stop before any deviation, keep execution.md current, and ask how much adversarial review to run. |
qstack-loop-trequartista |
Explicit | Execute the plan with controlled creative freedom. Preserve its intent, record every adaptation, and ask the same review-depth question. |
qstack-plan-adherence-review |
Automatic | Build a requirement-to-evidence matrix from the plan, the execution record, and the real diff, then assign a guarded 0 to 5 adherence score. Report-only. |
qstack-plan-close |
Explicit | Fold the board, check nothing is still claimed or in flight, and write outcome.md: the delta between the plan and what actually happened. |
qstack-serve-plans |
Explicit | Serve this repository's plan collection over HTTP, asking for the bind address and port instead of guessing your network exposure. |
Project reflection
| Skill | Invocation | Purpose |
|---|---|---|
qstack-reflect |
Automatic | Report how the project is actually being worked, across every worktree Git tracks: branch topology, momentum, rework, instruction churn, plan-record completeness. Every finding is a count you can reproduce; a category without evidence is refused, not padded. Takes plan directories, as in /qstack-reflect docs/rfcs. |
qstack |
Explicit | List every installed QStack skill and optional collection, read from disk on each run, then recommend what to run next. |
qstack-next |
Automatic | Say what was just done, what that leaves undone, and the one skill that closes the gap. Three or four lines. Names the skill; never runs it. |
Engineering practice
Adapted from PStack. These carry no plan-folder dependency and work in any repo.
| Skill | Invocation | Purpose |
|---|---|---|
qstack-fix-root-causes |
Automatic | Reproduce the failure and follow the causal chain until direct evidence supports the root cause. Rejects nil guards that only silence a crash. Diagnosis does not authorize the fix. |
qstack-prove-it-works |
Automatic | Run the real artifact from input through every boundary to output. A clean compile, a fresh timestamp, and an agent's summary are not proof. |
qstack-blast-radius |
Automatic | Name the one fact the change is safe because of, then prove it with real code or mark it unproven. Follows effects past direct callers into pinned dependency source, wire formats, persisted data, and generated artifacts. |
qstack-how |
Automatic | Explain a subsystem from its real runtime flow, ownership, and boundaries. Critiques architecture only when you ask for it. Read-only. |
qstack-model-the-domain |
Automatic | Replace synchronized booleans, repeated validation, and ever-growing branches with the smallest structure that makes the invalid state unrepresentable. |
qstack-separate-before-serializing-shared-state |
Automatic | Remove the shared write target before adding a lock. Serialize only when one canonical writer is a genuine domain invariant. |
qstack-make-operations-idempotent |
Automatic | Model a crash after every mutation point and the rerun from each partial state, so retries and restarts converge instead of merely not erroring. |
qstack-encode-lessons-in-structure |
Automatic | Turn a recurring correction into the strongest practical guardrail: an unrepresentable state, a CI check, one canonical helper. Prose is the last resort, not the first. |
qstack-foundational-thinking |
Explicit | Settle data shape, access paths, ownership, concurrency, and shared setup before feature logic, without deciding more than current requirements justify. |
qstack-build-the-lever |
Explicit | For work that is more than a couple of obvious edits, build the smallest rerunnable tool that performs or proves it. A tool, not a framework. |
Writing
| Skill | Invocation | Purpose |
|---|---|---|
qstack-be-concise |
Automatic | Rewrite the previous answer in far fewer lines and plainer language. Takes a target, as in /qstack-be-concise 4. |
qstack-unslop |
Explicit | Strip AI writing patterns from the previous answer and restore a human voice, without losing meaning, detail, or technical accuracy. |
Install
git clone https://github.com/hani-q/qstack.git ~/work/code/qstack
cd ~/work/code/qstack && ./install
Restart your agent afterwards.
Or through the skills.sh CLI, which supports more than 70 agents:
npx skills add hani-q/qstack # everything
npx skills add hani-q/qstack --list # look first
npx skills add hani-q/qstack --skill qstack-plan-to-html # just one
./install links every skill into each harness it finds and skips the ones that
are absent:
| Harness | Skill directory | User-wide instructions |
|---|---|---|
| Claude Code | ~/.claude/skills/ |
~/.claude/CLAUDE.md |
| Codex | ~/.codex/skills/ |
~/.codex/AGENTS.md |
generic agents (Cline, Warp, Zed, ...) |
~/.agents/skills/ |
N/A |
Those paths match the ones the skills.sh CLI uses, so the two installers agree.
The installer also maintains a ## General instructions section and a small
## qstack routing section in the user-wide instruction files, both wrapped in
HTML comment markers. Re-running replaces only the marked block and preserves
every other line. ./install --version prints the release and the exact source
revision.
Requirements
Bash and Python 3 for the plan renderer, the local plan server, and the
/qstack listing. Node for board-event validation, which every skill that reads
a board runs as node --check before trusting it. Git throughout;
/qstack-reflect needs a Git repository and says so rather than guessing.
full and final loop runs need a host that can launch a fresh, independent
review agent. A none run does not. When the selected mode requires an agent
and the host has none, the loop stops before claiming completion instead of
reviewing its own work.
Flags
| Flag | Effect |
|---|---|
| (none) | Symlink each skill in. git pull then updates every harness at once. |
--copy |
Copy instead, for a harness that will not follow a link or a machine where this checkout is temporary. Needs a re-run after every pull. |
--dry-run |
Print what would happen, change nothing. |
--with-matt-pocock |
Install Matt Pocock's skills without asking. |
--without-matt-pocock |
Skip that prompt. |
--with-human-review |
Install human-review without asking. |
--without-human-review |
Skip that prompt. |
--yes, -y |
Accept every optional collection without prompting. A later --without-... still wins, so --yes --without-human-review takes only the rest. |
--uninstall |
Remove the linked skills and both qstack-managed instruction sections. |
--version |
Print the release version and exact Git revision. |
Link installs must run from the repository's primary Git worktree, because
user-global symlinks into a disposable worktree break when it is removed. The
installer refuses and prints the right path. --copy works from anywhere.
Re-running is safe, and the installer never deletes an entry it did not create:
a qstack-<name> directory it did not install is reported and left alone.
Symlink installs carry a hidden marker recording the exact target, so uninstall
can still identify them if this checkout later moves or disappears.
Optional collections
An interactive install offers each one separately and defaults to yes, so a bare
Enter takes the recommended set. Both need npx.
| Collection | What it adds |
|---|---|
| Matt Pocock's skills | A broad general-purpose skill library, installed through the skills CLI. |
| human-review | Opens an HTML file, a Markdown file, or a localhost page in the browser so you can edit the text and comment on specific parts, then sends the batch back to the agent. It closes the loop /qstack-plan-to-html opens: a rendered plan becomes something you redline directly instead of describing in chat. Needs Node 20+. |
Each is installed by running its own upstream installer, so both stay owned upstream. QStack does not update or uninstall them.
Two things worth knowing about human-review. QStack installs it from source
tag v0.5.0 rather than npm, because the published release only installs a
Claude Code skill while Codex and ~/.agents support exists in the tagged
source and has never been published. npx cannot install a git dependency by
commit SHA, so QStack clones the repository, checks out the reviewed commit,
verifies HEAD matches, and runs the installer from there, binding what runs to
a commit rather than a movable tag. Separately, its installer writes into
~/.claude, ~/.codex, and ~/.agents whether or not those harnesses exist,
and the skill it writes tells agents to run npx -y human-review, which
resolves to that project's current npm release at the time of use. QStack's own
install only touches directories that are already there.
In the default ask mode a non-interactive invocation installs neither, so a
piped or scripted install never pulls third-party code on a silent default. Pass
--with-... for one or --yes for all; that flag keeps working as collections
are added. Dry-run and uninstall never prompt. If one optional install fails the
other is still attempted, and the installer exits non-zero.
Layout
This repo is the single source of truth. The harnesses hold links back to it, so there is no second copy to drift.
qstack/ ← this repo, anywhere on disk
├── GENERAL_INSTRUCTIONS.md ← shared Claude/Codex behavior and writing source
├── install
├── scripts/
│ ├── qstack-version ← allocate, write, and validate branch versions
│ ├── test-versioning ← collision and retry regression tests
│ ├── validate-board-fold ← board event stream folding rules
│ ├── validate-skill-invocation ← Claude/Codex policy parity + portable validation
│ └── validate-template-sync ← keeps the two template copies byte-identical
└── skills/ ← the layout skills.sh discovers
├── qstack/SKILL.md
├── qstack-next/SKILL.md
├── ... ← one directory per skill, 23 in total
├── qstack-how/
│ ├── SKILL.md
│ └── references/ ← exploration, explanation, critique
└── qstack-plan-to-html/
├── SKILL.md
├── references/board-breakdown.md ← epics, cards, points, dependencies
└── template/v1/ ← "cyanotype & redline" plan template
├── board.js plan.css plan.js pretext.js
├── plan-template.html
└── fonts/ ← self-hosted woff2, offline-safe
~/.claude/skills/qstack-<name> ┐
~/.codex/skills/qstack-<name> ├─ symlinks → qstack/skills/qstack-<name>
~/.agents/skills/qstack-<name> ┘
A skill's directory name is its name: it matches the name: in its frontmatter,
which is what the agent invokes. Nothing derives or appends a prefix, so there is
one place to rename a skill.
The qstack- prefix is deliberate. The ecosystem convention is to namespace by
owner/repo and leave names bare, the way Anthropic ships frontend-design
rather than anthropic-frontend-design. But these directories are shared with
vendored stacks like gstack and
greptile, and the prefix is what stops a
gstack-upgrade from clobbering them. A worthwhile deviation.
template/v1 is vendored rather than authored here; its component reference and
house rules live in
skills/qstack-plan-to-html/template/v1/README.md.
The skill copies it into the target repo instead of linking, so a rendered plan
keeps working on a machine that has never heard of qstack.
Local changes to the vendored template, tracked so the drift stays visible:
| Change | Files |
|---|---|
.eli asides: plain-English explanation behind an ⓘ, revealed on hover, focus, and tap; prints inline as a footnote |
plan.css §8, plan.js, plan-template.html, README.md |
Upstream is <repo>/plans/template/v1 in the workspace this was taken from and
does not have these. Port them across before treating either copy as canonical.
What QStack writes into your project
The renderer creates this structure inside each target repository:
qstack/
├── compound_engineering/plans/
│ ├── .template/v1/
│ └── <feature>/
│ ├── plan.html ← authoritative, frozen once execution starts
│ ├── board-events.js ← append-only card events, written during execution
│ ├── execution.md ← decisions, deviations, progress
│ └── outcome.md ← written by /qstack-plan-close
└── scripts/
├── serve.sh
└── migrate-board-log
No Markdown is maintained after conversion, and none is written when the plan
came from a conversation. Nothing in the cycle
writes to CLAUDE.md: what a plan taught stays in its folder, where
/qstack-plan-prior-art reads it before the next plan in the same area.
Serve the collection with ./qstack/scripts/serve.sh [port] [bind-address] or
/qstack-serve-plans [address] [port]. The skill asks for anything missing
before starting. Use 127.0.0.1 for local-only access, or choose 0.0.0.0
explicitly to listen on every interface.
Adding a skill
mkdir -p skills/qstack-<name>
$EDITOR skills/qstack-<name>/SKILL.md # frontmatter: name: qstack-<name>
./install # picks it up automatically
Any directory under skills/ holding a SKILL.md is a skill; the installer
finds it with no list to maintain. Keep the directory name and the frontmatter
name: identical. skills.sh requires name and description, lowercase with
hyphens.
Every skill also carries an agents/openai.yaml, and Claude and Codex use the
same invocation mode. SKILL.md owns that choice: omit
disable-model-invocation for automatic selection, or set it to true for a
manual-only skill. Mirror it with policy.allow_implicit_invocation: true or
false in agents/openai.yaml. CI runs scripts/validate-skill-invocation in
the same Python environment as its pinned Agent Skills reference validator: the
script checks parity, validates each agents/openai.yaml, and sends a temporary
portable projection through skills-ref.
Releases
version.txt is the release source of truth, using MAJOR.MINOR.PATCH.MICRO as
a monotonically increasing identifier. Every branch that ships claims a version
and adds its own topmost changelog entry before landing on main.
scripts/qstack-version prepare --bump patch --pretty
Use micro for docs and tiny internal changes, patch for fixes and small
additions, minor for substantial new capability, and major for breaking
public changes. The command reads open pull requests and existing sibling Git
worktrees, then writes the next free version atomically. It is safe to rerun: an
unclaimed branch version is reused, while a real collision moves to the next free
slot.
Add a CHANGELOG.md entry headed ## [MAJOR.MINOR.PATCH.MICRO] - YYYY-MM-DD
for that branch's user-visible change. Pull request titles keep Conventional
Commit syntax and are automatically prefixed with the version. CI requires the
version to advance past main, match the first changelog entry, and stay
unclaimed by every other open pull request. Protect main with the
Version gate check required and "Require branches to be up to date before
merging" enabled, so a lower claim rechecks after a higher version lands.
The Skills workflow verifies that the official skills.sh CLI discovers all current skills. skills.sh owns its catalog index and cached snapshots and its CLI offers no publish or re-index command, so GitHub releases remain the release history while skills.sh shows whichever snapshot its service has indexed.
Credits
The ten engineering-practice skills and the writing guidance in
GENERAL_INSTRUCTIONS.md adapt Lauren Tan's PStack
at a pinned commit. The implementation ladder both execution loops apply per
card, the design-sheet rule in plan-to-html, and the reviewer's
unrequested-code check adapt Dietrich Gebert's Ponytail, also pinned. Source
maps and the complete MIT licenses are in
Third-party notices.
QStack is MIT licensed. See LICENSE.
No comments yet
Be the first to share your take.