Dynamic Commands

Dynamic commands are Bruno's portable operator vocabulary — one shared .md library at ~/Herd/.dynamic-commands/ that both Claude Code and Codex CLI dispatch through. Edit a command file once, both tools see the new behaviour on the next call.

This chapter documents every command that lives in the library today. The dispatcher itself (/do) is not in the library — it's the thin per-tool router that reads the library files at invocation time.


Why a shared library

Before this system, every custom slash command existed in two flavours — one for Claude (~/.claude/commands/<name>.md), one for Codex (its own folder, its own syntax). They drifted out of sync constantly. The dispatcher pattern collapses that into a single tool-agnostic prose file per command. Both tools read the same file and decide how to act with their native tool calls.

Result: edit kraite-deploy.md once → next time Bruno types /do kraite-deploy (Claude) or use skill do kraite-deploy (Codex), both tools execute the new behaviour. No skill reload, no IDE restart, no parallel maintenance.


Invocation contract

The dispatcher reads $ARGUMENTS (everything after /do) and parses:

TokenMeaning
First whitespace-separated tokenthe command name (kraite-deploy, push, xss-audit, etc.)
Everything after the first tokena free-form natural-language modifier — unrestricted, sits on top of whatever the library file says

Empty /do → error, no auto-list. Missing file at ~/Herd/.dynamic-commands/<name>.md → error, no fallback to native commands, no fuzzy-match suggestions. Bruno wants explicit failures, not menus.

The modifier is unrestricted on purpose. It can skip steps, override safety gates, redirect targets, change parameters — Bruno owns the consequences. The dispatcher does not sanitise it; it threads it through as additional instruction.


Recursive dispatch

A library file may instruct "now run code-review" or "then do simplify on the dirty files". Each such sub-step re-enters the full dispatcher with a fresh read of the sub-command's .md file. Nothing is cached, nothing is paraphrased from memory. Editing code-review.md immediately changes every parent command that recurses into it — including releases, pushes, tags.

This cascading model is the whole reason the system exists. Without it, the parent commands would freeze their sub-skill semantics at authoring time, and edits to the leaf files would have no effect on real flows.


Tool-agnostic prose

Each command file describes WHAT to do in plain English. Tool-specific affordances (Claude's Read / Bash / Edit, Codex's shell, scheduled-task primitives, etc.) are picked by the runtime. The library files never name Claude-only or Codex-only tools, never include conditional blocks per tool. If the prose needs a scheduled task or a log-tail or a database probe, it says so in tool-neutral language and trusts the runtime to find the right call.

This is non-negotiable: the moment a library file mentions Read or WebFetch or any tool name, it stops being portable.


Command families

The library currently spans four families. Each family below maps a single project (or category) onto its operator surface.

Kraite — trading-system operator stack

Profile-aware operator commands for the Kraite ingestion + web + worker fleet. Every kraite-* command starts by recursing into kraite-profile to detect the active project from CWD, then branches per profile (ingestion / web-app / web-app-with-queue / static-site).

Quanamo — feedback-platform operator stack

Single-host (odin) variant of the same operator pattern. Three apps share the box — admin (PostgreSQL master), feedz (shares the same DB), kanban (own MySQL). No profile detection — quanamo has exactly one profile.

Ralph — autonomous overnight-run scaffolding

Ralph is the autonomous code-execution loop (per-iteration fresh Claude instance, no memory). The ralph-* commands manage the scaffolding around it — task queue, PRD conversion, deploy, monitor, archive.

Generic — cross-project dev commands

The "everyday" tooling — git workflow, code quality, requirements, memory, debugging, mode-switching. Project-agnostic by design.

  • brainstorm — read-only solution exploration
  • code-review — defend code against an SME review
  • code-safe — careful analysis-first mode
  • commit — local commit (packages first), no push
  • confirm — verbal alignment checkpoint, zero tool calls
  • cv — silent re-anchor of global + project rules
  • distill — force the librarian to process learnings
  • elicitate — Senior IT BA requirements session
  • explain — onion-peel conceptual explanation, read-only
  • fix — disciplined fix with dependency mapping
  • forget — remove a specific learning
  • learn — understand a codebase area, brevity-first
  • memorize — store a learning to persistent memory
  • memory — librarian status / stats
  • pest — adversarial Pest test authoring
  • prd — Product Requirements Document generator
  • pull — sync from remote with safe default
  • push — commit + push, packages first
  • read-docs — read project documentation
  • refactor — rethink-then-polish refactor flow
  • screenshot — analyse upload.waygou.com screenshots
  • tag — full release pipeline against odin
  • tm — too-much trigger, rewrite terser
  • troubleshoot — root-cause-or-nothing diagnosis
  • update-docs — refresh project docs
  • upset — caught-slipping reset + verify-from-zero protocol
  • xss-audit — multi-section security audit checklist

Authoring conventions

Three rules govern every library file:

  1. Tool-agnostic prose. WHAT to do, not HOW. No tool names.
  2. Frontmatter for discoverability. name, description, keywords — purely human-facing, the dispatcher itself doesn't parse them.
  3. Reference sub-skills by their command name. "now run code-review" (the dispatcher converts that to /do code-review recursion). Never paste a sub-skill's body inline — that freezes a stale copy.

When migrating a native slash command into the library, the retired native body lands in ~/Herd/.dynamic-commands/backup/<name>.md so the system travels together if the folder is ever git-tracked or cloud-synced.