claudemd-cli 0.97.0 → 0.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# claudemd
|
|
2
2
|
|
|
3
|
-
> A **personal AI-coding discipline harness**: one developer's opinionated **AI-CODING-SPEC v6.
|
|
3
|
+
> A **personal AI-coding discipline harness**: one developer's opinionated **AI-CODING-SPEC v6.35**, encoded as Claude Code shell hooks and shipped with the plugin. Built and dogfooded on my own repos — fork and adapt, don't adopt wholesale.
|
|
4
4
|
|
|
5
5
|
[](https://github.com/sdsrss/claudemd/actions/workflows/ci.yml)
|
|
6
6
|
[](https://www.npmjs.com/package/claudemd-cli)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
|
|
9
|
-
claudemd plugs into the Claude Code hook system to **block commits, pushes, and bash commands** that violate AI-CODING-SPEC v6.
|
|
9
|
+
claudemd plugs into the Claude Code hook system to **block commits, pushes, and bash commands** that violate AI-CODING-SPEC v6.35 — banned vocabulary in commit messages, `rm -rf $VAR` without variable validation, ship-on-red-CI, unread `MEMORY.md` entries during release flows, and more. The spec itself (`CLAUDE.md` + `CLAUDE-extended.md` + `CLAUDE-changelog.md` + `OPERATOR.md`) ships with the plugin and installs into `~/.claude/`, so the rules Claude Code reads at session start match the rules the hooks enforce. (`OPERATOR.md` is the human-only spec-maintenance handbook — Agent-loaded files are the CLAUDE trio.)
|
|
10
10
|
|
|
11
11
|
A standalone CLI (`npx claudemd-cli`) reuses the same `banned-vocab.patterns` source for git pre-commit hooks, GitHub Actions, and other agents that don't run inside Claude Code.
|
|
12
12
|
|
|
@@ -60,7 +60,7 @@ Verify in one command (Linux): `node --version && jq --version && gh --version &
|
|
|
60
60
|
| 22 shell hooks | `banned-vocab-check` · `pre-bash-safety-check` · `ship-baseline-check` · `residue-audit` · `memory-read-check` · `memory-prompt-hint` · `sandbox-disposal-check` · `session-start-check` · `session-extended-read` · `session-summary` · `session-end-check` · `transcript-vocab-scan` · `rework-breaker` · `cross-repo-write-check` · `tmp-sweep` · `branch-prune` · `evidence-gate` · `ledger-staleness` · `reply-language-check` · `transcript-structure-scan` · `version-sync` · `mem-audit` |
|
|
61
61
|
| 16 slash commands | `/claudemd-install` · `/claudemd-status` · `/claudemd-update` · `/claudemd-refresh` · `/claudemd-audit` · `/claudemd-toggle` · `/claudemd-doctor` · `/claudemd-analyze` · `/claudemd-uninstall` · `/claudemd-rules` · `/claudemd-clean-residue` · `/claudemd-sparkline` · `/claudemd-sampling-audit` · `/claudemd-bypass-audit` · `/claudemd-design-adopt` · `/claudemd-statusline` |
|
|
62
62
|
| 1 standalone CLI | `claudemd-cli lint` · `claudemd-cli audit` ([npm: `claudemd-cli`](https://www.npmjs.com/package/claudemd-cli)) |
|
|
63
|
-
| Spec v6.
|
|
63
|
+
| Spec v6.35 | `~/.claude/CLAUDE.md` · `CLAUDE-extended.md` · `CLAUDE-changelog.md` · `OPERATOR.md` (backup-before-overwrite) |
|
|
64
64
|
| StatusLine (opt-out) | PS1-style line — `user@host:dir (branch) Model [ctx:N% · 5h:N% · 7d:N%]` (`dir` = cwd basename; context / 5-hour quota / weekly quota, all **used %**, read from Claude Code's `rate_limits` payload; quota segments auto-hide when the data is absent, or force-hide with `DISABLE_STATUSLINE_QUOTA=1`) — wired into `~/.claude/settings.json` on install **only when the slot is empty**; an existing statusline is left untouched. Skip entirely with `CLAUDEMD_NO_STATUSLINE=1`. Manage via `/claudemd-statusline`. |
|
|
65
65
|
|
|
66
66
|
Install backs up a hand-written `~/.claude/CLAUDE.md` (any file without the `# AI-CODING-SPEC` H1) to `~/.claude/backup-<ISO>/` before overwriting (last 5 kept automatically). An already-installed claudemd spec never enters `backup-<ISO>/` — deliberate (v0.23.11): no directory in that namespace ever has the spec as its `CLAUDE.md`, so `restore` can never return a stale spec instead. (The user-content sweep does move `CLAUDE-extended.md`, `CLAUDE-changelog.md` and `OPERATOR.md` along beside your own file, so the directory is not literally yours alone — the `CLAUDE.md` in it is.) It is not discarded either (v0.83.0): unless it already matches the shipped spec byte for byte, it is copied to `spec-backup-<ISO>/`, a separate namespace `restore` does not read (last 5 kept). Uninstall offers `keep / restore / delete`; `delete` requires an extra confirmation.
|
|
@@ -80,7 +80,7 @@ Once installed, hooks run silently in the background. Verbose log: `~/.claude/lo
|
|
|
80
80
|
| `git push` while the pushed branch's CI is red | `ship-baseline-check` | Blocks the push (2-second `gh run list` timeout; fail-open if `gh` absent or times out). |
|
|
81
81
|
| Bash command matching ship/push/deploy/release with an unread matched `MEMORY.md` entry | `memory-read-check` | Blocks the command with a list of memory files to Read first. |
|
|
82
82
|
| Session end with `~/.claude/tmp/` growth > 20 entries | `residue-audit` | Advisory stderr warning; never blocks. |
|
|
83
|
-
| Session stop with fresh test/probe residue: `tmp.XXXXXX` / `claudemd-*` directories in `~/.claude/tmp` or `/var/tmp`, `claudemd-*` in `/tmp`, or a `~/.claude/projects/` dir left by a headless `claude -p` run from a temp cwd (the session's own transcript dir excluded); judged since the session's previous Stop, by mtime, so a concurrent session's sandbox can show up | `sandbox-disposal-check` | Advisory stderr warning by default. Opt-in `SANDBOX_DISPOSAL_BLOCK=1` (v0.97.0+, default OFF) returns `{"decision":"block"}` naming up to five, with a reason that some may belong to another session, so the session removes the ones it created before finishing, once per turn (`stop_hook_active`). |
|
|
83
|
+
| Session stop with fresh test/probe residue: `tmp.XXXXXX` / `claudemd-*` directories in `~/.claude/tmp` or `/var/tmp`, `claudemd-*` in `/tmp`, or a `~/.claude/projects/` dir left by a headless `claude -p` run from a temp cwd (the session's own transcript dir excluded); judged since the session's previous Stop, by mtime, so a concurrent session's sandbox can show up. Since v0.98.0 a directory is reported only if it is still there at the session's NEXT Stop, so a dir a background run removes on its own is not reported; `SANDBOX_DISPOSAL_IMMEDIATE=1` reports at first sight as before | `sandbox-disposal-check` | Advisory stderr warning by default. Opt-in `SANDBOX_DISPOSAL_BLOCK=1` (v0.97.0+, default OFF) returns `{"decision":"block"}` naming up to five, with a reason that some may belong to another session, so the session removes the ones it created before finishing, once per turn (`stop_hook_active`). |
|
|
84
84
|
| Session end (Stop), at most once per 24h | `mem-audit` (v0.9.4+) | Scans CC auto-memory `~/.claude/projects/*/memory/feedback_*.md` for missing `**Why:**` / `**How to apply:**` body structure plus MEMORY.md ↔ files index drift; advisory stderr, never blocks. |
|
|
85
85
|
| Session end | `session-summary` (v0.8.0+) | Writes `~/.claude/.claudemd-state/last-session-summary.json`; banner emit at next `SessionStart`. |
|
|
86
86
|
| New session start with GitHub remote tag newer than local cache max version | `session-start-check` (v0.4.0+) | Injects an "upgrade available" banner via `additionalContext`. Rate-limited to once per 24h via `~/.claude/.claudemd-state/upstream-check.lastrun` sentinel. 3-second `git ls-remote` timeout, fail-open. |
|
|
@@ -90,7 +90,7 @@ Once installed, hooks run silently in the background. Verbose log: `~/.claude/lo
|
|
|
90
90
|
| Session stop with a completion claim in the last assistant message and no verification output behind it | `evidence-gate` (v0.90.0+) | Stop advisory — judges the TRANSCRIPT (is there a non-error Bash result after the last code edit whose command names a runner, or whose output looks like one) rather than the prose, which is what the prose-reading detector closed in the 2026-07-24 labeling pass, one of six closed there at a pooled precision bound of 0.17 were doing. Opt-in (`EVIDENCE_GATE=1`, default OFF) for FP signal collection. |
|
|
91
91
|
| Session stop after code edits, with a long-task ledger under `cwd` that nothing wrote to | `ledger-staleness` (v0.91.0+) | Stop advisory — the third G7 arm, beside the `SessionStart` re-injection. Both halves are transcript structure over the same tail window: a code-file `Edit`/`Write` in it, and no `Edit`/`Write` on the resolved `tasks/<slug>-ledger.md` in it. The window is a staleness threshold rather than a scanning budget, so a ledger written more than a window ago reads as behind. No ledger means the convention is not in use in this project; a ledger older than `CLAUDEMD_LEDGER_MAX_AGE_DAYS` (default 14) means a finished task. Either way it stays silent — and the age bound is skipped rather than guessed if `hooks/lib/platform.sh` is unavailable, so on that path an old ledger can still draw the advisory. Opt-in (`LEDGER_STALENESS=1`, default OFF) for FP signal collection. |
|
|
92
92
|
| Session stop whose last reply is English while the human writes 中文 | `reply-language-check` (v0.96.0+) | Stop, returning `{"decision":"block"}` (as `sandbox-disposal-check` does under its opt-in): the turn continues for one more message, asking for the same content in 中文 (no new work, no tools); the English text already shown stays. The human's language comes from the human's own messages only — task notifications, teammate messages, meta rows and tool results never count; a slash command counts by its arguments; a message typed mid-turn counts. The majority language of the human's newest 20 messages decides, so one pasted English log does not flip a 中文 session. What the human says about language is not parsed: a 中文 request for English replies, a translation or an `英文版` still gets a 中文 restatement — turn the hook off or set it to `log` for that. A reply whose first line is a conventional-commit subject is not judged. Headless `claude -p` runs are skipped, and it asks at most once per turn (`stop_hook_active`). Opt-in: `REPLY_LANGUAGE_CHECK=1`, or `=log` to record without asking; default OFF. |
|
|
93
|
-
| `PostToolUse` on `Edit`/`Write`, at each 8th edit of one file in one session | `rework-breaker` (v0.90.0+) | Advisory; injects one line naming the count (§1 Root cause over patch). Opt-in (`REWORK_BREAKER=1`, default OFF) for FP signal collection — a large legitimate refactor looks identical from here. |
|
|
93
|
+
| `PostToolUse` on `Edit`/`Write`/`Bash`, at each 8th edit of one file in one session (a Bash command counts once per code file its `bashEditDiff` lists; one changing more than 20 is skipped as bulk, v0.99.0+) | `rework-breaker` (v0.90.0+) | Advisory; injects one line naming the count (§1 Root cause over patch). Opt-in (`REWORK_BREAKER=1`, default OFF) for FP signal collection — a large legitimate refactor looks identical from here. |
|
|
94
94
|
| `PreToolUse` on `Edit`/`Write`/`NotebookEdit`/`Bash`, when the target is a git repo other than the session's project | `cross-repo-write-check` (v0.95.0+) | Advisory, never a verdict; injects one line per target repo per session: stop and ask unless the user asked for that repo, and use `git worktree add` rather than switching branches in its shared tree. Bash side sees git writes after a literal `cd` or `git -C` only. Opt-in (`CROSS_REPO_WRITE=1`, default OFF); `CROSS_REPO_WRITE_ALLOW` takes colon-separated absolute repo roots (a leading `~/` or `$HOME/` is expanded). |
|
|
95
95
|
| `PostToolUse` on any `Bash` call, at most once per 10 min | `tmp-sweep` (v0.93.0+) | Deletes, detached, the per-run dirs vitest leaves in the temp root and never removes (`<tmp>/<21-char id>/ssr/<sha1>`, 13-45 MB each; on a tmpfs `/tmp` that is RAM). Only the exact vitest signature, only when idle 60 min (24 h while a vitest watcher runs), across `$TMPDIR`, `/tmp` and `~/.cache/tmp`. Also injects one line when the temp root (`$TMPDIR`, else `/tmp`) is ≥ 80% full. Parallel Bash calls claim the slot atomically, so one sweep runs (a few can overlap only while a lock left by a killed hook is being cleared). **On by default.** |
|
|
96
96
|
| `PostToolUse` after `git merge` / `pull` / `fetch` / `push` or `gh pr merge` | `branch-prune` (v0.93.0+) | Advisory. Lists the local branches whose remote branch was deleted (`[gone]`) and whose tip is on the default branch, plus `worktree-agent-*` branches on it, with the `git branch -d` command that deletes them; git re-checks merged-ness and use at the moment of deletion. Never lists the default branch, a worktree checkout or a symbolic ref, nor (`worktree-agent-*` aside) a branch whose upstream still exists or one with no upstream. Deletes nothing. Local git only. **On by default.** |
|
|
@@ -123,7 +123,7 @@ Per-hook timeout (3-5s in `hooks.json`); timeout = treated as exit 0 (pass) per
|
|
|
123
123
|
| `/claudemd-doctor [--prune-backups=N]` | Health checks; optionally prune each backup namespace (`~/.claude/backup-*`, `spec-backup-*`, `handhook-backup-*`) to its N newest. Dirs the `backup-namespace-legacy` check reports (pre-0.68.3 spec backups sitting in the personal namespace) are skipped — neither deleted nor counted toward N — and echoed under `pruneSkippedLegacy`. v0.7.1+ also flags rule sections whose bypass:deny ratio > 50% (R-N6 §0.1 demotion candidates). |
|
|
124
124
|
| `/claudemd-rules [N]` | v0.8.0+ — audit `spec/hard-rules.json` manifest over last N days (default 30 — lowered from 90d in v0.13.1 after the 90d gate was structurally unreachable under typical log retention). Surfaces `demoteCandidates` (hook-enforced rules with 0 hits) and `staleReviews` (rules whose `last_demote_review` is null/old). |
|
|
125
125
|
| `/claudemd-sparkline [--days=A,B,C]` | v0.8.4+ R-N9 — per-`spec_section` cumulative counts of signal events across 3 windows (default 30/60/90d). Trend arrow compares per-period rate; `(newly active)` / `(silenced)` annotations flag activation/deactivation transitions. Markdown block suitable for CHANGELOG header pre-release. |
|
|
126
|
-
| `/claudemd-clean-residue [--apply]` | Dry-run-by-default cleanup across
|
|
126
|
+
| `/claudemd-clean-residue [--apply]` | Dry-run-by-default cleanup across four scopes: `$TMPDIR` (`claudemd-sync-*` / `claudemd-memtags-hay-*` sentinels, historical `claudemd-(mockgh\|work).*` sandboxes), `~/.claude/tmp` tool-exhaust past the §EXT §7-EXT retention window, the seven ephemeral classes in `~/.claude/.claudemd-state`, and headless-probe dirs (`-tmp-*`, `-var-tmp`, every transcript `entrypoint: sdk-cli`) in `~/.claude/projects` past the same window, never an interactive session's or one holding a memory file. Exits 3 if `--apply` leaves targets behind. |
|
|
127
127
|
| `/claudemd-design-adopt [check\|remove]` | v0.24.0 — for a UI project, generate a thin, fact-based `DESIGN.md` from its real design-token sources (deterministic detector `scripts/design-detect.js`; evidence-gated rules menu; never invents values) and wire a sentinel block into project CLAUDE.md. `check` verifies pointers resolve; `remove` unwires. Always shows the diff and asks before writing. Manual/opt-in — no SessionStart hook, nothing auto-fires. |
|
|
128
128
|
| `/claudemd-statusline [check\|remove] [--force]` | v0.25.0 — register claudemd's PS1-style statusLine into `~/.claude/settings.json`. Default adopts into an empty slot; `check` reports the current owner with no writes; `remove` restores the prior statusline (or clears the slot) and deletes `~/.claude/claudemd-statusline.sh`; `--force` takes over another provider's slot, saving its command so `remove` can restore it. Always shows the diff and asks before writing. Install-time auto-adopt is empty-slot-only (opt-out: `CLAUDEMD_NO_STATUSLINE=1`). When another composite provider (e.g. code-graph) owns the slot, claudemd registers as a guest so both segments render; `--supersede=<id>` replaces a named provider. |
|
|
129
129
|
| `/claudemd-uninstall` | Pre-uninstall cleanup: clears manifest + legacy `settings.json` hook entries; add `CLAUDEMD_PURGE=1` to also drop `~/.claude/.claudemd-state/` + the rule-hits log. Run BEFORE `/plugin uninstall claudemd@claudemd` (see [Uninstall](#uninstall)). |
|
|
@@ -189,12 +189,12 @@ export DISABLE_SHIP_BASELINE_HOOK=1 # or
|
|
|
189
189
|
export DISABLE_RESIDUE_AUDIT_HOOK=1 # or
|
|
190
190
|
export DISABLE_MEMORY_READ_HOOK=1 # or
|
|
191
191
|
export DISABLE_MEMORY_HINT_HOOK=1 # v0.11.0+ — UserPromptSubmit MEMORY.md tag pre-matcher (proactive §11 hint)
|
|
192
|
-
export DISABLE_SANDBOX_DISPOSAL_HOOK=1 # Stop §8.V4 residue scan (opt-in block: SANDBOX_DISPOSAL_BLOCK=1, v0.97.0+)
|
|
192
|
+
export DISABLE_SANDBOX_DISPOSAL_HOOK=1 # Stop §8.V4 residue scan (opt-in block: SANDBOX_DISPOSAL_BLOCK=1, v0.97.0+; first-sight timing: SANDBOX_DISPOSAL_IMMEDIATE=1, v0.98.0+)
|
|
193
193
|
export DISABLE_SESSION_START_HOOK=1 # or
|
|
194
194
|
export DISABLE_SESSION_SUMMARY_HOOK=1 # v0.8.0+ — Stop hook writing summary
|
|
195
195
|
export DISABLE_USER_PROMPT_SUBMIT_HOOK=1 # version-sync (mid-session upgrade re-install)
|
|
196
196
|
export DISABLE_TRANSCRIPT_VOCAB_SCAN_HOOK=1 # PostToolUse §10-V advisory scan
|
|
197
|
-
export DISABLE_REWORK_BREAKER_HOOK=1 # v0.90.0+ — PostToolUse:Edit|Write G2 rework advisory (§1 root-cause; opt-in REWORK_BREAKER=1)
|
|
197
|
+
export DISABLE_REWORK_BREAKER_HOOK=1 # v0.90.0+ — PostToolUse:Edit|Write|Bash G2 rework advisory (§1 root-cause; opt-in REWORK_BREAKER=1)
|
|
198
198
|
export DISABLE_CROSS_REPO_WRITE_HOOK=1 # v0.95.0+ — PreToolUse cross-repo write advisory (§5 scope; opt-in CROSS_REPO_WRITE=1)
|
|
199
199
|
export DISABLE_TMP_SWEEP_HOOK=1 # v0.93.0+ — PostToolUse:Bash vitest tmp-dir sweep + temp-root pressure advisory
|
|
200
200
|
export DISABLE_BRANCH_PRUNE_HOOK=1 # v0.93.0+ — PostToolUse:Bash hint listing local branches that are merged and whose remote branch is gone
|
|
@@ -225,6 +225,11 @@ export DISABLE_COMPACT_REREAD_REMINDER=1 # v0.27.0+ — only the post-compacti
|
|
|
225
225
|
# source=="compact"); compact events still
|
|
226
226
|
# skip bootstrap/upgrade-banner either way.
|
|
227
227
|
|
|
228
|
+
export DISABLE_PAUSED_BANNER=1 # v0.98.0+ — only the SessionStart list of
|
|
229
|
+
# tasks/*-paused.md checkpoints (names + ages,
|
|
230
|
+
# 5 newest; startup / resume / clear, never
|
|
231
|
+
# compact).
|
|
232
|
+
|
|
228
233
|
export DISABLE_LEDGER_INJECT=1 # v0.90.0+ — only the G7 long-task ledger
|
|
229
234
|
# injection (SessionStart source=="compact" or
|
|
230
235
|
# "resume" re-injects tasks/<slug>-ledger.md's
|
|
@@ -433,7 +438,7 @@ claudemd/
|
|
|
433
438
|
├── commands/ # 16 slash-command markdown files
|
|
434
439
|
├── bin/ # standalone CLI entrypoint (claudemd-lint.js → `npx claudemd-cli` on npmjs.org)
|
|
435
440
|
├── scripts/ # 20 Node.js scripts + scripts/lib/ (single-source registry, lint, etc.)
|
|
436
|
-
├── spec/ # shipped v6.
|
|
441
|
+
├── spec/ # shipped v6.35 CLAUDE*.md trio + OPERATOR.md + hard-rules.json manifest
|
|
437
442
|
├── tests/ # hook shell tests + Node.js tests + integration + fixtures
|
|
438
443
|
├── docs/ # ADDING-NEW-HOOK.md + RULE-HITS-SCHEMA.md + superpowers/
|
|
439
444
|
└── .github/workflows/ # ci.yml (ubuntu+macOS × node 20/22/24) + npm-publish.yml (tag-triggered)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudemd-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.99.0",
|
|
4
4
|
"description": "Standalone CLI for §10-V banned-vocab + transcript scanning. Companion to the claudemd Claude Code plugin (github.com/sdsrss/claudemd) for use in git pre-commit hooks, GitHub Actions, and other agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|