Write and guard your project's history — craft commits (auto simple/atomic), author reviewer-legible PRs/MRs, cut config-first releases, and promote cockpit…

A local Claude Code, Codex, and OpenCode plugin marketplace for a personal coding workflow. It ships five plugins: monitor turns local traces into useful dashboards — the usage-dashboard skill is the rear-view mirror for usage history, and the cockpit skill is the windshield for the session currently in flight; dispatch is interview-driven planning you can then execute — spec the work, write a blueprint to disk, and fly it with a quality loop, or map a whole project into milestone legs and plan each one just-in-time; relay delegates a task out to another harness's CLI (codex, opencode, or claude) — delegate work, request a review, or generate an image — then captures the result and reports back; chronicle authors your git history — commits (auto simple/atomic), reviewer-legible PRs/MRs, and config-first releases that bump versions, write the changelog, and cut the tag; herdr is reference plus a typed wrapper for driving agents across panes in the Herdr terminal workspace manager.
This repository uses GitHub Flow. Create feature and fix branches from main, then open pull requests back into main. The existing develop branch is historical and does not indicate that this repository uses git-flow. Chronicle records this machine-readable PR policy in .chronicle/pr.json.
monitor bundles three skills:
| Skill | Description |
|---|---|
| usage-dashboard | Local usage dashboard for Claude Code, Codex, and OpenCode: sessions, tokens, cost, model mix, and project activity, plus live sessions for Claude Code and Codex |
| cockpit | Per-project work cockpit for Claude Code, Codex, and OpenCode: goal capture, decision log, live transcript, needs-your-call bridge, and a send box for live sessions |
| install | One-stop prerequisite check and permission wiring for the whole plugin, command-triggered |
dispatch bundles five skills:
| Skill | Description |
|---|---|
| preflight | Short interview that captures what you want as docs/<slug>/INTENT.md, before anyone decides how to build it — writes one file and stops, never executes |
| hop | Lightweight interviewer that gathers requirements into a single in-conversation plan to approve and execute |
| flightplan | Heavyweight interviewer that writes a multi-file blueprint to disk — PLAN.md + a tasks/ tree of self-contained task files for sub-agents |
| autopilot | Executes a flightplan tree in parallel waves — a dev→verify→judge→score loop gated on each task's Eval rubric, an atomic commit between waves, then the closing final-review gate, leaving an audit trail |
| waypoints | Rolling-wave milestone-roadmap tier above flightplan — writes only docs/<proj>/WAYPOINTS.md plus a waypoints.ts CLI (active / leg-scaffold / advance) so each leg's flightplan is planned just-in-time after the previous leg lands |
relay is a single portable skill:
| Skill | Description |
|---|---|
| relay | Delegate a task to another harness's CLI (codex / opencode / claude): delegate (do work), review (analysis only), or image (codex only) — capture the result, smart-apply when safe, and report back |
chronicle bundles four skills:
| Skill | Description |
|---|---|
| commit | Craft git commit(s) for the current changes — auto-decides between one simple commit and an atomic split |
| pr | Open a reviewer-legible PR/MR for the current branch, enriched by the cockpit decision trail when present |
| release | Cut a release — bump version files, write the CHANGELOG entry, then commit, merge, tag, and push; local stops before the push, prepare after the entry |
| install | Set up chronicle's prerequisites — the named agent roles on Codex (Claude Code needs none) |
herdr is a single skill:
| Skill | Description |
|---|---|
| herdr | Reference for the Herdr terminal workspace manager (config, CLI, plugin dev) plus a typed herd wrapper to spawn and drive agents in sibling panes when running inside herdr |
claude plugins marketplace add FunnyQ/cc-plugins
claude plugins install monitor@q-lab-marketplace
# Any of these plugin ids works: monitor, dispatch, relay, chronicle, herdr
/plugins to open the plugin managerFunnyQ/cc-pluginsThe usage-dashboard skill runs a prerequisite check automatically before launching the dashboard, so there's no manual setup step. If something is missing, the hint is surfaced in the terminal. The most common case is stats-cache.json not existing yet; run /stats once in Claude Code to seed it.
If you want to run the precheck yourself:
bun $CLAUDE_PLUGIN_ROOT/skills/install/scripts/install.ts
Codex reads this marketplace from .agents/plugins/marketplace.json. The registry lists all five plugins, and each is installed by id.
codex plugin marketplace add FunnyQ/cc-plugins
codex plugin add monitor@q-lab-marketplace
# Any of these plugin ids works: monitor, dispatch, relay, chronicle, herdr
Check the install:
codex plugin list | rg 'q-lab-marketplace|monitor'
After installing a Codex plugin, start a new Codex session so the skill list is refreshed.
There is no plugin registry step. The repo is the single source of truth: opencode/install.ts symlinks skills, agents, commands, and the plugin module straight into ~/.config/opencode/, so an update to the checkout is live immediately — no reinstall, no rebuild.
Requires OpenCode 1.x. The plugin module targets OpenCode's V1 plugin API. OpenCode 2.x replaced that API, so on 2.x the module fails to load and none of its hooks run. The cockpit send and relay's opencode backend also support 1.x only.
bun opencode/install.ts --check # report what is and is not wired
bun opencode/install.ts --apply # symlink everything, raise subagent_depth
bun opencode/install.ts --unlink # remove only what --apply created
--dry-run also exists — it prints the same plan as --apply without writing anything.
--apply installs:
| Installs | Count | Target |
|---|---|---|
| Skills | 15 | ~/.config/opencode/skills/<name>/ |
| Plugin module | 1 | ~/.config/opencode/plugin/q-lab.ts |
| Chronicle agents | 6 | ~/.config/opencode/agents/<name>.md |
| Commands | 2 | ~/.config/opencode/commands/<name>.md |
subagent_depth | 1 edit | ~/.config/opencode/opencode.json |
The subagent_depth prerequisite. --apply raises subagent_depth to at least 2 in ~/.config/opencode/opencode.json, the one config file it touches outside symlinks. The edit is raise-only — every other key in that file is preserved, and a value already ≥ 2 is left alone. OpenCode ships defaulting subagent_depth to 1, which blocks nesting outright, so this isn't a hypothetical edge case — it's the shipped default. Chronicle no longer needs it — none of its agents spawns a child — but dispatch's autopilot does: below the required depth its driver simply stops mid-run with no error naming the config, and the failure reads exactly like a plugin bug. Anyone hand-editing opencode.json instead of running --apply needs to set this key to 2 themselves.
Which config file gets the edit. OpenCode merges three global config names in order — config.json, then opencode.json, then opencode.jsonc — so the last one present wins. The installer patches whichever of those already exists, highest precedence first, and creates opencode.json only when none does. Two consequences: an existing opencode.jsonc is the file that gets raised, and a config carrying comments is read but never rewritten, because re-serializing it would delete them — --check and --apply report manual and print the line to add by hand.
Works under OpenCode:
~/.config/opencode/skills/.~/.local/share/opencode/opencode.db.opencode --port <n>), or OPENCODE_TUI_SERVER_URL must be set before cockpit starts.delegate and review.Does not work under OpenCode:
image — codex-only, and it fails at the capability gate before any CLI runs.setup.ts --session-check. It is deliberately not ported because it is inert outside Claude Code — it returns immediately without CLAUDE_PLUGIN_DATA, and its actual work is statusline-path migration and reaping orphaned Claude processes.A single-page dashboard that reads local ~/.claude/ and ~/.codex/ data and visualizes usage in a browser. No telemetry, no cloud; everything stays on your machine.

