a1f95a1161
Replaces public-comms.md and code-comments.md (749 words, ~25 rules, almost all prohibitions, no examples) with a single writing.md that leads with worked examples. The rule is selection, not compression: keep output short by cutting whole ideas that don't change what the reader does next, then write what survives as plain sentences. Not by dropping articles or writing fragments, which Anthropic's Fable 5 guide calls out as the wrong lever. Prompt style leaks into output style, so the file is written in the voice it asks for. Drops the BLUF ask-line rule entirely: everyone on a PR already knows who reviews and who merges, and read literally it produced openers like "Ask: reviewers please merge". Links the contract to ~/.agents/AGENTS.md, which Codex had nothing in at all, and to the nix module for the NixOS machine.
41 lines
1.8 KiB
Markdown
41 lines
1.8 KiB
Markdown
# hooks
|
|
|
|
Claude Code hooks. Claude-only — Codex ignores. `bin/link.sh` / `nix/home.nix` symlink these into `~/.claude/hooks/`; **wiring is manual**, see below.
|
|
|
|
| hook | event | what |
|
|
|------|-------|------|
|
|
| `comms-lint.py` | `PreToolUse` / `Bash` | Gates `gh issue\|pr create\|edit\|comment\|review`. Lints body against `claude-md/writing.md` (150-word target / 300 hard cap above fold, no reviewer-addressing opener, plain diction, ≤4 bold spans, no essay headings). Exit 2 blocks, stderr becomes feedback. |
|
|
| `comment-lint.py` | `PostToolUse` / `Write\|Edit\|MultiEdit` | Lints newly-added comment lines in code files against `claude-md/writing.md`. Exit 2 = revise nudge (edit already applied). Long-comment-run finding (>3 lines) is advisory, delivered via `additionalContext`. |
|
|
|
|
Both fail open on anything they can't parse. Debug with `COMMS_LINT_DEBUG=1` / `COMMENT_LINT_DEBUG=1`.
|
|
|
|
## Wiring
|
|
|
|
`~/.claude/settings.json` is machine-local (MCP servers, statusline, per-box hooks), so this repo does not own it. Merge into `.hooks`:
|
|
|
|
```json
|
|
{
|
|
"hooks": {
|
|
"PreToolUse": [
|
|
{ "matcher": "Bash",
|
|
"hooks": [{ "type": "command", "command": "~/.claude/hooks/comms-lint.py" }] }
|
|
],
|
|
"PostToolUse": [
|
|
{ "matcher": "Write|Edit|MultiEdit",
|
|
"hooks": [{ "type": "command", "command": "~/.claude/hooks/comment-lint.py" }] }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Contract prose lives in `claude-md/writing.md`, linked to `~/.claude/writing.md` and imported from `~/.claude/CLAUDE.md` via `@writing.md`. Both linters cite that path in their block message — moving the fragment means updating the linter string too.
|
|
|
|
## Testing a hook
|
|
|
|
Feed it the payload shape Claude Code sends:
|
|
|
|
```sh
|
|
echo '{"tool_name":"Bash","tool_input":{"command":"gh pr comment 1 --body \"short\""}}' \
|
|
| ~/.claude/hooks/comms-lint.py; echo "exit=$?"
|
|
```
|