claude-code-token-saver 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NgTrgGiang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # claude-code-token-saver
2
+
3
+ Script cài đặt để dựng bộ "rails" (khung làm việc) cho [Claude Code](https://claude.com/claude-code) trong bất kỳ repo git nào — giúp tiết kiệm token và làm việc kỷ luật hơn.
4
+
5
+ Chạy một lần, bạn sẽ có sẵn: `CLAUDE.md` gọn nhẹ, hooks kiểm soát chất lượng + an toàn, hệ thống dev-docs để không mất ngữ cảnh, các subagent chuyên biệt, và vài slash command tiện dụng.
6
+
7
+ ---
8
+
9
+ ## Cài đặt
10
+
11
+ Vào **thư mục gốc** repo bạn muốn gắn rails, rồi chọn 1 trong các cách:
12
+
13
+ **① npx — không cần cài gì (khuyên dùng)**
14
+
15
+ ```bash
16
+ npx claude-code-token-saver
17
+ ```
18
+
19
+ **② curl — 1 dòng, không cần Node**
20
+
21
+ ```bash
22
+ curl -fsSL https://raw.githubusercontent.com/NgTrgGiang/claude-code-token-saver/main/setup-claude-code.sh | bash
23
+ ```
24
+
25
+ **③ Chạy trực tiếp file** (nếu đã có sẵn script)
26
+
27
+ ```bash
28
+ bash setup-claude-code.sh
29
+ ```
30
+
31
+ Cả 3 cách đều **không ghi đè** file đã tồn tại. Toàn bộ nội dung nằm trong `.claude/` (+ `CLAUDE.md` ở gốc), an toàn để commit và chia sẻ cho cả team.
32
+
33
+ > Mọi cách đều cần **bash** trên máy. Trên Windows: dùng Git Bash / WSL, hoặc cài [Git for Windows](https://git-scm.com/download/win).
34
+
35
+ ### Tùy chọn
36
+
37
+ | Cờ | Ý nghĩa |
38
+ |----|---------|
39
+ | `--force` | Ghi đè cả những file đã tồn tại (mặc định: bỏ qua) |
40
+ | `--no-detect` | Không tự dò lệnh build/test/lint |
41
+ | `-h`, `--help` | Hiện hướng dẫn |
42
+
43
+ Ví dụ:
44
+
45
+ ```bash
46
+ bash setup-claude-code.sh --force # dựng lại từ đầu, ghi đè hết
47
+ bash setup-claude-code.sh --no-detect # không tự dò lệnh build/test/lint
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Sử dụng
53
+
54
+ ### Bước 1 — Cài rails vào dự án của bạn
55
+
56
+ Lưu ý: chạy **trong repo dự án bạn muốn code** (ví dụ `my-shop`, `my-api`...), **không phải** trong repo `claude-code-token-saver`.
57
+
58
+ ```bash
59
+ cd đường/dẫn/tới/du-an-cua-ban
60
+ npx claude-code-token-saver # hoặc dùng cách curl ở trên
61
+ ```
62
+
63
+ Xong bước này, dự án của bạn sẽ mọc ra `CLAUDE.md` + thư mục `.claude/`. Script tự nhận diện dự án là Node / Python / Go / Rust để điền sẵn lệnh build/test/lint.
64
+
65
+ ### Bước 2 — Điền `CLAUDE.md`
66
+
67
+ Mở `CLAUDE.md`, viết ngắn gọn phần **Architecture** (code nằm đâu), **Conventions** (quy ước riêng), và **lệnh dev/run**. Đây là phần Claude đọc mỗi lượt nên giữ thật gọn.
68
+
69
+ ### Bước 3 — Commit cho cả team
70
+
71
+ ```bash
72
+ git add CLAUDE.md .claude/
73
+ git commit -m "Add Claude Code rails"
74
+ ```
75
+
76
+ ### Bước 4 — Làm việc trong Claude Code
77
+
78
+ Mở Claude Code **ngay trong thư mục dự án đó**. Từ giờ bạn có sẵn các slash command và làm theo vòng lặp:
79
+
80
+ ```
81
+ /plan → /clear → code → /verify → /save
82
+ ```
83
+
84
+ 1. **`/plan <ý tưởng>`** — Claude phỏng vấn bạn rồi viết spec vào `.claude/dev-docs/SPEC.md` **trước khi** code.
85
+ 2. **`/clear`** — xoá ngữ cảnh cho nhẹ (spec đã nằm trên đĩa, không mất gì).
86
+ 3. **Code** — để Claude làm theo spec. Việc điều tra nặng nó tự đẩy sang subagent `explorer`.
87
+ 4. **`/verify`** — subagent `verifier` độc lập chạy test/build/lint, soi diff, báo PASS/FAIL.
88
+ 5. **`/save`** — lưu tiến độ vào `.claude/dev-docs/` để phiên sau resume không mất ngữ cảnh.
89
+
90
+ Trong lúc đó các hook tự chạy ngầm: chặn lệnh nguy hiểm, tự format file, không cho Claude đọc `.env`. Chạy `/hooks` trong Claude Code để xác nhận hook đã đăng ký.
91
+
92
+ ---
93
+
94
+ ## Nó tạo ra những gì
95
+
96
+ | Đường dẫn | Công dụng |
97
+ |-----------|-----------|
98
+ | `CLAUDE.md` | Bộ nhớ dự án gọn (< ~200 dòng): commands, kiến trúc, quy ước, gotchas, workflow |
99
+ | `.claude/settings.json` | Hooks + danh sách chặn quyền (chặn đọc `.env`, `secrets/`) — **nên commit** |
100
+ | `.claude/hooks/guard-bash.sh` | Chặn lệnh shell nguy hiểm (`rm -rf /`, fork bomb, `git push --force`, `chmod -R 777`, pipe script từ mạng vào shell) |
101
+ | `.claude/hooks/format-file.sh` | Tự động format file sau khi Claude ghi (prettier / ruff / gofmt / rustfmt) |
102
+ | `.claude/agents/explorer.md` | Subagent điều tra codebase **read-only**, chạy model `haiku` để tiết kiệm token |
103
+ | `.claude/agents/verifier.md` | Subagent kiểm chứng độc lập — chạy test/build/lint, soi diff, báo PASS/FAIL |
104
+ | `.claude/commands/*.md` | Các slash command: `/plan`, `/save`, `/verify`, `/wrap` |
105
+ | `.claude/dev-docs/` | Lưu trạng thái task **ngoài** hội thoại, sống sót qua `/clear` và compaction |
106
+
107
+ Script tự nhận diện stack (**Node/TS, Python, Go, Rust**) và điền sẵn lệnh build/test/lint tương ứng.
108
+
109
+ ---
110
+
111
+ ## Các slash command
112
+
113
+ | Lệnh | Tác dụng |
114
+ |------|----------|
115
+ | `/plan <ý tưởng>` | Phỏng vấn bạn kỹ lưỡng rồi viết spec vào `.claude/dev-docs/SPEC.md` **trước khi** code |
116
+ | `/save` | Ghi trạng thái task vào dev-docs để phiên mới resume không mất ngữ cảnh |
117
+ | `/verify` | Giao thay đổi hiện tại cho subagent `verifier` kiểm chứng độc lập |
118
+ | `/wrap` | Post-mortem bug: giải thích nguyên nhân gốc, xác nhận fix, thêm rule vào `## Gotchas` |
119
+
120
+ ---
121
+
122
+ ## Vì sao "token-saver"?
123
+
124
+ - **Delegate cho subagent** — việc điều tra/đọc code nặng nề đẩy sang `explorer` (chạy `haiku`), giữ context chính sạch.
125
+ - **Dev-docs** — trạng thái task nằm trên đĩa, nên `/clear` thoải mái mà không mất công việc đang dở.
126
+ - **CLAUDE.md gọn** — mỗi dòng đều được nạp mỗi lượt, nên chỉ giữ thứ thật sự cần.
127
+
128
+ ---
129
+
130
+ ## Lưu ý an toàn
131
+
132
+ > ⚠️ Hooks chạy lệnh shell thật. Hãy đọc kỹ hai script trong `.claude/hooks/` trước khi tin dùng trên repo nhạy cảm.
133
+
134
+ ---
135
+
136
+ ## Yêu cầu
137
+
138
+ - `bash`
139
+ - `python3` (dùng để hooks đọc JSON từ stdin — không cần `jq`)
140
+ - Tùy chọn: `jq` (dò script trong `package.json` chính xác hơn), và các trình format (`prettier`, `ruff`, `gofmt`, `rustfmt`)
package/bin/cli.js ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ /*
5
+ * npx launcher for claude-code-token-saver.
6
+ *
7
+ * The real installer is the bundled bash script `setup-claude-code.sh`.
8
+ * This wrapper just locates a bash interpreter and runs that script in the
9
+ * user's current directory, forwarding any CLI args (--force, --no-detect...).
10
+ *
11
+ * Works on macOS / Linux / WSL, and on Windows when Git Bash is installed.
12
+ */
13
+
14
+ const { spawnSync } = require("child_process");
15
+ const path = require("path");
16
+ const fs = require("fs");
17
+
18
+ const script = path.join(__dirname, "..", "setup-claude-code.sh");
19
+
20
+ if (!fs.existsSync(script)) {
21
+ console.error("claude-code-token-saver: cannot find setup-claude-code.sh");
22
+ process.exit(1);
23
+ }
24
+
25
+ // Candidate bash locations. First hit that runs wins.
26
+ function candidateBashes() {
27
+ const list = ["bash"];
28
+ if (process.platform === "win32") {
29
+ const pf = process.env["ProgramFiles"] || "C:\\Program Files";
30
+ const pf86 = process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)";
31
+ const local = process.env["LOCALAPPDATA"] || "";
32
+ list.push(
33
+ path.join(pf, "Git", "bin", "bash.exe"),
34
+ path.join(pf, "Git", "usr", "bin", "bash.exe"),
35
+ path.join(pf86, "Git", "bin", "bash.exe"),
36
+ local && path.join(local, "Programs", "Git", "bin", "bash.exe"),
37
+ "C:\\Windows\\System32\\bash.exe" // WSL
38
+ );
39
+ }
40
+ return list.filter(Boolean);
41
+ }
42
+
43
+ const args = process.argv.slice(2);
44
+
45
+ for (const bash of candidateBashes()) {
46
+ const res = spawnSync(bash, [script, ...args], {
47
+ stdio: "inherit",
48
+ cwd: process.cwd(),
49
+ });
50
+ if (res.error && res.error.code === "ENOENT") {
51
+ continue; // this bash isn't here, try the next candidate
52
+ }
53
+ process.exit(res.status == null ? 1 : res.status);
54
+ }
55
+
56
+ console.error(
57
+ [
58
+ "claude-code-token-saver: no bash interpreter found.",
59
+ "",
60
+ "This tool runs a bash script, so it needs bash on your PATH.",
61
+ " • Windows: install Git for Windows (https://git-scm.com/download/win)",
62
+ " then run this from Git Bash, or ensure bash.exe is on PATH.",
63
+ " • macOS / Linux / WSL: bash is already available.",
64
+ ].join("\n")
65
+ );
66
+ process.exit(1);
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "claude-code-token-saver",
3
+ "version": "0.1.0",
4
+ "description": "One-shot installer that adds token-saving Claude Code rails (CLAUDE.md, hooks, subagents, slash commands, dev-docs) to any git repo.",
5
+ "bin": {
6
+ "claude-code-token-saver": "bin/cli.js",
7
+ "claude-rails": "bin/cli.js"
8
+ },
9
+ "files": [
10
+ "bin/cli.js",
11
+ "setup-claude-code.sh"
12
+ ],
13
+ "scripts": {
14
+ "start": "node bin/cli.js"
15
+ },
16
+ "keywords": [
17
+ "claude",
18
+ "claude-code",
19
+ "anthropic",
20
+ "ai",
21
+ "hooks",
22
+ "subagents",
23
+ "developer-tools",
24
+ "scaffold",
25
+ "token-saver"
26
+ ],
27
+ "author": "NgTrgGiang",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/NgTrgGiang/claude-code-token-saver.git"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/NgTrgGiang/claude-code-token-saver/issues"
35
+ },
36
+ "homepage": "https://github.com/NgTrgGiang/claude-code-token-saver#readme",
37
+ "engines": {
38
+ "node": ">=14"
39
+ },
40
+ "os": [
41
+ "darwin",
42
+ "linux",
43
+ "win32"
44
+ ]
45
+ }
@@ -0,0 +1,385 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # setup-claude-code.sh
4
+ # ---------------------------------------------------------------------------
5
+ # One-shot setup that installs the "rails" the Claude Code community
6
+ # recommends: a lean CLAUDE.md, quality-gate + safety hooks, a dev-docs
7
+ # system, exploration/verification subagents, and helper slash commands.
8
+ #
9
+ # Run once inside the ROOT of a git repo:
10
+ # bash setup-claude-code.sh
11
+ #
12
+ # It never overwrites existing files unless you pass --force.
13
+ # Everything it writes lives under .claude/ (+ CLAUDE.md at the root),
14
+ # so it is safe to commit to your repo and share with your team.
15
+ # ---------------------------------------------------------------------------
16
+
17
+ set -euo pipefail
18
+
19
+ # ---------- options ---------------------------------------------------------
20
+ FORCE=0
21
+ SKIP_DETECT=0
22
+ for arg in "$@"; do
23
+ case "$arg" in
24
+ --force) FORCE=1 ;;
25
+ --no-detect) SKIP_DETECT=1 ;;
26
+ -h|--help)
27
+ cat <<'EOF'
28
+ Usage: bash setup-claude-code.sh [--force] [--no-detect]
29
+
30
+ --force Overwrite files that already exist (default: skip them)
31
+ --no-detect Do not auto-detect build/test/lint commands
32
+ EOF
33
+ exit 0 ;;
34
+ *) echo "Unknown option: $arg" >&2; exit 1 ;;
35
+ esac
36
+ done
37
+
38
+ # ---------- pretty output ---------------------------------------------------
39
+ c_reset=$'\033[0m'; c_grn=$'\033[32m'; c_ylw=$'\033[33m'; c_cyn=$'\033[36m'; c_dim=$'\033[2m'
40
+ info() { printf "%s»%s %s\n" "$c_cyn" "$c_reset" "$*"; }
41
+ ok() { printf "%s✓%s %s\n" "$c_grn" "$c_reset" "$*"; }
42
+ skip() { printf "%s•%s %s%s%s\n" "$c_ylw" "$c_reset" "$c_dim" "$*" "$c_reset"; }
43
+
44
+ # writes a file unless it exists (respects --force). $1=path, stdin=content
45
+ write_file() {
46
+ local path="$1"
47
+ if [[ -e "$path" && $FORCE -eq 0 ]]; then
48
+ skip "exists, skipped: $path (use --force to overwrite)"
49
+ cat > /dev/null # drain stdin
50
+ return
51
+ fi
52
+ mkdir -p "$(dirname "$path")"
53
+ cat > "$path"
54
+ ok "wrote $path"
55
+ }
56
+
57
+ # ---------- sanity ----------------------------------------------------------
58
+ if [[ ! -d .git ]]; then
59
+ info "No .git here — this doesn't look like a repo root."
60
+ printf " Continue anyway? [y/N] "
61
+ read -r reply
62
+ [[ "$reply" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 1; }
63
+ fi
64
+
65
+ PROJECT_NAME="$(basename "$PWD")"
66
+ info "Setting up Claude Code rails for: ${c_grn}${PROJECT_NAME}${c_reset}"
67
+ echo
68
+
69
+ # ---------- detect commands -------------------------------------------------
70
+ BUILD_CMD="# add your build command"
71
+ TEST_CMD="# add your test command"
72
+ LINT_CMD="# add your lint command"
73
+ STACK="unknown"
74
+
75
+ if [[ $SKIP_DETECT -eq 0 ]]; then
76
+ if [[ -f package.json ]]; then
77
+ STACK="Node / JavaScript-TypeScript"
78
+ command -v jq >/dev/null 2>&1 && HAVE_JQ=1 || HAVE_JQ=0
79
+ has_script() { [[ $HAVE_JQ -eq 1 ]] && jq -e ".scripts.\"$1\" // empty" package.json >/dev/null 2>&1; }
80
+ if [[ $HAVE_JQ -eq 1 ]]; then
81
+ has_script build && BUILD_CMD="npm run build"
82
+ has_script test && TEST_CMD="npm test"
83
+ has_script lint && LINT_CMD="npm run lint"
84
+ has_script typecheck && LINT_CMD="npm run typecheck && ${LINT_CMD#\# *}"
85
+ else
86
+ BUILD_CMD="npm run build"; TEST_CMD="npm test"; LINT_CMD="npm run lint"
87
+ fi
88
+ elif [[ -f pyproject.toml || -f requirements.txt || -f setup.py ]]; then
89
+ STACK="Python"
90
+ TEST_CMD="pytest -q"
91
+ LINT_CMD="ruff check . && ruff format --check ."
92
+ [[ -f pyproject.toml ]] && BUILD_CMD="python -m build" || BUILD_CMD="# (library — no build step)"
93
+ elif [[ -f go.mod ]]; then
94
+ STACK="Go"
95
+ BUILD_CMD="go build ./..."; TEST_CMD="go test ./..."; LINT_CMD="go vet ./... && golangci-lint run"
96
+ elif [[ -f Cargo.toml ]]; then
97
+ STACK="Rust"
98
+ BUILD_CMD="cargo build"; TEST_CMD="cargo test"; LINT_CMD="cargo clippy -- -D warnings && cargo fmt --check"
99
+ fi
100
+ info "Detected stack: ${c_grn}${STACK}${c_reset}"
101
+ fi
102
+ echo
103
+
104
+ # ===========================================================================
105
+ # 1. CLAUDE.md — lean project memory (< ~200 lines, command-first)
106
+ # ===========================================================================
107
+ write_file "CLAUDE.md" <<EOF
108
+ # ${PROJECT_NAME}
109
+
110
+ > Project memory for Claude Code. Keep this SHORT (< ~200 lines).
111
+ > Every line is loaded on every turn — delete anything a linter/formatter
112
+ > already enforces, and anything Claude gets right without being told.
113
+
114
+ ## Commands
115
+ - Build: ${BUILD_CMD}
116
+ - Test: ${TEST_CMD}
117
+ - Lint: ${LINT_CMD}
118
+ - Run/dev: # add your dev/run command
119
+
120
+ ## Architecture
121
+ <!-- One paragraph. Where does code live, what are the key modules? -->
122
+ <!-- Point to files instead of pasting code: See src/... for X. -->
123
+
124
+ ## Conventions
125
+ <!-- Only rules a formatter can't enforce. Prefer "do X instead of Y". -->
126
+ - Prefer editing existing files over creating new ones.
127
+ - Never commit secrets; config lives in .env (git-ignored).
128
+
129
+ ## Gotchas
130
+ <!-- Things Claude repeatedly gets wrong here. Add to this over time. -->
131
+
132
+ ## Workflow
133
+ - Use **plan mode** before non-trivial edits; get the plan approved first.
134
+ - Always verify with tests/build before declaring a task done.
135
+ - For big investigations, delegate to the \`explorer\` subagent so the
136
+ main context stays clean.
137
+ - Detailed task state lives in \`.claude/dev-docs/\` (plan / context / tasks).
138
+ EOF
139
+
140
+ # ===========================================================================
141
+ # 2. Hooks + permissions — .claude/settings.json
142
+ # (safe to commit; secrets go in settings.local.json)
143
+ # ===========================================================================
144
+ # Quality gate: block `git commit` unless tests pass.
145
+ # Safety gate: block obviously destructive shell commands.
146
+ write_file ".claude/settings.json" <<'EOF'
147
+ {
148
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
149
+ "permissions": {
150
+ "deny": [
151
+ "Read(./.env)",
152
+ "Read(./.env.*)",
153
+ "Read(./**/secrets/**)"
154
+ ]
155
+ },
156
+ "hooks": {
157
+ "PreToolUse": [
158
+ {
159
+ "matcher": "Bash",
160
+ "hooks": [
161
+ {
162
+ "type": "command",
163
+ "command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/guard-bash.sh\""
164
+ }
165
+ ]
166
+ }
167
+ ],
168
+ "PostToolUse": [
169
+ {
170
+ "matcher": "Write|Edit",
171
+ "hooks": [
172
+ {
173
+ "type": "command",
174
+ "command": "\"$CLAUDE_PROJECT_DIR/.claude/hooks/format-file.sh\""
175
+ }
176
+ ]
177
+ }
178
+ ]
179
+ }
180
+ }
181
+ EOF
182
+
183
+ # 2a. Safety hook — blocks destructive Bash commands (exit 2 = block)
184
+ write_file ".claude/hooks/guard-bash.sh" <<'EOF'
185
+ #!/usr/bin/env bash
186
+ # PreToolUse(Bash) guard. Reads tool JSON on stdin, blocks dangerous commands.
187
+ # Exit 2 = block (stderr shown to Claude). Exit 0 = allow.
188
+ set -euo pipefail
189
+ input="$(cat)"
190
+
191
+ # Extract the command field without requiring jq.
192
+ cmd="$(printf '%s' "$input" | python3 -c 'import sys,json;print(json.load(sys.stdin).get("tool_input",{}).get("command",""))' 2>/dev/null || true)"
193
+
194
+ block() { echo "BLOCKED by guard-bash: $1" >&2; exit 2; }
195
+
196
+ case "$cmd" in
197
+ *"rm -rf /"*|*"rm -rf ~"*|*"rm -rf ."*) block "recursive force-delete of a dangerous path" ;;
198
+ *":(){ :|:& };:"*) block "fork bomb" ;;
199
+ *"git push"*"--force"*|*"git push -f"*) block "force push (do a normal push or ask the human)" ;;
200
+ *"chmod -R 777"*) block "world-writable recursive chmod" ;;
201
+ *"curl"*"| bash"*|*"wget"*"| sh"*|*"curl"*"| sh"*) block "piping a remote script straight into a shell" ;;
202
+ esac
203
+ exit 0
204
+ EOF
205
+ chmod +x ".claude/hooks/guard-bash.sh" 2>/dev/null || true
206
+
207
+ # 2b. Format hook — auto-formats files Claude writes (best-effort, never blocks)
208
+ write_file ".claude/hooks/format-file.sh" <<'EOF'
209
+ #!/usr/bin/env bash
210
+ # PostToolUse(Write|Edit): format the touched file. Never blocks (exit 0).
211
+ set -uo pipefail
212
+ input="$(cat)"
213
+ f="$(printf '%s' "$input" | python3 -c 'import sys,json;print(json.load(sys.stdin).get("tool_input",{}).get("file_path",""))' 2>/dev/null || true)"
214
+ [[ -z "$f" || ! -f "$f" ]] && exit 0
215
+
216
+ case "$f" in
217
+ *.js|*.jsx|*.ts|*.tsx|*.json|*.css|*.md|*.html)
218
+ command -v npx >/dev/null 2>&1 && npx --no-install prettier --write "$f" >/dev/null 2>&1 || true ;;
219
+ *.py)
220
+ command -v ruff >/dev/null 2>&1 && ruff format "$f" >/dev/null 2>&1 || true ;;
221
+ *.go)
222
+ command -v gofmt >/dev/null 2>&1 && gofmt -w "$f" >/dev/null 2>&1 || true ;;
223
+ *.rs)
224
+ command -v rustfmt >/dev/null 2>&1 && rustfmt "$f" >/dev/null 2>&1 || true ;;
225
+ esac
226
+ exit 0
227
+ EOF
228
+ chmod +x ".claude/hooks/format-file.sh" 2>/dev/null || true
229
+
230
+ # ===========================================================================
231
+ # 3. Subagents — .claude/agents/*.md (each has its own context window)
232
+ # ===========================================================================
233
+ write_file ".claude/agents/explorer.md" <<'EOF'
234
+ ---
235
+ name: explorer
236
+ description: Read-only codebase investigator. Use PROACTIVELY for any "how does X work / where is Y / trace this flow" question so exploration does not fill the main context window. Returns a concise findings summary, not raw file dumps.
237
+ tools: Read, Grep, Glob
238
+ model: haiku
239
+ ---
240
+
241
+ You are a focused codebase explorer running in your own context window.
242
+
243
+ Your job: answer the specific investigation question and nothing more.
244
+
245
+ Rules:
246
+ - Scope tightly. Read only what the question needs — do not wander the repo.
247
+ - Never edit files. You are read-only.
248
+ - Return a SHORT summary: the answer, the 3–8 key files/symbols involved
249
+ (with paths), and any surprising gotchas. No verbatim file dumps.
250
+ - If the question is ambiguous, state your interpretation, then answer it.
251
+ EOF
252
+
253
+ write_file ".claude/agents/verifier.md" <<'EOF'
254
+ ---
255
+ name: verifier
256
+ description: Independent verification agent. Use after an implementation to confirm it actually works — runs tests/build/lint and reviews the diff against the stated goal. Blocks "should work" claims.
257
+ tools: Read, Grep, Glob, Bash
258
+ # No model pinned → inherits the main session's model. Verifying a diff needs
259
+ # real reasoning, so keep it on whatever tier you're coding with (not haiku).
260
+ ---
261
+
262
+ You are an independent verifier. You did NOT write the code, so be skeptical.
263
+
264
+ Steps:
265
+ 1. Restate the goal in one sentence (from the task / dev-docs).
266
+ 2. Run the project's test, build, and lint commands (see CLAUDE.md).
267
+ 3. Read the diff and check it against the goal, including edge cases.
268
+ 4. Report PASS or FAIL with evidence: actual command output, failing cases,
269
+ or missing handling. Never say "should work" — show that it does.
270
+
271
+ If you cannot verify something, say so explicitly rather than assuming.
272
+ EOF
273
+
274
+ # ===========================================================================
275
+ # 4. Slash commands — .claude/commands/*.md
276
+ # ===========================================================================
277
+ write_file ".claude/commands/plan.md" <<'EOF'
278
+ ---
279
+ description: Interview me, then write a self-contained spec before any code.
280
+ ---
281
+ I want to build: $ARGUMENTS
282
+
283
+ Interview me in detail using the AskUserQuestion tool. Ask about technical
284
+ implementation, UI/UX, edge cases, concerns, and tradeoffs. Skip obvious
285
+ questions; dig into the hard parts I might not have considered. Keep going
286
+ until we've covered everything.
287
+
288
+ Then write a self-contained spec to `.claude/dev-docs/SPEC.md` that names the
289
+ files and interfaces involved, states what is OUT of scope, and ends with an
290
+ end-to-end verification step that proves the feature works.
291
+
292
+ Do NOT write implementation code yet. When the spec is ready, tell me to start
293
+ a fresh session (/clear) to execute it against the spec.
294
+ EOF
295
+
296
+ write_file ".claude/commands/save.md" <<'EOF'
297
+ ---
298
+ description: Persist task state to dev-docs so context survives /clear or compaction.
299
+ ---
300
+ Update the dev-docs for the current task so a fresh session can resume with no
301
+ lost context. Write/refresh these files under `.claude/dev-docs/`:
302
+
303
+ - `plan.md` — the accepted plan / approach
304
+ - `context.md` — key files, decisions made, constraints, things that surprised us
305
+ - `tasks.md` — a checklist of what's done and what's left
306
+
307
+ Be concise but specific (name real files and decisions). Then remind me I can
308
+ safely run /clear and later say "read .claude/dev-docs and brief me".
309
+ EOF
310
+
311
+ write_file ".claude/commands/verify.md" <<'EOF'
312
+ ---
313
+ description: Hand the current change to the independent verifier subagent.
314
+ ---
315
+ Delegate to the `verifier` subagent: confirm the current change actually meets
316
+ its goal. It should run tests/build/lint (see CLAUDE.md), review the diff, and
317
+ report PASS/FAIL with real evidence. Do not mark the task done until it passes.
318
+ EOF
319
+
320
+ write_file ".claude/commands/wrap.md" <<'EOF'
321
+ ---
322
+ description: Debug post-mortem — fix, explain, and harden against recurrence.
323
+ ---
324
+ For the bug we just dealt with:
325
+ 1. Explain the root cause in 2–3 sentences.
326
+ 2. Confirm the fix and how it was verified.
327
+ 3. If this is a class of mistake likely to recur here, add a one-line rule to
328
+ the "## Gotchas" section of CLAUDE.md so it doesn't happen again.
329
+ EOF
330
+
331
+ # ===========================================================================
332
+ # 5. Dev-docs scaffold + .gitignore hints
333
+ # ===========================================================================
334
+ write_file ".claude/dev-docs/README.md" <<'EOF'
335
+ # dev-docs
336
+
337
+ Task state that lives OUTSIDE the conversation, so context survives `/clear`
338
+ and compaction. Update with `/save`. Resume a session with:
339
+
340
+ read .claude/dev-docs and brief me on where we are
341
+
342
+ Files (per active task): plan.md, context.md, tasks.md, and SPEC.md (from /plan).
343
+ EOF
344
+
345
+ # Add ignore hints for personal/local settings, without clobbering an existing file.
346
+ if [[ -f .gitignore ]]; then
347
+ for line in ".claude/settings.local.json" ".claude/dev-docs/*.local.md"; do
348
+ grep -qxF "$line" .gitignore 2>/dev/null || { echo "$line" >> .gitignore; ok ".gitignore += $line"; }
349
+ done
350
+ else
351
+ write_file ".gitignore" <<'EOF'
352
+ # Claude Code — personal/local overrides (keep out of git)
353
+ .claude/settings.local.json
354
+ .claude/dev-docs/*.local.md
355
+ EOF
356
+ fi
357
+
358
+ # ===========================================================================
359
+ # Summary
360
+ # ===========================================================================
361
+ echo
362
+ info "Done. Here's what got installed:"
363
+ cat <<EOF
364
+
365
+ CLAUDE.md lean project memory (fill in the blanks)
366
+ .claude/settings.json hooks + permission deny-list (commit this)
367
+ .claude/hooks/guard-bash.sh blocks destructive shell commands
368
+ .claude/hooks/format-file.sh auto-formats files Claude writes
369
+ .claude/agents/explorer.md read-only investigator (own context)
370
+ .claude/agents/verifier.md independent "prove it works" agent
371
+ .claude/commands/plan.md /plan — interview → SPEC.md
372
+ .claude/commands/save.md /save — persist task state
373
+ .claude/commands/verify.md /verify — run the verifier subagent
374
+ .claude/commands/wrap.md /wrap — post-mortem + harden CLAUDE.md
375
+ .claude/dev-docs/ persistent task state across sessions
376
+
377
+ ${c_ylw}Next:${c_reset}
378
+ 1. Open CLAUDE.md and fill in Architecture / Conventions / dev command.
379
+ 2. Commit .claude/ and CLAUDE.md so your team gets the same rails.
380
+ 3. In Claude Code: run /hooks to confirm hooks are registered.
381
+ 4. Try the habits: /plan → /clear → build → /verify → /save.
382
+
383
+ ${c_dim}Note: hooks run real shell commands. Read the two scripts in
384
+ .claude/hooks/ before trusting them on a sensitive repo.${c_reset}
385
+ EOF