~/.local/share/q-lab/token-atlas/), so your token/cost/model history survives Claude Code's automatic transcript cleanup (cleanupPeriodDays) instead of disappearing as old sessions age outcockpit shim fetches its release binary on first run)/stats once to seed stats-cache.jsonpackages/monitor/skills/cockpit/bin/cockpit atlas serve # [--port N] [--no-open]
As JSON instead: cockpit atlas stats (dashboard data), cockpit atlas live (active sessions), cockpit atlas rollup-update [--rebuild] (rollup DB).
Opens http://localhost:5938 in your default browser.
--port <n> Use a different port (default: 5938)
--no-open Don't auto-open browser
Token costs are estimated using bundled defaults (references/pricing-defaults.json). On startup, live prices are fetched from OpenRouter (3s timeout, silent fail). You can override with a custom file:
~/.config/cc-dashboard/pricing.json
{
"models": {
"claude-opus-4-7": { "input": 5.00, "output": 25.00, "cacheRead": 0.50, "cacheWrite": 6.25 }
}
}
Cockpit is a per-project dashboard and skill for active work. Start with a session goal, keep a distilled decision log, stream the current Claude Code or Codex transcript, and park on needs_your_call so a button click in the dashboard wakes the session.

In Claude Code or Codex, invoke the cockpit skill and confirm the proposed goals. From a development checkout, the dashboard can also be started directly:
packages/monitor/skills/cockpit/bin/cockpit server
Opens http://localhost:5858 in your default browser.
~/.claude/projects/**/<session>.jsonl.~/.codex/state_5.sqlite thread rows and rollout files under ~/.codex/sessions.opencode provider in packages/monitor/cockpit-rs/src/server/transcript.rs, reading the same ~/.local/share/opencode/opencode.db the usage-dashboard uses..cockpit/; the registry and wait/send bridge are shared through ~/.local/share/q-lab/cockpit/.The send box at the bottom of the Decision Log column can send text into a running session.
OPENCODE_TUI_SERVER_URL (or a ps scan for opencode --port <n>) and delivers through /tui/append-prompt + /tui/submit-prompt. Same port precondition as the OpenCode Installation section above — the TUI must have been started with --port; a serve process is not discovered, and a successful send is not a delivery receipt.A monitor mod (hooks/register.ts) delivers Claude Code sends. On session start it long-polls the cockpit daemon's inbox over HTTP and submits each message as a new turn once the session is idle. The same mod relays permission dialogs to the dashboard. It needs a Claude Code build with function-hook mods, and a plain claude session gets both:
claude
If an older version left a hand-wired cockpit-channel entry in ~/.claude.json, /monitor:install removes it. See the cockpit skill for the full setup.
For Codex send support, install and enable the managed standalone Codex remote-control daemon:
curl -fsSL https://chatgpt.com/codex/install.sh | sh
codex app-server daemon enable-remote-control
Cockpit checks /api/codex-control/status before enabling the Codex send box, so stale or non-resumable threads stay disabled instead of failing only after send.
Interview-driven planning you can execute. Four skills form one arc — capture what you want, gather the spec, commit a blueprint to disk, then fly it with a multi-agent quality loop — and a fifth, waypoints, sits above it for whole-project rolling-wave planning.
docs/<slug>/INTENT.md, before anyone decides how to build it. Writes one file and stops; never executes.preflight.docs/<slug>/PLAN.md plus a tasks/ tree of self-contained task files (each with its own ## Eval rubric). Best when the work spans sessions or hands off to sub-agents.next-ready) and runs those tasks in parallel; for each task it runs Dev → an independent binary gate (re-runs the task's Verification) → a rubric judge → a deterministic score gate, retrying until the task passes its rubric. Between waves it makes an atomic commit of the completed work, so the run leaves a clean per-wave history rather than one giant diff. The Final review task depends transitively on every other task, so the wave loop naturally schedules it last as the whole-tree gate — a closing multi-lens review round (cross-vendor codex + four /simplify lenses → an Opus fixer), followed by a final commit of its fixes. Every verdict lands in a self-gitignored docs/<slug>/.flightlog/ audit trail (RUNLOG.md).docs/<proj>/WAYPOINTS.md, legs tracked with [x]/[~]/[ ]); each leg's detailed flightplan is generated just-in-time after the previous leg lands, so every plan starts from what actually shipped rather than one oversized up-front guess. A waypoints.ts CLI collapses the lifecycle into three verbs — active (rolling-wave digest), leg-scaffold (nest a leg's tree under docs/<proj>/legs/NN-slug/), and advance (land the active leg; writing requires --outcome as the confirmation gate). flightplan gains a narrow waypoint mode that plans one leg at a time. Human-in-loop by design — one leg lands before the next is planned.# Claude Code
claude plugins install dispatch@q-lab-marketplace
# Codex
codex plugin add dispatch@q-lab-marketplace
# OpenCode
bun opencode/install.ts --apply
(Add the marketplace first if you haven't — see the monitor install steps above.)
One portable skill that delegates a task out to another harness's CLI, then captures the output and reports back — a multi-backend generalization of the codex-only odin-codex skill.
/relay <codex|opencode|claude> delegate <task>
/relay <codex|opencode|claude> review [task]
/relay codex image <prompt> --out <path>
opencode/claude fail fast at the capability gate.A capability gate rejects unsupported (backend, mode) pairs before any CLI runs. Every run captures full output to /tmp/relay/<ts>/last.md and prints it. Models resolve by precedence: --model flag > config file (~/.config/q-lab/cc-plugins/relay/config.json) > built-in defaults. Per-CLI invocation details, headless output handling, and the OpenCode symlink install live in the backend reference.
Live-pane mode — inside herdr (HERDR_ENV=1), delegate/review automatically run the backend's interactive TUI in a visible, take-over-able pane opened in its own new tab (so your working pane keeps its full size), via the herdr plugin's herd.ts, dynamically imported — no hard dependency. The answer is captured through a result-file contract; stdout stays the clean answer, live metadata rides stderr. --dangerous makes it a YOLO / unattended run (auto-approves permissions: codex/claude bypass flags, opencode --auto); without it, approval prompts surface in the pane for a human to answer. A run that outlives --wait-timeout (default 10 min) exits 0 with a "still running" report and leaves the pane alive. --headless opts out; outside herdr the classic headless flow is unchanged.
# Claude Code
claude plugins install relay@q-lab-marketplace
# Codex
codex plugin add relay@q-lab-marketplace
# OpenCode
bun opencode/install.ts --apply
If you previously ran the old manual symlink (ln -s .../packages/relay/skills/relay ~/.claude/skills/relay), remove it. opencode/install.ts --apply installs relay under ~/.config/opencode/skills/, and OpenCode scans ~/.claude/skills/ as well — leaving the old symlink in place surfaces two skills both named relay. --check warns about it.
Chronicle authors your git history — what a commit says, what a pull request argues, and what a release ships. A thin SKILL.md sends the bulky reading to an agent — a diff, a branch, a range of commits — and keeps the decisions where you can see them. Diff-reading and git output stay out of your conversation.
simple to force one commit..chronicle/release.json, then bumps the version files and writes the CHANGELOG entry, commits, tags, and pushes. Pass local to stop before the push, or prepare to stop after the entry.# Claude Code
claude plugins install chronicle@q-lab-marketplace
# Codex
codex plugin add chronicle@q-lab-marketplace
# OpenCode
bun opencode/install.ts --apply
Reference and in-session agent orchestration for Herdr, a terminal workspace manager with workspaces, tabs, split panes, and agent detection. Two halves:
config.toml, CLI, keybindings, and plugin development. Detail lives in references/; the skill reads only the relevant file.herd wrapper — a typed Bun wrapper (scripts/herd.ts) over the raw herdr CLI, for when you (an agent) are running inside a herdr pane (HERDR_ENV=1) and want to spawn and drive other agents in sibling panes or their own tabs (spawn --new-tab). It collapses herdr's multi-step recipes into seven verbs and handles the sharp edges: it addresses agents by a collision-resistant generated name (pane ids renumber), its send writes the prompt and presses Enter (raw agent send only writes literal text), its keys verb sends bare key chords (submit / clear the input box), and its read defaults to the visible screen (agent TUIs leave scrollback empty).HERD="$CLAUDE_PLUGIN_ROOT/skills/herdr/scripts/herd.ts" # or the skill's load-time base dir
bun "$HERD" spawn reviewer --agent codex --task "review the diff in src/api/"
bun "$HERD" send reviewer-a3f9 "now check error handling"
bun "$HERD" wait reviewer-a3f9 --status idle --timehooks/register.ts 77 lines1/**
2 * check-branch as a Claude Code mod: the matcher rejects every Bash call that
3 * is not a git commit before the hook runs, so an ordinary command spawns
4 * nothing. It hooks `classic.PreToolUse` rather than `tool.call` because only
5 * the classic result can ask; `tool.call` can pass or deny and nothing else.
6 * OpenCode keeps check-branch.sh, since it has no function hooks.
7 */
8
9import type { Register } from "claude-code";
10import { COMMIT_COMMAND } from "./commit-command.ts";
11
12type PrConfig = {
13 workflow?: string;
14 base?: string;
15 production?: string;
16 development?: string;
17};
18
19export const register: Register = (on) => {
20 on(
21 "classic.PreToolUse",
22 { tool: "Bash", command: COMMIT_COMMAND },
23 async ($, e, next) => {
24 if (e.tool !== "Bash") return next(e);
25
26 const git = async (...args: string[]) => {
27 const r = await $.process.run(["git", ...args]);
28 return r.exitCode === 0 ? r.stdout.trim() : "";
29 };
30
31 const ask = async (): Promise<string | undefined> => {
32 const [branch, root] = await Promise.all([
33 git("branch", "--show-current"),
34 git("rev-parse", "--show-toplevel"),
35 ]);
36 let config: PrConfig = {};
37 if (root) {
38 try {
39 config = JSON.parse(await $.fs.read(`${root}/.chronicle/pr.json`));
40 } catch {}
41 }
42
43 if (config.workflow === "github-flow") {
44 // A GitHub Flow repo has one long-lived branch, so `/chronicle:release` commits the bump on the base by design.
45 if (!config.base || branch !== config.base) return;
46 if (e.command.includes("🔧 release:")) return;
47 return `⚠️ You're on \`${branch}\`, the configured GitHub Flow PR base. Commit from a topic branch, or confirm explicitly before retrying.`;
48 }
49 if (config.workflow === "git-flow") {
50 if (!config.production || branch !== config.production) return;
51 return `⚠️ You're on \`${branch}\`, the configured Git Flow production branch. Commit on \`${config.development ?? ""}\`, or confirm explicitly before retrying.`;
52 }
53
54 const develop = await git("config", "--get", "gitflow.branch.develop");
55 if (!develop) return;
56 const production = await git(
57 "config",
58 "--get",
59 "gitflow.branch.master",
60 );
61 if (
62 (production && branch === production) ||
63 branch === "main" ||
64 branch === "master"
65 ) {
66 return `⚠️ You're on \`${branch}\` in a git-flow repo. Commit on \`${develop}\`, or confirm explicitly before retrying.`;
67 }
68 };
69
70 const reason = await ask();
71 const below = await next(e);
72 if (reason === undefined || below.deny !== undefined) return below;
73 return { ...below, allow: undefined, ask: reason };
74 },
75 );
76};
77hooks/commit-command.ts 3 lines1// Copied in check-branch.sh and as COMMIT_COMMAND in opencode/plugin.ts; commit-command.test.ts holds the three equal.
2export const COMMIT_COMMAND = /git\s+commit/;
3