@gannonh/kata 1.1.1 → 1.1.2
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 +22 -0
- package/README.md +600 -0
- package/hooks/dist/kata-check-update.js +70 -0
- package/hooks/dist/kata-npm-statusline.js +100 -0
- package/hooks/dist/kata-plugin-statusline.js +91 -0
- package/hooks/dist/kata-setup-statusline.js +85 -0
- package/hooks/dist/kata-statusline.js +100 -0
- package/kata/VERSION +1 -0
- package/package.json +8 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Lex Christopherson
|
|
4
|
+
Copyright (c) 2026 Gannon Hall
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,600 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# KATA
|
|
4
|
+
|
|
5
|
+
**型** · /ˈkɑːtɑː/ · *noun*
|
|
6
|
+
<br>
|
|
7
|
+
<sub>a choreographed pattern practiced repeatedly until perfected</sub>
|
|
8
|
+
|
|
9
|
+
<br>
|
|
10
|
+
|
|
11
|
+
Agent orchestration framework for spec-driven development.
|
|
12
|
+
<br>
|
|
13
|
+
|
|
14
|
+
[kata.sh](https://kata.sh)
|
|
15
|
+
|
|
16
|
+
<br>
|
|
17
|
+
|
|
18
|
+
[](https://github.com/gannonh/kata-marketplace)
|
|
19
|
+
[](https://www.npmjs.com/package/@gannonh/kata)
|
|
20
|
+
|
|
21
|
+
<br>
|
|
22
|
+
|
|
23
|
+
[](https://kata.sh/)
|
|
24
|
+
|
|
25
|
+
<br>
|
|
26
|
+
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Install as Claude Code plugin
|
|
32
|
+
/plugin marketplace add gannonh/kata-marketplace
|
|
33
|
+
/plugin install kata@gannonh-kata-marketplace
|
|
34
|
+
|
|
35
|
+
# Or install via NPM
|
|
36
|
+
npx @gannonh/kata
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Talk to It Like a Person
|
|
42
|
+
|
|
43
|
+
Drive your entire workflow with **natural language**.
|
|
44
|
+
|
|
45
|
+
Say what you want:
|
|
46
|
+
|
|
47
|
+
| You say... | Kata does... |
|
|
48
|
+
| ------------------------ | -------------------------------------- |
|
|
49
|
+
| "Start a new project" | Launches full project initialization |
|
|
50
|
+
| "What's the status?" | Shows progress, next steps, blockers |
|
|
51
|
+
| "Plan phase 2" | Researches and creates execution plans |
|
|
52
|
+
| "Execute the phase" | Runs all plans with parallel agents |
|
|
53
|
+
| "I'm done for today" | Creates handoff for session resumption |
|
|
54
|
+
| "Debug this login issue" | Spawns systematic debugging workflow |
|
|
55
|
+
|
|
56
|
+
Every workflow responds to natural language. Slash commands exist for precision when you want them (`/kata:planning-phases 2`), but you never *need* them.
|
|
57
|
+
|
|
58
|
+
**Intent recognition.** Kata parses what you're trying to accomplish and routes to the right workflow (research, planning, execution, verification) automatically.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Who This Is For
|
|
63
|
+
|
|
64
|
+
Teams and individuals that want to describe what they want and have it built correctly.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
<!-- sanitize -->
|
|
69
|
+
## Getting Started
|
|
70
|
+
|
|
71
|
+
### Recommended: Plugin Install
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
/plugin marketplace add gannonh/kata-marketplace
|
|
75
|
+
/plugin install kata@gannonh-kata-marketplace
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Verify with `/kata:providing-help` (plugin) or `/kata-providing-help` (NPX) inside Claude Code.
|
|
79
|
+
|
|
80
|
+
<details>
|
|
81
|
+
<summary><strong>Alternative: NPM Install</strong></summary>
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npx @gannonh/kata
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Use NPM if you prefer global installation or need CI/container support.
|
|
88
|
+
|
|
89
|
+
</details>
|
|
90
|
+
|
|
91
|
+
### Staying Updated
|
|
92
|
+
|
|
93
|
+
Kata evolves fast. Check for updates periodically:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
/kata:showing-whats-new # plugin
|
|
97
|
+
/kata-showing-whats-new # NPX
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Plugin users:**
|
|
101
|
+
```bash
|
|
102
|
+
claude plugin update kata@gannonh-kata-marketplace
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**NPM users:**
|
|
106
|
+
```bash
|
|
107
|
+
npx @gannonh/kata@latest
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
<details>
|
|
111
|
+
<summary><strong>Non-interactive Install (Docker, CI, Scripts)</strong></summary>
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npx @gannonh/kata --global # Install to ~/.claude/
|
|
115
|
+
npx @gannonh/kata --local # Install to ./.claude/
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use `--global` (`-g`) or `--local` (`-l`) to skip the interactive prompt.
|
|
119
|
+
|
|
120
|
+
</details>
|
|
121
|
+
|
|
122
|
+
<details>
|
|
123
|
+
<summary><strong>Development Installation</strong></summary>
|
|
124
|
+
|
|
125
|
+
Clone the repository and run the installer locally:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
git clone https://github.com/gannonh/kata.git
|
|
129
|
+
cd kata
|
|
130
|
+
node bin/install.js --local
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Installs to `./.claude/` for testing modifications before contributing.
|
|
134
|
+
|
|
135
|
+
</details>
|
|
136
|
+
|
|
137
|
+
### Recommended: Skip Permissions Mode
|
|
138
|
+
|
|
139
|
+
Kata is designed for frictionless automation. Run Claude Code with:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
claude --dangerously-skip-permissions
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
> [!TIP]
|
|
146
|
+
> Kata works best this way. Approving `date` and `git commit` 50 times defeats the purpose.
|
|
147
|
+
|
|
148
|
+
<details>
|
|
149
|
+
<summary><strong>Alternative: Granular Permissions</strong></summary>
|
|
150
|
+
|
|
151
|
+
If you prefer not to use that flag, add this to your project's `.claude/settings.json`:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"permissions": {
|
|
156
|
+
"allow": [
|
|
157
|
+
"Bash(date:*)",
|
|
158
|
+
"Bash(echo:*)",
|
|
159
|
+
"Bash(cat:*)",
|
|
160
|
+
"Bash(ls:*)",
|
|
161
|
+
"Bash(mkdir:*)",
|
|
162
|
+
"Bash(wc:*)",
|
|
163
|
+
"Bash(head:*)",
|
|
164
|
+
"Bash(tail:*)",
|
|
165
|
+
"Bash(sort:*)",
|
|
166
|
+
"Bash(grep:*)",
|
|
167
|
+
"Bash(tr:*)",
|
|
168
|
+
"Bash(git add:*)",
|
|
169
|
+
"Bash(git commit:*)",
|
|
170
|
+
"Bash(git status:*)",
|
|
171
|
+
"Bash(git log:*)",
|
|
172
|
+
"Bash(git diff:*)",
|
|
173
|
+
"Bash(git tag:*)"
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
</details>
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## How It Works
|
|
184
|
+
|
|
185
|
+
> **Already have code?** Run `/kata:mapping-codebases` (plugin) or `/kata-mapping-codebases` (NPX) first. It spawns parallel agents to analyze your stack, architecture, conventions, and concerns. Then your next project setup knows your codebase. Questions focus on what you're adding, and planning automatically loads your patterns.
|
|
186
|
+
|
|
187
|
+
### 1. Initialize Project
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
"Start a new project"
|
|
191
|
+
```
|
|
192
|
+
<sub>or `/kata:starting-projects` (plugin) | `/kata-starting-projects` (NPX)</sub>
|
|
193
|
+
|
|
194
|
+
One command, one flow. The system:
|
|
195
|
+
|
|
196
|
+
1. **Questions**: Asks until it understands your idea completely (goals, constraints, tech preferences, edge cases)
|
|
197
|
+
2. **Research**: Spawns parallel agents to investigate the domain (optional but recommended)
|
|
198
|
+
3. **Requirements**: Extracts what's v1, v2, and out of scope
|
|
199
|
+
4. **Roadmap**: Creates phases mapped to requirements
|
|
200
|
+
|
|
201
|
+
You approve the roadmap. Now you're ready to build.
|
|
202
|
+
|
|
203
|
+
**Creates:** `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, `STATE.md`, `.planning/research/`
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
### 2. Discuss Phase
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
"Let's discuss phase 1"
|
|
211
|
+
```
|
|
212
|
+
<sub>or `/kata:discussing-phases 1` (plugin) | `/kata-discussing-phases 1` (NPX)</sub>
|
|
213
|
+
|
|
214
|
+
**This is where you shape the implementation.**
|
|
215
|
+
|
|
216
|
+
Your roadmap has a sentence or two per phase. That's not enough context to build something the way *you* imagine it. This step captures your preferences before anything gets researched or planned.
|
|
217
|
+
|
|
218
|
+
The system analyzes the phase and identifies gray areas based on what's being built:
|
|
219
|
+
|
|
220
|
+
- **Visual features** → Layout, density, interactions, empty states
|
|
221
|
+
- **APIs/CLIs** → Response format, flags, error handling, verbosity
|
|
222
|
+
- **Content systems** → Structure, tone, depth, flow
|
|
223
|
+
- **Organization tasks** → Grouping criteria, naming, duplicates, exceptions
|
|
224
|
+
|
|
225
|
+
For each area you select, it asks until you're satisfied. The output (`CONTEXT.md`) feeds directly into the next two steps:
|
|
226
|
+
|
|
227
|
+
1. **Researcher reads it**: Knows what patterns to investigate ("user wants card layout" → research card component libraries)
|
|
228
|
+
2. **Planner reads it**: Knows what decisions are locked ("infinite scroll decided" → plan includes scroll handling)
|
|
229
|
+
|
|
230
|
+
Depth here correlates with alignment to your intent. Skip it for reasonable defaults.
|
|
231
|
+
|
|
232
|
+
**Creates:** `{phase}-CONTEXT.md`
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### 3. Plan Phase
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
"Plan phase 1"
|
|
240
|
+
```
|
|
241
|
+
<sub>or `/kata:planning-phases 1` (plugin) | `/kata-planning-phases 1` (NPX)</sub>
|
|
242
|
+
|
|
243
|
+
The system:
|
|
244
|
+
|
|
245
|
+
1. **Researches**: Investigates how to implement this phase, guided by your CONTEXT.md decisions
|
|
246
|
+
2. **Plans**: Creates 2-3 atomic task plans with XML structure
|
|
247
|
+
3. **Verifies**: Checks plans against requirements, loops until they pass
|
|
248
|
+
|
|
249
|
+
Each plan fits in a fresh context window.
|
|
250
|
+
|
|
251
|
+
**Creates:** `{phase}-RESEARCH.md`, `{phase}-{N}-PLAN.md`
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
### 4. Execute Phase
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
"Execute phase 1"
|
|
259
|
+
```
|
|
260
|
+
<sub>or `/kata:executing-phases 1` (plugin) | `/kata-executing-phases 1` (NPX)</sub>
|
|
261
|
+
|
|
262
|
+
The system:
|
|
263
|
+
|
|
264
|
+
1. **Runs plans in waves**: Parallel where possible, sequential when dependent
|
|
265
|
+
2. **Fresh context per plan**: 200k tokens for implementation, zero accumulated garbage
|
|
266
|
+
3. **Commits per task**: Every task gets its own atomic commit
|
|
267
|
+
4. **Verifies against goals**: Checks the codebase delivers what the phase promised
|
|
268
|
+
|
|
269
|
+
Walk away, come back to completed work with clean git history.
|
|
270
|
+
|
|
271
|
+
**Creates:** `{phase}-{N}-SUMMARY.md`, `{phase}-VERIFICATION.md`
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### 5. Verify Work
|
|
276
|
+
|
|
277
|
+
```
|
|
278
|
+
"Verify phase 1"
|
|
279
|
+
```
|
|
280
|
+
<sub>or `/kata:verifying-phases 1` (plugin) | `/kata-verifying-phases 1` (NPX)</sub>
|
|
281
|
+
|
|
282
|
+
**This is where you confirm it actually works.**
|
|
283
|
+
|
|
284
|
+
Automated verification checks that code exists and tests pass. But does the feature *work* the way you expected? This is your chance to use it.
|
|
285
|
+
|
|
286
|
+
The system:
|
|
287
|
+
|
|
288
|
+
1. **Extracts testable deliverables**: What you should be able to do now
|
|
289
|
+
2. **Walks you through one at a time**: "Can you log in with email?" Yes/no, or describe what's wrong
|
|
290
|
+
3. **Diagnoses failures automatically**: Spawns debug agents to find root causes
|
|
291
|
+
4. **Creates verified fix plans**: Ready for immediate re-execution
|
|
292
|
+
|
|
293
|
+
If everything passes, you move on. If something's broken, run `/kata:executing-phases` again with the fix plans it created.
|
|
294
|
+
|
|
295
|
+
**Creates:** `{phase}-UAT.md`, fix plans if issues found
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
### 6. Repeat → Complete → Next Milestone
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
"Discuss phase 2"
|
|
303
|
+
"Plan phase 2"
|
|
304
|
+
"Execute phase 2"
|
|
305
|
+
"Verify phase 2"
|
|
306
|
+
...
|
|
307
|
+
"Complete the milestone"
|
|
308
|
+
"Start the next milestone"
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Loop **discuss → plan → execute → verify** until milestone complete.
|
|
312
|
+
|
|
313
|
+
Each phase gets your input (discuss), proper research (plan), clean execution (execute), and human verification (verify). Context stays fresh. Quality stays high.
|
|
314
|
+
|
|
315
|
+
When all phases are done, "complete the milestone" archives the milestone and tags the release.
|
|
316
|
+
|
|
317
|
+
Then "start the next milestone" kicks off the next version. Same flow as project initialization for your existing codebase. You describe what you want to build next, the system researches the domain, you scope requirements, and it creates a fresh roadmap. Each milestone is a clean cycle: define → build → ship.
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
### Quick Mode
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
"Quick task: add dark mode toggle"
|
|
325
|
+
```
|
|
326
|
+
<sub>or `/kata:executing-quick-tasks` (plugin) | `/kata-executing-quick-tasks` (NPX)</sub>
|
|
327
|
+
|
|
328
|
+
**For ad-hoc tasks that don't need full planning.**
|
|
329
|
+
|
|
330
|
+
Quick mode gives you Kata guarantees (atomic commits, state tracking) with a faster path:
|
|
331
|
+
|
|
332
|
+
- **Same agents**: Planner + executor, same quality
|
|
333
|
+
- **Skips optional steps**: No research, no plan checker, no verifier
|
|
334
|
+
- **Separate tracking**: Lives in `.planning/quick/`
|
|
335
|
+
|
|
336
|
+
Use for: bug fixes, small features, config changes, one-off tasks.
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
"Quick task: add dark mode toggle to settings"
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**Creates:** `.planning/quick/001-add-dark-mode-toggle/PLAN.md`, `SUMMARY.md`
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Why It Works
|
|
347
|
+
|
|
348
|
+
### Context Engineering
|
|
349
|
+
|
|
350
|
+
Claude Code requires the right context to perform well. Kata manages context for you:
|
|
351
|
+
|
|
352
|
+
| File | What it does |
|
|
353
|
+
| ----------------- | ------------------------------------------------------------- |
|
|
354
|
+
| `PROJECT.md` | Project vision, always loaded |
|
|
355
|
+
| `research/` | Ecosystem knowledge (stack, features, architecture, pitfalls) |
|
|
356
|
+
| `REQUIREMENTS.md` | Scoped v1/v2 requirements with phase traceability |
|
|
357
|
+
| `ROADMAP.md` | Where you're going, what's done |
|
|
358
|
+
| `STATE.md` | Decisions, blockers, position. Memory across sessions |
|
|
359
|
+
| `PLAN.md` | Atomic task with XML structure, verification steps |
|
|
360
|
+
| `SUMMARY.md` | What happened, what changed, committed to history |
|
|
361
|
+
| `todos/` | Captured ideas and tasks for later work |
|
|
362
|
+
|
|
363
|
+
Size limits based on where Claude's quality degrades.
|
|
364
|
+
|
|
365
|
+
### XML Prompt Formatting
|
|
366
|
+
|
|
367
|
+
Every plan is structured XML optimized for Claude:
|
|
368
|
+
|
|
369
|
+
```xml
|
|
370
|
+
<task type="auto">
|
|
371
|
+
<name>Create login endpoint</name>
|
|
372
|
+
<files>src/app/api/auth/login/route.ts</files>
|
|
373
|
+
<action>
|
|
374
|
+
Use jose for JWT (not jsonwebtoken - CommonJS issues).
|
|
375
|
+
Validate credentials against users table.
|
|
376
|
+
Return httpOnly cookie on success.
|
|
377
|
+
</action>
|
|
378
|
+
<verify>curl -X POST localhost:3000/api/auth/login returns 200 + Set-Cookie</verify>
|
|
379
|
+
<done>Valid credentials return cookie, invalid return 401</done>
|
|
380
|
+
</task>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Precise instructions with verification built in.
|
|
384
|
+
|
|
385
|
+
### Multi-Agent Orchestration
|
|
386
|
+
|
|
387
|
+
Every stage uses the same pattern: a thin orchestrator spawns specialized agents, collects results, and routes to the next step.
|
|
388
|
+
|
|
389
|
+
| Stage | Orchestrator does | Agents do |
|
|
390
|
+
| ------------ | ---------------------------------- | -------------------------------------------------------------------------- |
|
|
391
|
+
| Research | Coordinates, presents findings | 4 parallel researchers investigate stack, features, architecture, pitfalls |
|
|
392
|
+
| Planning | Validates, manages iteration | Planner creates plans, checker verifies, loop until pass |
|
|
393
|
+
| Execution | Groups into waves, tracks progress | Executors implement in parallel, each with fresh 200k context |
|
|
394
|
+
| Verification | Presents results, routes next | Verifier checks codebase against goals, debuggers diagnose failures |
|
|
395
|
+
|
|
396
|
+
The orchestrator never does heavy lifting. It spawns agents, waits, integrates results.
|
|
397
|
+
|
|
398
|
+
**The result:** You can run an entire phase (research, planning, execution, verification) and your main context window stays at 30-40%. The work happens in fresh subagent contexts.
|
|
399
|
+
|
|
400
|
+
### Atomic Git Commits
|
|
401
|
+
|
|
402
|
+
Each task gets its own commit immediately after completion:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
abc123f docs(08-02): complete user registration plan
|
|
406
|
+
def456g feat(08-02): add email confirmation flow
|
|
407
|
+
hij789k feat(08-02): implement password hashing
|
|
408
|
+
lmn012o feat(08-02): create registration endpoint
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
> [!NOTE]
|
|
412
|
+
> **Benefits:** Git bisect finds exact failing task. Each task independently revertable. Clear history for Claude in future sessions. Better observability in AI-automated workflow.
|
|
413
|
+
|
|
414
|
+
Every commit is traceable and revertable.
|
|
415
|
+
|
|
416
|
+
### Modular by Design
|
|
417
|
+
|
|
418
|
+
- Add phases to current milestone
|
|
419
|
+
- Insert urgent work between phases
|
|
420
|
+
- Complete milestones and start fresh
|
|
421
|
+
- Adjust plans without rebuilding everything
|
|
422
|
+
|
|
423
|
+
The system adapts to changing requirements.
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## Skills
|
|
428
|
+
|
|
429
|
+
> **Remember:** All skills respond to natural language. "What's my progress?" works the same as `/kata:tracking-progress` (plugin) or `/kata-tracking-progress` (NPX).
|
|
430
|
+
|
|
431
|
+
Skills are invoked via slash commands. The syntax differs between plugin and NPX installations:
|
|
432
|
+
|
|
433
|
+
| Installation | Syntax | Example |
|
|
434
|
+
| ------------ | ------ | ------- |
|
|
435
|
+
| Plugin | `/kata:skill-name` | `/kata:planning-phases 1` |
|
|
436
|
+
| NPX | `/kata-skill-name` | `/kata-planning-phases 1` |
|
|
437
|
+
|
|
438
|
+
### Core Workflow
|
|
439
|
+
|
|
440
|
+
| Skill | What it does |
|
|
441
|
+
| ----- | ------------ |
|
|
442
|
+
| `starting-projects` | Full initialization: questions → research → requirements → roadmap |
|
|
443
|
+
| `discussing-phases [N]` | Capture implementation decisions before planning |
|
|
444
|
+
| `planning-phases [N]` | Research + plan + verify for a phase |
|
|
445
|
+
| `executing-phases <N>` | Execute all plans in parallel waves, verify when complete |
|
|
446
|
+
| `verifying-phases [N]` | Manual user acceptance testing |
|
|
447
|
+
| `auditing-milestones` | Verify milestone achieved its definition of done |
|
|
448
|
+
| `completing-milestones` | Archive milestone, tag release |
|
|
449
|
+
| `starting-milestones [name]` | Start next version: questions → research → requirements → roadmap |
|
|
450
|
+
|
|
451
|
+
### Navigation
|
|
452
|
+
|
|
453
|
+
| Skill | What it does |
|
|
454
|
+
| ----- | ------------ |
|
|
455
|
+
| `tracking-progress` | Where am I? What's next? |
|
|
456
|
+
| `providing-help` | Show all skills and usage guide |
|
|
457
|
+
| `showing-whats-new` | See what changed since your installed version |
|
|
458
|
+
| `updating` | Update Kata with changelog preview (NPX only) |
|
|
459
|
+
|
|
460
|
+
### Brownfield
|
|
461
|
+
|
|
462
|
+
| Skill | What it does |
|
|
463
|
+
| ----- | ------------ |
|
|
464
|
+
| `mapping-codebases` | Analyze existing codebase before project setup |
|
|
465
|
+
|
|
466
|
+
### Phase Management
|
|
467
|
+
|
|
468
|
+
| Skill | What it does |
|
|
469
|
+
| ----- | ------------ |
|
|
470
|
+
| `adding-phases` | Append phase to roadmap |
|
|
471
|
+
| `inserting-phases [N]` | Insert urgent work between phases |
|
|
472
|
+
| `removing-phases [N]` | Remove future phase, renumber |
|
|
473
|
+
| `listing-phase-assumptions [N]` | See Claude's intended approach before planning |
|
|
474
|
+
| `planning-milestone-gaps` | Create phases to close gaps from audit |
|
|
475
|
+
|
|
476
|
+
### Session
|
|
477
|
+
|
|
478
|
+
| Skill | What it does |
|
|
479
|
+
| ----- | ------------ |
|
|
480
|
+
| `pausing-work` | Create handoff when stopping mid-phase |
|
|
481
|
+
| `resuming-work` | Restore from last session |
|
|
482
|
+
|
|
483
|
+
### Utilities
|
|
484
|
+
|
|
485
|
+
| Skill | What it does |
|
|
486
|
+
| ----- | ------------ |
|
|
487
|
+
| `configuring-settings` | Configure model profile and workflow agents |
|
|
488
|
+
| `setting-profiles <profile>` | Switch model profile (quality/balanced/budget) |
|
|
489
|
+
| `adding-todos [desc]` | Capture idea for later |
|
|
490
|
+
| `checking-todos` | List pending todos |
|
|
491
|
+
| `debugging [desc]` | Systematic debugging with persistent state |
|
|
492
|
+
| `executing-quick-tasks` | Execute ad-hoc task with Kata guarantees |
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
## Configuration
|
|
497
|
+
|
|
498
|
+
Kata stores project settings in `.planning/config.json`. Configure during `/kata:starting-projects` or update later with `/kata:configuring-settings`.
|
|
499
|
+
|
|
500
|
+
### Core Settings
|
|
501
|
+
|
|
502
|
+
| Setting | Options | Default | What it controls |
|
|
503
|
+
| ------- | ------------------------------------ | ------------- | -------------------------------------- |
|
|
504
|
+
| `mode` | `yolo`, `interactive` | `interactive` | Auto-approve vs confirm at each step |
|
|
505
|
+
| `depth` | `quick`, `standard`, `comprehensive` | `standard` | Planning thoroughness (phases × plans) |
|
|
506
|
+
|
|
507
|
+
### Model Profiles
|
|
508
|
+
|
|
509
|
+
Control which Claude model each agent uses. Balance quality vs token spend.
|
|
510
|
+
|
|
511
|
+
| Profile | Planning | Execution | Verification |
|
|
512
|
+
| -------------------- | -------- | --------- | ------------ |
|
|
513
|
+
| `quality` | Opus | Opus | Sonnet |
|
|
514
|
+
| `balanced` (default) | Opus | Sonnet | Sonnet |
|
|
515
|
+
| `budget` | Sonnet | Sonnet | Haiku |
|
|
516
|
+
|
|
517
|
+
Switch profiles:
|
|
518
|
+
```
|
|
519
|
+
/kata:setting-profiles budget
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
Or configure via `/kata:configuring-settings`.
|
|
523
|
+
|
|
524
|
+
### Workflow Agents
|
|
525
|
+
|
|
526
|
+
These spawn additional agents during planning/execution. They improve quality but add tokens and time.
|
|
527
|
+
|
|
528
|
+
| Setting | Default | What it does |
|
|
529
|
+
| --------------------- | ------- | --------------------------------------------------- |
|
|
530
|
+
| `workflow.research` | `true` | Researches domain before planning each phase |
|
|
531
|
+
| `workflow.plan_check` | `true` | Verifies plans achieve phase goals before execution |
|
|
532
|
+
| `workflow.verifier` | `true` | Confirms must-haves were delivered after execution |
|
|
533
|
+
|
|
534
|
+
Use `/kata:configuring-settings` to toggle these, or override per-invocation:
|
|
535
|
+
- `planning-phases --skip-research`
|
|
536
|
+
- `planning-phases --skip-verify`
|
|
537
|
+
|
|
538
|
+
### Execution
|
|
539
|
+
|
|
540
|
+
| Setting | Default | What it controls |
|
|
541
|
+
| ------------------------- | ------- | ------------------------------------ |
|
|
542
|
+
| `parallelization.enabled` | `true` | Run independent plans simultaneously |
|
|
543
|
+
| `planning.commit_docs` | `true` | Track `.planning/` in git |
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
## Troubleshooting
|
|
548
|
+
|
|
549
|
+
**Skills not found after install?**
|
|
550
|
+
- Restart Claude Code to reload skills
|
|
551
|
+
- **Plugin:** Verify skills exist in `./.claude/skills/` (prefixes stripped)
|
|
552
|
+
- **NPX:** Verify skills exist in `~/.claude/skills/kata-*` (global) or `./.claude/skills/kata-*` (local)
|
|
553
|
+
|
|
554
|
+
**Skills not working as expected?**
|
|
555
|
+
- Run `/kata:providing-help` (plugin) or `/kata-providing-help` (NPX) to verify installation
|
|
556
|
+
- Re-run `npx @gannonh/kata` to reinstall
|
|
557
|
+
|
|
558
|
+
**Updating to the latest version?**
|
|
559
|
+
```bash
|
|
560
|
+
npx @gannonh/kata@latest
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
**Using Docker or containerized environments?**
|
|
564
|
+
|
|
565
|
+
If file reads fail with tilde paths (`~/.claude/...`), set `CLAUDE_CONFIG_DIR` before installing:
|
|
566
|
+
```bash
|
|
567
|
+
CLAUDE_CONFIG_DIR=/home/youruser/.claude npx @gannonh/kata --global
|
|
568
|
+
```
|
|
569
|
+
This ensures absolute paths are used instead of `~` which may not expand correctly in containers.
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
573
|
+
## Background
|
|
574
|
+
|
|
575
|
+
This project began as a fork of the [GSD system](https://github.com/glittercowboy/get-shit-done), and then quickly became a hard fork. Why hard fork and not contribute to the original project? The reasons are two fold, well three fold, or two and a half-fold.
|
|
576
|
+
|
|
577
|
+
- **Team-oriented by design.** GSD is optimized for solo devs, viewing "enterprise" features as anti-patterns. I respect that position, but my projects are multi-player. At a minimum, I need:
|
|
578
|
+
- **GitHub integration**: PRs, issues, code review workflows. Planning that connects to where teams actually collaborate.
|
|
579
|
+
- **IDE agnostic**: Kata should work with the tools teams already use.
|
|
580
|
+
|
|
581
|
+
- **Skills as the foundation.** GSD is built on `/commands`, which are Claude Code-specific. Kata standardizes on **skills**, an emerging open standard supported across major agentic frameworks.
|
|
582
|
+
- Portable across tools.
|
|
583
|
+
- Progressive disclosure keeps prompts lean.
|
|
584
|
+
- Natural language instantiation (useful for voice input).
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
## License
|
|
589
|
+
|
|
590
|
+
MIT License. See [LICENSE](LICENSE) for details.
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
<div align="center">
|
|
595
|
+
|
|
596
|
+
**Kata adds structure to Claude Code.**
|
|
597
|
+
|
|
598
|
+
*Tell it what you want.*
|
|
599
|
+
|
|
600
|
+
</div>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Check for Kata updates in background, write result to cache
|
|
3
|
+
// Called by SessionStart hook - runs once per session
|
|
4
|
+
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import os from 'os';
|
|
8
|
+
import { spawn } from 'child_process';
|
|
9
|
+
|
|
10
|
+
const homeDir = os.homedir();
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
|
|
13
|
+
// Detect local vs global installation by checking VERSION file
|
|
14
|
+
// This single check tells us both: existence = local install, contents = version
|
|
15
|
+
const localVersionFile = path.join(cwd, '.claude', 'kata', 'VERSION');
|
|
16
|
+
const globalVersionFile = path.join(homeDir, '.claude', 'kata', 'VERSION');
|
|
17
|
+
const isLocalInstall = fs.existsSync(localVersionFile);
|
|
18
|
+
|
|
19
|
+
// Use paths based on installation type - cache location matches install context
|
|
20
|
+
const versionFile = isLocalInstall ? localVersionFile : globalVersionFile;
|
|
21
|
+
const cacheDir = isLocalInstall
|
|
22
|
+
? path.join(cwd, '.claude', 'kata', 'cache')
|
|
23
|
+
: path.join(homeDir, '.claude', 'kata', 'cache');
|
|
24
|
+
const cacheFile = path.join(cacheDir, 'update-check.json');
|
|
25
|
+
|
|
26
|
+
// Store cwd in cache so statusline can detect stale cache
|
|
27
|
+
const checkedCwd = cwd;
|
|
28
|
+
|
|
29
|
+
// Ensure cache directory exists
|
|
30
|
+
if (!fs.existsSync(cacheDir)) {
|
|
31
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Run check in background (spawn detached process)
|
|
35
|
+
// Note: The spawned process uses --input-type=module for ESM compatibility
|
|
36
|
+
const child = spawn(process.execPath, ['--input-type=module', '-e', `
|
|
37
|
+
import fs from 'fs';
|
|
38
|
+
import { execSync } from 'child_process';
|
|
39
|
+
|
|
40
|
+
const cacheFile = ${JSON.stringify(cacheFile)};
|
|
41
|
+
const versionFile = ${JSON.stringify(versionFile)};
|
|
42
|
+
const checkedCwd = ${JSON.stringify(checkedCwd)};
|
|
43
|
+
const isLocalInstall = ${JSON.stringify(isLocalInstall)};
|
|
44
|
+
|
|
45
|
+
let installed = '0.0.0';
|
|
46
|
+
try {
|
|
47
|
+
installed = fs.readFileSync(versionFile, 'utf8').trim();
|
|
48
|
+
} catch (e) {}
|
|
49
|
+
|
|
50
|
+
let latest = null;
|
|
51
|
+
try {
|
|
52
|
+
latest = execSync('npm view @gannonh/kata version', { encoding: 'utf8', timeout: 10000 }).trim();
|
|
53
|
+
} catch (e) {}
|
|
54
|
+
|
|
55
|
+
const result = {
|
|
56
|
+
update_available: latest && installed !== latest,
|
|
57
|
+
installed,
|
|
58
|
+
latest: latest || 'unknown',
|
|
59
|
+
checked: Math.floor(Date.now() / 1000),
|
|
60
|
+
cwd: checkedCwd,
|
|
61
|
+
isLocalInstall: isLocalInstall
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
fs.writeFileSync(cacheFile, JSON.stringify(result));
|
|
65
|
+
`], {
|
|
66
|
+
detached: true,
|
|
67
|
+
stdio: 'ignore'
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
child.unref();
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Claude Code Statusline - Kata Edition
|
|
3
|
+
// Shows: model | current task | directory | context usage
|
|
4
|
+
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import os from 'os';
|
|
8
|
+
|
|
9
|
+
// Read JSON from stdin
|
|
10
|
+
let input = '';
|
|
11
|
+
process.stdin.setEncoding('utf8');
|
|
12
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
13
|
+
process.stdin.on('end', () => {
|
|
14
|
+
try {
|
|
15
|
+
const data = JSON.parse(input);
|
|
16
|
+
const model = data.model?.display_name || 'Claude';
|
|
17
|
+
const dir = data.workspace?.current_dir || process.cwd();
|
|
18
|
+
const session = data.session_id || '';
|
|
19
|
+
const remaining = data.context_window?.remaining_percentage;
|
|
20
|
+
|
|
21
|
+
// Context window display (shows USED percentage)
|
|
22
|
+
let ctx = '';
|
|
23
|
+
if (remaining != null) {
|
|
24
|
+
const rem = Math.round(remaining);
|
|
25
|
+
const used = 100 - rem;
|
|
26
|
+
|
|
27
|
+
// Build progress bar (10 segments)
|
|
28
|
+
const filled = Math.floor(used / 10);
|
|
29
|
+
const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(10 - filled);
|
|
30
|
+
|
|
31
|
+
// Color based on usage
|
|
32
|
+
if (used < 50) {
|
|
33
|
+
ctx = ` \x1b[32m${bar} ${used}%\x1b[0m`;
|
|
34
|
+
} else if (used < 65) {
|
|
35
|
+
ctx = ` \x1b[33m${bar} ${used}%\x1b[0m`;
|
|
36
|
+
} else if (used < 80) {
|
|
37
|
+
ctx = ` \x1b[38;5;208m${bar} ${used}%\x1b[0m`;
|
|
38
|
+
} else {
|
|
39
|
+
ctx = ` \x1b[5;31m\u{1F480} ${bar} ${used}%\x1b[0m`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Current task from todos
|
|
44
|
+
let task = '';
|
|
45
|
+
const homeDir = os.homedir();
|
|
46
|
+
const todosDir = path.join(homeDir, '.claude', 'todos');
|
|
47
|
+
if (session && fs.existsSync(todosDir)) {
|
|
48
|
+
const files = fs.readdirSync(todosDir)
|
|
49
|
+
.filter(f => f.startsWith(session) && f.includes('-agent-') && f.endsWith('.json'))
|
|
50
|
+
.map(f => ({ name: f, mtime: fs.statSync(path.join(todosDir, f)).mtime }))
|
|
51
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
52
|
+
|
|
53
|
+
if (files.length > 0) {
|
|
54
|
+
try {
|
|
55
|
+
const todos = JSON.parse(fs.readFileSync(path.join(todosDir, files[0].name), 'utf8'));
|
|
56
|
+
const inProgress = todos.find(t => t.status === 'in_progress');
|
|
57
|
+
if (inProgress) task = inProgress.activeForm || '';
|
|
58
|
+
} catch (e) {}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Kata update available?
|
|
63
|
+
let kataUpdate = '';
|
|
64
|
+
const currentDir = dir;
|
|
65
|
+
|
|
66
|
+
// Detect local vs global installation by checking VERSION file
|
|
67
|
+
const localVersionFile = path.join(currentDir, '.claude', 'kata', 'VERSION');
|
|
68
|
+
const currentIsLocalInstall = fs.existsSync(localVersionFile);
|
|
69
|
+
|
|
70
|
+
// Read cache from location matching current context
|
|
71
|
+
const cacheFile = currentIsLocalInstall
|
|
72
|
+
? path.join(currentDir, '.claude', 'kata', 'cache', 'update-check.json')
|
|
73
|
+
: path.join(homeDir, '.claude', 'kata', 'cache', 'update-check.json');
|
|
74
|
+
|
|
75
|
+
if (fs.existsSync(cacheFile)) {
|
|
76
|
+
try {
|
|
77
|
+
const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
|
|
78
|
+
|
|
79
|
+
// Validate cache matches current context (sanity check)
|
|
80
|
+
const cacheIsRelevant = currentIsLocalInstall
|
|
81
|
+
? (cache.isLocalInstall && cache.cwd === currentDir)
|
|
82
|
+
: !cache.isLocalInstall;
|
|
83
|
+
|
|
84
|
+
if (cache.update_available && cacheIsRelevant) {
|
|
85
|
+
kataUpdate = '\x1b[33m\u2B06 /kata:update\x1b[0m \u2502 ';
|
|
86
|
+
}
|
|
87
|
+
} catch (e) {}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Output
|
|
91
|
+
const dirname = path.basename(dir);
|
|
92
|
+
if (task) {
|
|
93
|
+
process.stdout.write(`${kataUpdate}\x1b[2m${model}\x1b[0m \u2502 \x1b[1m${task}\x1b[0m \u2502 \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
94
|
+
} else {
|
|
95
|
+
process.stdout.write(`${kataUpdate}\x1b[2m${model}\x1b[0m \u2502 \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
96
|
+
}
|
|
97
|
+
} catch (e) {
|
|
98
|
+
// Silent fail - don't break statusline on parse errors
|
|
99
|
+
}
|
|
100
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Claude Code Statusline - Kata Plugin Edition
|
|
3
|
+
// Shows: model | current task | directory | context usage
|
|
4
|
+
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import os from 'os';
|
|
8
|
+
|
|
9
|
+
// Read JSON from stdin
|
|
10
|
+
let input = '';
|
|
11
|
+
process.stdin.setEncoding('utf8');
|
|
12
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
13
|
+
process.stdin.on('end', () => {
|
|
14
|
+
try {
|
|
15
|
+
const data = JSON.parse(input);
|
|
16
|
+
const model = data.model?.display_name || 'Claude';
|
|
17
|
+
const dir = data.workspace?.current_dir || process.cwd();
|
|
18
|
+
const session = data.session_id || '';
|
|
19
|
+
const remaining = data.context_window?.remaining_percentage;
|
|
20
|
+
|
|
21
|
+
// Context window display (shows USED percentage)
|
|
22
|
+
let ctx = '';
|
|
23
|
+
if (remaining != null) {
|
|
24
|
+
const rem = Math.round(remaining);
|
|
25
|
+
const used = 100 - rem;
|
|
26
|
+
|
|
27
|
+
// Build progress bar (10 segments)
|
|
28
|
+
const filled = Math.floor(used / 10);
|
|
29
|
+
const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(10 - filled);
|
|
30
|
+
|
|
31
|
+
// Color based on usage
|
|
32
|
+
if (used < 50) {
|
|
33
|
+
ctx = ` \x1b[32m${bar} ${used}%\x1b[0m`;
|
|
34
|
+
} else if (used < 65) {
|
|
35
|
+
ctx = ` \x1b[33m${bar} ${used}%\x1b[0m`;
|
|
36
|
+
} else if (used < 80) {
|
|
37
|
+
ctx = ` \x1b[38;5;208m${bar} ${used}%\x1b[0m`;
|
|
38
|
+
} else {
|
|
39
|
+
ctx = ` \x1b[5;31m\u{1F480} ${bar} ${used}%\x1b[0m`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Current task from todos
|
|
44
|
+
let task = '';
|
|
45
|
+
const homeDir = os.homedir();
|
|
46
|
+
const todosDir = path.join(homeDir, '.claude', 'todos');
|
|
47
|
+
if (session && fs.existsSync(todosDir)) {
|
|
48
|
+
const files = fs.readdirSync(todosDir)
|
|
49
|
+
.filter(f => f.startsWith(session) && f.includes('-agent-') && f.endsWith('.json'))
|
|
50
|
+
.map(f => ({ name: f, mtime: fs.statSync(path.join(todosDir, f)).mtime }))
|
|
51
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
52
|
+
|
|
53
|
+
if (files.length > 0) {
|
|
54
|
+
try {
|
|
55
|
+
const todos = JSON.parse(fs.readFileSync(path.join(todosDir, files[0].name), 'utf8'));
|
|
56
|
+
const inProgress = todos.find(t => t.status === 'in_progress');
|
|
57
|
+
if (inProgress) task = inProgress.activeForm || '';
|
|
58
|
+
} catch (e) {}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Kata update available?
|
|
63
|
+
let kataUpdate = '';
|
|
64
|
+
const currentDir = dir;
|
|
65
|
+
|
|
66
|
+
// For plugin installs, check the project-local cache
|
|
67
|
+
const cacheFile = path.join(currentDir, '.claude', 'kata', 'cache', 'update-check.json');
|
|
68
|
+
|
|
69
|
+
if (fs.existsSync(cacheFile)) {
|
|
70
|
+
try {
|
|
71
|
+
const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
|
|
72
|
+
|
|
73
|
+
if (cache.update_available) {
|
|
74
|
+
// Plugin update message with version and both update methods
|
|
75
|
+
const latest = cache.latest || 'new';
|
|
76
|
+
kataUpdate = `\x1b[33m⬆ v${latest}: /plugin (CC) or claude plugin update kata@kata-marketplace (term)\x1b[0m \u2502 `;
|
|
77
|
+
}
|
|
78
|
+
} catch (e) {}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Output
|
|
82
|
+
const dirname = path.basename(dir);
|
|
83
|
+
if (task) {
|
|
84
|
+
process.stdout.write(`${kataUpdate}\x1b[2m${model}\x1b[0m \u2502 \x1b[1m${task}\x1b[0m \u2502 \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
85
|
+
} else {
|
|
86
|
+
process.stdout.write(`${kataUpdate}\x1b[2m${model}\x1b[0m \u2502 \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
// Silent fail - don't break statusline on parse errors
|
|
90
|
+
}
|
|
91
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Kata Statusline Setup Hook
|
|
3
|
+
// Runs on SessionStart to set up the statusline if configured
|
|
4
|
+
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
// Read JSON from stdin (SessionStart hook input)
|
|
9
|
+
let input = '';
|
|
10
|
+
process.stdin.setEncoding('utf8');
|
|
11
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
12
|
+
process.stdin.on('end', () => {
|
|
13
|
+
try {
|
|
14
|
+
const data = JSON.parse(input);
|
|
15
|
+
const cwd = data.cwd || process.cwd();
|
|
16
|
+
const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
|
|
17
|
+
|
|
18
|
+
// Check if statusline is enabled in config
|
|
19
|
+
const configPath = path.join(cwd, '.planning', 'config.json');
|
|
20
|
+
if (!fs.existsSync(configPath)) {
|
|
21
|
+
process.exit(0); // No config, nothing to do
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
25
|
+
if (!config.display?.statusline) {
|
|
26
|
+
process.exit(0); // Statusline not enabled
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check if statusline hook already exists
|
|
30
|
+
const projectHookPath = path.join(cwd, '.claude', 'hooks', 'kata-statusline.js');
|
|
31
|
+
if (fs.existsSync(projectHookPath)) {
|
|
32
|
+
process.exit(0); // Already set up
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Find the source statusline hook
|
|
36
|
+
let sourceHook = null;
|
|
37
|
+
|
|
38
|
+
// Try plugin root first
|
|
39
|
+
if (pluginRoot) {
|
|
40
|
+
const pluginHook = path.join(pluginRoot, 'hooks', 'kata-plugin-statusline.js');
|
|
41
|
+
if (fs.existsSync(pluginHook)) {
|
|
42
|
+
sourceHook = pluginHook;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Try NPM locations
|
|
47
|
+
if (!sourceHook) {
|
|
48
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE;
|
|
49
|
+
const npmGlobal = path.join(homeDir, '.claude', 'kata', 'hooks', 'kata-npm-statusline.js');
|
|
50
|
+
if (fs.existsSync(npmGlobal)) {
|
|
51
|
+
sourceHook = npmGlobal;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!sourceHook) {
|
|
56
|
+
process.exit(0); // No source hook found
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Create .claude/hooks directory
|
|
60
|
+
const hooksDir = path.join(cwd, '.claude', 'hooks');
|
|
61
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
62
|
+
|
|
63
|
+
// Copy the hook
|
|
64
|
+
fs.copyFileSync(sourceHook, projectHookPath);
|
|
65
|
+
|
|
66
|
+
// Set up settings.json if needed
|
|
67
|
+
const settingsPath = path.join(cwd, '.claude', 'settings.json');
|
|
68
|
+
let settings = {};
|
|
69
|
+
if (fs.existsSync(settingsPath)) {
|
|
70
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!settings.statusLine) {
|
|
74
|
+
settings.statusLine = {
|
|
75
|
+
type: 'command',
|
|
76
|
+
command: 'node "$CLAUDE_PROJECT_DIR/.claude/hooks/kata-statusline.js"'
|
|
77
|
+
};
|
|
78
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log('✓ Kata statusline configured');
|
|
82
|
+
} catch (e) {
|
|
83
|
+
// Silent fail - don't break session start
|
|
84
|
+
}
|
|
85
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Claude Code Statusline - Kata Edition
|
|
3
|
+
// Shows: model | current task | directory | context usage
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
|
|
9
|
+
// Read JSON from stdin
|
|
10
|
+
let input = '';
|
|
11
|
+
process.stdin.setEncoding('utf8');
|
|
12
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
13
|
+
process.stdin.on('end', () => {
|
|
14
|
+
try {
|
|
15
|
+
const data = JSON.parse(input);
|
|
16
|
+
const model = data.model?.display_name || 'Claude';
|
|
17
|
+
const dir = data.workspace?.current_dir || process.cwd();
|
|
18
|
+
const session = data.session_id || '';
|
|
19
|
+
const remaining = data.context_window?.remaining_percentage;
|
|
20
|
+
|
|
21
|
+
// Context window display (shows USED percentage)
|
|
22
|
+
let ctx = '';
|
|
23
|
+
if (remaining != null) {
|
|
24
|
+
const rem = Math.round(remaining);
|
|
25
|
+
const used = 100 - rem;
|
|
26
|
+
|
|
27
|
+
// Build progress bar (10 segments)
|
|
28
|
+
const filled = Math.floor(used / 10);
|
|
29
|
+
const bar = '█'.repeat(filled) + '░'.repeat(10 - filled);
|
|
30
|
+
|
|
31
|
+
// Color based on usage
|
|
32
|
+
if (used < 50) {
|
|
33
|
+
ctx = ` \x1b[32m${bar} ${used}%\x1b[0m`;
|
|
34
|
+
} else if (used < 65) {
|
|
35
|
+
ctx = ` \x1b[33m${bar} ${used}%\x1b[0m`;
|
|
36
|
+
} else if (used < 80) {
|
|
37
|
+
ctx = ` \x1b[38;5;208m${bar} ${used}%\x1b[0m`;
|
|
38
|
+
} else {
|
|
39
|
+
ctx = ` \x1b[5;31m💀 ${bar} ${used}%\x1b[0m`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Current task from todos
|
|
44
|
+
let task = '';
|
|
45
|
+
const homeDir = os.homedir();
|
|
46
|
+
const todosDir = path.join(homeDir, '.claude', 'todos');
|
|
47
|
+
if (session && fs.existsSync(todosDir)) {
|
|
48
|
+
const files = fs.readdirSync(todosDir)
|
|
49
|
+
.filter(f => f.startsWith(session) && f.includes('-agent-') && f.endsWith('.json'))
|
|
50
|
+
.map(f => ({ name: f, mtime: fs.statSync(path.join(todosDir, f)).mtime }))
|
|
51
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
52
|
+
|
|
53
|
+
if (files.length > 0) {
|
|
54
|
+
try {
|
|
55
|
+
const todos = JSON.parse(fs.readFileSync(path.join(todosDir, files[0].name), 'utf8'));
|
|
56
|
+
const inProgress = todos.find(t => t.status === 'in_progress');
|
|
57
|
+
if (inProgress) task = inProgress.activeForm || '';
|
|
58
|
+
} catch (e) {}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Kata update available?
|
|
63
|
+
let kataUpdate = '';
|
|
64
|
+
const currentDir = dir;
|
|
65
|
+
|
|
66
|
+
// Detect local vs global installation by checking VERSION file
|
|
67
|
+
const localVersionFile = path.join(currentDir, '.claude', 'kata', 'VERSION');
|
|
68
|
+
const currentIsLocalInstall = fs.existsSync(localVersionFile);
|
|
69
|
+
|
|
70
|
+
// Read cache from location matching current context
|
|
71
|
+
const cacheFile = currentIsLocalInstall
|
|
72
|
+
? path.join(currentDir, '.claude', 'kata', 'cache', 'update-check.json')
|
|
73
|
+
: path.join(homeDir, '.claude', 'kata', 'cache', 'update-check.json');
|
|
74
|
+
|
|
75
|
+
if (fs.existsSync(cacheFile)) {
|
|
76
|
+
try {
|
|
77
|
+
const cache = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
|
|
78
|
+
|
|
79
|
+
// Validate cache matches current context (sanity check)
|
|
80
|
+
const cacheIsRelevant = currentIsLocalInstall
|
|
81
|
+
? (cache.isLocalInstall && cache.cwd === currentDir)
|
|
82
|
+
: !cache.isLocalInstall;
|
|
83
|
+
|
|
84
|
+
if (cache.update_available && cacheIsRelevant) {
|
|
85
|
+
kataUpdate = '\x1b[33m⬆ /kata:update\x1b[0m │ ';
|
|
86
|
+
}
|
|
87
|
+
} catch (e) {}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Output
|
|
91
|
+
const dirname = path.basename(dir);
|
|
92
|
+
if (task) {
|
|
93
|
+
process.stdout.write(`${kataUpdate}\x1b[2m${model}\x1b[0m │ \x1b[1m${task}\x1b[0m │ \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
94
|
+
} else {
|
|
95
|
+
process.stdout.write(`${kataUpdate}\x1b[2m${model}\x1b[0m │ \x1b[2m${dirname}\x1b[0m${ctx}`);
|
|
96
|
+
}
|
|
97
|
+
} catch (e) {
|
|
98
|
+
// Silent fail - don't break statusline on parse errors
|
|
99
|
+
}
|
|
100
|
+
});
|
package/kata/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.0.3
|
package/package.json
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gannonh/kata",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Spec-driven development framework for Claude Code.",
|
|
6
6
|
"scripts": {
|
|
7
|
+
"test": "node --test --test-reporter spec ./tests/build.test.js",
|
|
7
8
|
"test:smoke": "node --test --test-reporter spec ./tests/smoke.test.js",
|
|
8
|
-
"test:all": "node --test --test-reporter spec ./tests/build.test.js ./tests/smoke.test.js"
|
|
9
|
+
"test:all": "node --test --test-reporter spec ./tests/build.test.js ./tests/smoke.test.js",
|
|
10
|
+
"build": "node scripts/build.js all",
|
|
11
|
+
"build:plugin": "node scripts/build.js plugin",
|
|
12
|
+
"build:npm": "node scripts/build.js npm",
|
|
13
|
+
"build:hooks": "node scripts/build-hooks.cjs",
|
|
14
|
+
"prepublishOnly": "npm run build:hooks"
|
|
9
15
|
},
|
|
10
16
|
"bin": {
|
|
11
17
|
"kata": "bin/install.js"
|