claudemd-cli 0.100.0 → 0.101.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 +20 -15
- 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
|
|
3
|
+
> A **personal AI-coding discipline harness**: one developer's opinionated **AI-CODING-SPEC v7.0**, 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
|
|
9
|
+
claudemd plugs into the Claude Code hook system to **block commits, pushes, and bash commands** that violate AI-CODING-SPEC v7.0 — 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
|
|
|
@@ -57,10 +57,10 @@ Verify in one command (Linux): `node --version && jq --version && gh --version &
|
|
|
57
57
|
|
|
58
58
|
| Layer | Contents |
|
|
59
59
|
|---|---|
|
|
60
|
-
|
|
|
60
|
+
| 24 shell hooks | `banned-vocab-check` · `pre-bash-safety-check` · `ship-baseline-check` · `residue-audit` · `memory-read-check` · `memory-prompt-hint` · `spec-module-inject` · `spec-module-gate` · `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
|
|
63
|
+
| Spec v7.0 | `~/.claude/CLAUDE.md` · `CLAUDE-extended.md` · `CLAUDE-changelog.md` · `OPERATOR.md` (backup-before-overwrite) · `spec-modules/*.md` (mirrored from the plugin) |
|
|
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.
|
|
@@ -83,9 +83,11 @@ Once installed, hooks run silently in the background. Verbose log: `~/.claude/lo
|
|
|
83
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
|
-
| New session start with GitHub remote tag newer than local cache max version | `session-start-check` (v0.4.0+) |
|
|
86
|
+
| New session start with GitHub remote tag newer than local cache max version | `session-start-check` (v0.4.0+) | Shows an "upgrade available" notice to the user via `systemMessage`. Rate-limited to once per 24h via `~/.claude/.claudemd-state/upstream-check.lastrun` sentinel. 3-second `git ls-remote` timeout, fail-open. |
|
|
87
87
|
| New session start with a `~/.claude/CLAUDE*.md` / `OPERATOR.md` that is edited, or **missing** | `session-start-check` (v0.84.0+ for the missing half) | Two banners, because the fixes differ: an edited file says `/claudemd-update`, a deleted one says `/claudemd-install`. A deleted spec is the louder case — Claude Code reads these as your user-global instructions, so its absence silently unloads the spec. Silence both with `DISABLE_SPEC_DRIFT_BANNER=1`. |
|
|
88
88
|
| New session start with a `~/.claude/.claudemd-manifest.json` that exists but does not parse | `session-start-check` (v0.84.0+) | Re-runs the bootstrap, which rewrites the manifest atomically. Previously this state exited silently on every session, forever. |
|
|
89
|
+
| `UserPromptSubmit` whose text matches a spec module's `triggers:` (a module not yet injected this session) | `spec-module-inject` (v0.101.0+) | Adds the module's body from `~/.claude/spec-modules/` as context: at most two modules per prompt, `ship` first, each once per session and again after a compaction. On by default; `DISABLE_SPEC_MODULE_INJECT_HOOK=1` turns it off. |
|
|
90
|
+
| Bash release command (`git tag v1.2.3`, `git push --tags`, `gh release create`, `npm publish`) in a session that never received `ship.md` | `spec-module-gate` (v0.101.0+) | Default `log`: one `module-unread` rule-hits row, no output. `SPEC_MODULE_GATE=advisory` adds a note; `deny` refuses the command; `off` or `DISABLE_SPEC_MODULE_GATE_HOOK=1` silences it. |
|
|
89
91
|
| First `UserPromptSubmit` after a mid-session `/plugin install` upgrade | `version-sync` (v0.3.1+) | Backgrounds `install.js` once per session when the manifest version diverges from the active plugin's `package.json`. Sentinel-gated; fail-open. |
|
|
90
92
|
| 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
93
|
| 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. |
|
|
@@ -99,16 +101,17 @@ Once installed, hooks run silently in the background. Verbose log: `~/.claude/lo
|
|
|
99
101
|
|
|
100
102
|
### Execution order (PreToolUse:Bash)
|
|
101
103
|
|
|
102
|
-
CC runs all configured PreToolUse hooks for `Bash` sequentially in declaration order. **First deny stops the rest** and the tool call is denied. The
|
|
104
|
+
CC runs all configured PreToolUse hooks for `Bash` sequentially in declaration order. **First deny stops the rest** and the tool call is denied. The 5 hooks in the `Bash` matcher group fire in this order (declared in `hooks/hooks.json`; `cross-repo-write-check`, opt-in and advisory, runs on Bash from its own `Edit|Write|NotebookEdit|Bash` group):
|
|
103
105
|
|
|
104
106
|
1. `pre-bash-safety-check` (§8 SAFETY immutable) — `rm -rf $VAR`, unpinned `npx <pkg>`. First so a §8 violation can never be overridden by a downstream hook.
|
|
105
|
-
2. `
|
|
106
|
-
3. `
|
|
107
|
-
4. `
|
|
107
|
+
2. `spec-module-gate` (core §2.2) — a release command in a session without `ship.md`; logs by default, denies only under `SPEC_MODULE_GATE=deny`.
|
|
108
|
+
3. `banned-vocab-check` (§10-V) — `git commit` message scan.
|
|
109
|
+
4. `ship-baseline-check` (§7) — `git push` while base CI is red.
|
|
110
|
+
5. `memory-read-check` (§11) — ship/release/deploy commands matching unread MEMORY.md tags.
|
|
108
111
|
|
|
109
112
|
Per-hook timeout (3-5s in `hooks.json`); timeout = treated as exit 0 (pass) per fail-open contract. Stop / SessionStart / UserPromptSubmit / PostToolUse hooks run all declared hooks regardless (none can block; advisories accumulate). Internal hook errors (missing `jq`, malformed event JSON, unreadable patterns file) fail-open; failures do NOT propagate to subsequent hooks.
|
|
110
113
|
|
|
111
|
-
**Readonly fast-path** (v0.8.3 introduced opt-in default-OFF; **v0.20.0 promoted to default-ON** via §13.3 advisory→enforce gate):
|
|
114
|
+
**Readonly fast-path** (v0.8.3 introduced opt-in default-OFF; **v0.20.0 promoted to default-ON** via §13.3 advisory→enforce gate): the four Bash hooks other than `spec-module-gate` (which matches release commands only) short-circuit when the command is a definitely-read-only shape (no shell-meta, first token in safe-reader whitelist — `ls`, `cat`, `git log`, `git status`, `git diff`, `git rev-parse`, `pwd`, `echo`, `head`, `tail`, etc.). Opt-out: `export BASH_READONLY_FAST_PATH=0` (or any other value than the literal `0` is treated as ON).
|
|
112
115
|
|
|
113
116
|
## Commands
|
|
114
117
|
|
|
@@ -189,6 +192,8 @@ export DISABLE_SHIP_BASELINE_HOOK=1 # or
|
|
|
189
192
|
export DISABLE_RESIDUE_AUDIT_HOOK=1 # or
|
|
190
193
|
export DISABLE_MEMORY_READ_HOOK=1 # or
|
|
191
194
|
export DISABLE_MEMORY_HINT_HOOK=1 # v0.11.0+ — UserPromptSubmit MEMORY.md tag pre-matcher (proactive §11 hint)
|
|
195
|
+
export DISABLE_SPEC_MODULE_INJECT_HOOK=1 # v0.101.0+ — UserPromptSubmit spec-module injection (core §2.2)
|
|
196
|
+
export DISABLE_SPEC_MODULE_GATE_HOOK=1 # v0.101.0+ — PreToolUse ship-module check before release commands (SPEC_MODULE_GATE=log|advisory|deny|off, default log)
|
|
192
197
|
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
198
|
export DISABLE_SESSION_START_HOOK=1 # or
|
|
194
199
|
export DISABLE_SESSION_SUMMARY_HOOK=1 # v0.8.0+ — Stop hook writing summary
|
|
@@ -357,7 +362,7 @@ After the plugin upgrade, sync the shipped spec into `~/.claude/`:
|
|
|
357
362
|
/claudemd-update
|
|
358
363
|
```
|
|
359
364
|
|
|
360
|
-
The command prints per-file diff summary, then prompts `apply-all` or `cancel`. Per-file select is intentionally not supported — the 4-file spec set (`CLAUDE.md` + `CLAUDE-extended.md` + `CLAUDE-changelog.md` + `OPERATOR.md`) evolves lockstep, and mixing versions would dangle `§EXT §X-EXT` cross-references in Core. Backup is automatic (retained to 5). `/claudemd-update` never fetches from GitHub — it only diffs the plugin-cache spec against your `~/.claude/CLAUDE*.md` + `~/.claude/OPERATOR.md`. The network fetch is Claude Code's job (via `/plugin marketplace update`).
|
|
365
|
+
The command prints per-file diff summary, then prompts `apply-all` or `cancel`. Per-file select is intentionally not supported — the 4-file spec set (`CLAUDE.md` + `CLAUDE-extended.md` + `CLAUDE-changelog.md` + `OPERATOR.md`) evolves lockstep, and mixing versions would dangle `§EXT §X-EXT` cross-references in Core. `apply-all` also syncs the `~/.claude/spec-modules/` mirror, which the diff summary does not list. Backup is automatic (retained to 5). `/claudemd-update` never fetches from GitHub — it only diffs the plugin-cache spec against your `~/.claude/CLAUDE*.md` + `~/.claude/OPERATOR.md`. The network fetch is Claude Code's job (via `/plugin marketplace update`).
|
|
361
366
|
|
|
362
367
|
---
|
|
363
368
|
|
|
@@ -380,7 +385,7 @@ Reversing the order is the orphan-state vector — `${CLAUDE_PLUGIN_ROOT}` and `
|
|
|
380
385
|
|---|---|---|
|
|
381
386
|
| `keep` (default) | (none) | `~/.claude/CLAUDE*.md` left in place; settings.json hook entries cleared. |
|
|
382
387
|
| `restore` | `CLAUDEMD_SPEC_ACTION=restore` | Copies the most recent `~/.claude/backup-<ISO>/*.md` back to `~/.claude/`. Use this if your install-time stderr showed `[claudemd] WARN: existing ~/.claude/CLAUDE.md does not look like a claudemd spec` — your hand-written user-global instructions are sitting in the backup waiting to be brought back. |
|
|
383
|
-
| `delete` | `CLAUDEMD_SPEC_ACTION=delete CLAUDEMD_CONFIRM=1` | Hard-AUTH: removes all four spec files (`CLAUDE*.md` + `OPERATOR.md`)
|
|
388
|
+
| `delete` | `CLAUDEMD_SPEC_ACTION=delete CLAUDEMD_CONFIRM=1` | Hard-AUTH: removes all four spec files (`CLAUDE*.md` + `OPERATOR.md`) and every regular `*.md` file in `~/.claude/spec-modules/`. |
|
|
384
389
|
|
|
385
390
|
`CLAUDEMD_PURGE=1` (env var) on `/claudemd-uninstall` also drops `~/.claude/.claudemd-state/` and your rule-hits log.
|
|
386
391
|
|
|
@@ -433,12 +438,12 @@ claudemd/
|
|
|
433
438
|
├── .claude-plugin/
|
|
434
439
|
│ ├── plugin.json # minimal manifest (name, version, author, license, keywords)
|
|
435
440
|
│ └── marketplace.json # marketplace catalog entry
|
|
436
|
-
├── hooks/ #
|
|
441
|
+
├── hooks/ # 24 shell hooks + hooks/lib/ (hook-common, rule-hits, platform, memory-tags)
|
|
437
442
|
│ └── hooks.json # authoritative hook registration (v0.1.5+); CC expands ${CLAUDE_PLUGIN_ROOT} here
|
|
438
443
|
├── commands/ # 16 slash-command markdown files
|
|
439
444
|
├── bin/ # standalone CLI entrypoint (claudemd-lint.js → `npx claudemd-cli` on npmjs.org)
|
|
440
|
-
├── scripts/ #
|
|
441
|
-
├── spec/ # shipped
|
|
445
|
+
├── scripts/ # 22 Node.js scripts + scripts/lib/ (single-source registry, lint, etc.)
|
|
446
|
+
├── spec/ # shipped v7.0 CLAUDE*.md trio + OPERATOR.md + hard-rules.json manifest
|
|
442
447
|
├── tests/ # hook shell tests + Node.js tests + integration + fixtures
|
|
443
448
|
├── docs/ # ADDING-NEW-HOOK.md + RULE-HITS-SCHEMA.md + superpowers/
|
|
444
449
|
└── .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.101.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": {
|