@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 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
+ [![Plugin](https://img.shields.io/badge/plugin-kata--marketplace-blue?style=for-the-badge)](https://github.com/gannonh/kata-marketplace)
19
+ [![npm version](https://img.shields.io/npm/v/@gannonh/kata?style=for-the-badge&logo=npm&logoColor=white&color=CB3837)](https://www.npmjs.com/package/@gannonh/kata)
20
+
21
+ <br>
22
+
23
+ [![Kata Install](assets/terminal.svg)](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.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"