kingdom-cli 0.2__tar.gz → 0.3.0__tar.gz
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.
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/PKG-INFO +60 -23
- kingdom_cli-0.3.0/README.md +137 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/pyproject.toml +2 -1
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/agent.py +91 -2
- kingdom_cli-0.3.0/src/kingdom/cli/__init__.py +466 -0
- kingdom_cli-0.3.0/src/kingdom/cli/config.py +138 -0
- kingdom_cli-0.3.0/src/kingdom/cli/council.py +1220 -0
- kingdom_cli-0.3.0/src/kingdom/cli/design.py +94 -0
- kingdom_cli-0.3.0/src/kingdom/cli/display.py +42 -0
- kingdom_cli-0.3.0/src/kingdom/cli/helpers.py +148 -0
- kingdom_cli-0.3.0/src/kingdom/cli/peasant.py +1370 -0
- kingdom_cli-0.3.0/src/kingdom/cli/ticket.py +1229 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/config.py +106 -39
- kingdom_cli-0.3.0/src/kingdom/council/__init__.py +48 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/council/base.py +14 -7
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/council/council.py +19 -5
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/council/worker.py +2 -11
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/design.py +1 -1
- kingdom_cli-0.3.0/src/kingdom/harness.py +1144 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/parsing.py +30 -1
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/skill/SKILL.md +0 -6
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/skill/references/peasants.md +1 -5
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/state.py +118 -96
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/thread.py +49 -26
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/ticket.py +270 -77
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/tui/app.py +424 -151
- kingdom_cli-0.3.0/src/kingdom/tui/chat.tcss +116 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/tui/poll.py +23 -9
- kingdom_cli-0.3.0/src/kingdom/tui/terminal.py +43 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/tui/widgets.py +63 -83
- kingdom_cli-0.3.0/src/kingdom/worker.py +54 -0
- kingdom_cli-0.3.0/src/kingdom/worktree.py +133 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom_cli.egg-info/PKG-INFO +60 -23
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom_cli.egg-info/SOURCES.txt +22 -4
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_agent.py +67 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_cli.py +195 -163
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_cli_council.py +235 -99
- kingdom_cli-0.3.0/tests/test_cli_design_breakdown.py +78 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_cli_peasant.py +781 -89
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_cli_status.py +19 -23
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_cli_ticket_current.py +12 -12
- kingdom_cli-0.3.0/tests/test_cli_ticket_deps.py +382 -0
- kingdom_cli-0.3.0/tests/test_cli_ticket_lifecycle.py +904 -0
- kingdom_cli-0.3.0/tests/test_cli_ticket_links.py +83 -0
- kingdom_cli-0.3.0/tests/test_cli_ticket_list.py +953 -0
- kingdom_cli-0.3.0/tests/test_cli_ticket_show.py +340 -0
- kingdom_cli-0.3.0/tests/test_cli_ticket_worklog.py +102 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_config.py +91 -32
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_council.py +66 -7
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_done.py +71 -37
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_harness.py +746 -177
- kingdom_cli-0.3.0/tests/test_init.py +273 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_parsing.py +66 -1
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_session.py +0 -7
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_state.py +212 -6
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_thread.py +173 -12
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_ticket.py +380 -15
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_tui.py +775 -82
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_tui_clipboard.py +66 -1
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_tui_integration.py +239 -30
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_tui_poll.py +85 -14
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_tui_reply.py +58 -26
- kingdom_cli-0.3.0/tests/test_tui_terminal.py +82 -0
- kingdom_cli-0.3.0/tests/test_tui_thinking_persistence.py +191 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_tui_widgets.py +8 -0
- kingdom_cli-0.3.0/tests/test_worker.py +106 -0
- kingdom_cli-0.3.0/tests/test_worktree.py +25 -0
- kingdom_cli-0.2/README.md +0 -100
- kingdom_cli-0.2/src/kingdom/cli.py +0 -4176
- kingdom_cli-0.2/src/kingdom/council/__init__.py +0 -13
- kingdom_cli-0.2/src/kingdom/harness.py +0 -727
- kingdom_cli-0.2/tests/test_cli_design_breakdown.py +0 -83
- kingdom_cli-0.2/tests/test_cli_ticket.py +0 -2440
- kingdom_cli-0.2/tests/test_cli_whoami.py +0 -46
- kingdom_cli-0.2/tests/test_init.py +0 -360
- kingdom_cli-0.2/tests/test_tui_thinking_persistence.py +0 -159
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/LICENSE +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/setup.cfg +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/__init__.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/__main__.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/breakdown.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/council/bundle.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/session.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/skill/__init__.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/skill/references/__init__.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/skill/references/council.md +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/skill/references/tickets.md +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/synthesis.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/tui/__init__.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom/tui/clipboard.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom_cli.egg-info/dependency_links.txt +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom_cli.egg-info/entry_points.txt +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom_cli.egg-info/requires.txt +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/src/kingdom_cli.egg-info/top_level.txt +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_breakdown.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_design.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_skill.py +0 -0
- {kingdom_cli-0.2 → kingdom_cli-0.3.0}/tests/test_synthesis.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kingdom-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A markdown file-based CLI for software development with multi-agent council design, markdown tickets, and background worker loops.
|
|
5
5
|
Author: James Robinson-Bohnslav
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -48,49 +48,72 @@ Gastown minus the polecats.
|
|
|
48
48
|
uv tool install kingdom-cli
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
##
|
|
51
|
+
## Workflow Scales
|
|
52
|
+
|
|
53
|
+
`kd` scales down gracefully. You pick the parts of the workflow that fit the size of the work.
|
|
54
|
+
|
|
55
|
+
### Full workflow (new features)
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
Design with the council, break into tickets, dispatch peasants, review, and merge.
|
|
54
58
|
|
|
55
59
|
```bash
|
|
56
|
-
kd start
|
|
60
|
+
kd start # initialize branch session
|
|
61
|
+
kd council chat --new # discuss design with the council TUI
|
|
62
|
+
kd design approve # lock in the design
|
|
63
|
+
# create tickets from the design (via the kingdom skill or manually)
|
|
64
|
+
kd peasant start <id> # dispatch parallel workers
|
|
65
|
+
kd peasant review <id> # review completed work
|
|
66
|
+
kd peasant accept <id> # accept and close, or reject with feedback
|
|
67
|
+
kd done # archive and clean up
|
|
57
68
|
```
|
|
58
69
|
|
|
59
|
-
|
|
70
|
+
### Medium workflow (refactors, smaller features)
|
|
60
71
|
|
|
61
|
-
|
|
72
|
+
Pull tickets into a branch, work them directly or with peasants. No design phase needed.
|
|
62
73
|
|
|
63
74
|
```bash
|
|
64
|
-
kd
|
|
75
|
+
kd start
|
|
76
|
+
kd tk pull <id> <id> # pull backlog tickets onto this branch
|
|
77
|
+
kd tk start <id> # work tickets one at a time
|
|
78
|
+
kd tk close <id>
|
|
79
|
+
kd done
|
|
65
80
|
```
|
|
66
81
|
|
|
67
|
-
|
|
82
|
+
### Lightweight workflow (bug fixes)
|
|
83
|
+
|
|
84
|
+
Work a single ticket, close it, make a PR. Or batch several bug-fix tickets on one branch.
|
|
68
85
|
|
|
69
86
|
```bash
|
|
70
|
-
kd
|
|
87
|
+
kd start
|
|
88
|
+
kd tk create "fix: login redirect loop"
|
|
89
|
+
kd tk start <id>
|
|
90
|
+
# ... fix the bug ...
|
|
91
|
+
kd tk close <id>
|
|
92
|
+
kd done
|
|
71
93
|
```
|
|
72
94
|
|
|
73
|
-
|
|
95
|
+
Design docs, council sessions, and peasant workers are all optional. A branch with one ticket and no design doc is a perfectly valid `kd` workflow.
|
|
96
|
+
|
|
97
|
+
## Getting Started
|
|
74
98
|
|
|
75
99
|
```bash
|
|
76
|
-
kd
|
|
77
|
-
kd ticket show <id>
|
|
100
|
+
kd start # start a session on the current branch
|
|
78
101
|
```
|
|
79
102
|
|
|
80
|
-
|
|
81
|
-
- Serial: tell Claude Code or Codex to work tickets directly, or run `kd work <id>`.
|
|
82
|
-
- Parallel: dispatch peasants in worktrees.
|
|
103
|
+
Configure council agent CLIs in `.kd/config.json` (check effective config with `kd config show`).
|
|
83
104
|
|
|
84
|
-
|
|
85
|
-
kd peasant start <id>
|
|
86
|
-
kd peasant status
|
|
87
|
-
```
|
|
105
|
+
## Chat Modes
|
|
88
106
|
|
|
89
|
-
|
|
107
|
+
The council chat TUI (`kd council chat`) supports four modes, configured via `council.chat.mode`:
|
|
90
108
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
109
|
+
| Mode | First turn | Auto-turns | Default |
|
|
110
|
+
|------|-----------|------------|---------|
|
|
111
|
+
| `natural` | parallel broadcast | shuffled round-robin | yes |
|
|
112
|
+
| `round_robin` | sequential fixed-order | sequential fixed-order | |
|
|
113
|
+
| `manual` | only @mentioned | only @mentioned | |
|
|
114
|
+
| `broadcast` | parallel to all | parallel to all | |
|
|
115
|
+
|
|
116
|
+
LLM-to-LLM @mentions in responses automatically bump the mentioned member to the front of the auto-turn queue.
|
|
94
117
|
|
|
95
118
|
## How It Works
|
|
96
119
|
|
|
@@ -114,6 +137,20 @@ All state lives in `.kd/` as plain Markdown and JSON files, tracked in git along
|
|
|
114
137
|
|
|
115
138
|
No database. No server. Just files on disk.
|
|
116
139
|
|
|
140
|
+
## Commands
|
|
141
|
+
|
|
142
|
+
| Group | Description |
|
|
143
|
+
|-------|-------------|
|
|
144
|
+
| `kd start` / `kd done` / `kd status` | Branch lifecycle — initialize, finish, and inspect sessions |
|
|
145
|
+
| `kd design` | Manage design documents (`show`, `approve`) |
|
|
146
|
+
| `kd council` | Multi-model council — `ask`, `chat`, `review`, `show`, `list`, `watch`, `reset`, `retry` |
|
|
147
|
+
| `kd ticket` (alias `kd tk`) | Ticket management — `create`, `list`, `show`, `start`, `close`, `deps`, and more |
|
|
148
|
+
| `kd peasant` | Worker agents — `start`, `stop`, `review`, `accept`, `reject`, `msg`, `read`, `watch` |
|
|
149
|
+
| `kd config` | View and manage configuration |
|
|
150
|
+
| `kd doctor` | Check config and agent CLIs |
|
|
151
|
+
|
|
152
|
+
Run `kd <command> --help` for full flags and options.
|
|
153
|
+
|
|
117
154
|
## Development
|
|
118
155
|
|
|
119
156
|
```bash
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Kingdom
|
|
2
|
+
|
|
3
|
+
Kingdom (`kd`) is a markdown file-based CLI for software development: design with a multi-agent council, track work as markdown tickets, and run background RALPH loops with worker peasants.
|
|
4
|
+
|
|
5
|
+
The kingdom metaphor is intentional: you are the King, debate your design documents with a council of frontier coding agent CLIs you already use (Claude Code and Codex), break the design into modular markdown tickets, and then peasants execute those tickets in parallel worktrees.
|
|
6
|
+
|
|
7
|
+
Gastown minus the polecats.
|
|
8
|
+
|
|
9
|
+
## Why
|
|
10
|
+
|
|
11
|
+
- **Multi-agent council** — get perspectives from multiple frontier coding models, not just one opinion. Different models catch different things.
|
|
12
|
+
- **Ticket-based execution** — breaking work into scoped tickets fights context rot, lets you use cheaper models for already-designed work, or run tickets in parallel.
|
|
13
|
+
- **Multi-agent reviews** — reviews across models consistently catch bugs that single-agent reviews miss.
|
|
14
|
+
- **Plain markdown files** — tickets, designs, and council threads are all markdown. Your coding agents are already good at finding, reading, and updating markdown.
|
|
15
|
+
- **CLI + TUI** — the TUI is for humans; agent CLIs use `kd` directly to ask the council or other agents for opinions.
|
|
16
|
+
- **Worklog audit trail** — peasant worklogs capture decisions, bugs encountered, and test results in the ticket markdown, committed to git. You can always see *why* something was done, not just the diff.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
uv tool install kingdom-cli
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Workflow Scales
|
|
25
|
+
|
|
26
|
+
`kd` scales down gracefully. You pick the parts of the workflow that fit the size of the work.
|
|
27
|
+
|
|
28
|
+
### Full workflow (new features)
|
|
29
|
+
|
|
30
|
+
Design with the council, break into tickets, dispatch peasants, review, and merge.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
kd start # initialize branch session
|
|
34
|
+
kd council chat --new # discuss design with the council TUI
|
|
35
|
+
kd design approve # lock in the design
|
|
36
|
+
# create tickets from the design (via the kingdom skill or manually)
|
|
37
|
+
kd peasant start <id> # dispatch parallel workers
|
|
38
|
+
kd peasant review <id> # review completed work
|
|
39
|
+
kd peasant accept <id> # accept and close, or reject with feedback
|
|
40
|
+
kd done # archive and clean up
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Medium workflow (refactors, smaller features)
|
|
44
|
+
|
|
45
|
+
Pull tickets into a branch, work them directly or with peasants. No design phase needed.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
kd start
|
|
49
|
+
kd tk pull <id> <id> # pull backlog tickets onto this branch
|
|
50
|
+
kd tk start <id> # work tickets one at a time
|
|
51
|
+
kd tk close <id>
|
|
52
|
+
kd done
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Lightweight workflow (bug fixes)
|
|
56
|
+
|
|
57
|
+
Work a single ticket, close it, make a PR. Or batch several bug-fix tickets on one branch.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
kd start
|
|
61
|
+
kd tk create "fix: login redirect loop"
|
|
62
|
+
kd tk start <id>
|
|
63
|
+
# ... fix the bug ...
|
|
64
|
+
kd tk close <id>
|
|
65
|
+
kd done
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Design docs, council sessions, and peasant workers are all optional. A branch with one ticket and no design doc is a perfectly valid `kd` workflow.
|
|
69
|
+
|
|
70
|
+
## Getting Started
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
kd start # start a session on the current branch
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Configure council agent CLIs in `.kd/config.json` (check effective config with `kd config show`).
|
|
77
|
+
|
|
78
|
+
## Chat Modes
|
|
79
|
+
|
|
80
|
+
The council chat TUI (`kd council chat`) supports four modes, configured via `council.chat.mode`:
|
|
81
|
+
|
|
82
|
+
| Mode | First turn | Auto-turns | Default |
|
|
83
|
+
|------|-----------|------------|---------|
|
|
84
|
+
| `natural` | parallel broadcast | shuffled round-robin | yes |
|
|
85
|
+
| `round_robin` | sequential fixed-order | sequential fixed-order | |
|
|
86
|
+
| `manual` | only @mentioned | only @mentioned | |
|
|
87
|
+
| `broadcast` | parallel to all | parallel to all | |
|
|
88
|
+
|
|
89
|
+
LLM-to-LLM @mentions in responses automatically bump the mentioned member to the front of the auto-turn queue.
|
|
90
|
+
|
|
91
|
+
## How It Works
|
|
92
|
+
|
|
93
|
+
All state lives in `.kd/` as plain Markdown and JSON files, tracked in git alongside your code:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
.kd/
|
|
97
|
+
├── branches/ # Active branch work
|
|
98
|
+
│ └── feature-oauth-refresh/
|
|
99
|
+
│ ├── design.md # Design document
|
|
100
|
+
│ ├── breakdown.md # Ticket breakdown
|
|
101
|
+
│ ├── tickets/ # Branch-specific tickets
|
|
102
|
+
│ │ ├── a1b2.md
|
|
103
|
+
│ │ └── c3d4.md
|
|
104
|
+
│ └── threads/ # Council discussion threads
|
|
105
|
+
├── backlog/ # Unassigned tickets
|
|
106
|
+
│ └── tickets/
|
|
107
|
+
├── archive/ # Completed branches
|
|
108
|
+
└── worktrees/ # Git worktrees (gitignored)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
No database. No server. Just files on disk.
|
|
112
|
+
|
|
113
|
+
## Commands
|
|
114
|
+
|
|
115
|
+
| Group | Description |
|
|
116
|
+
|-------|-------------|
|
|
117
|
+
| `kd start` / `kd done` / `kd status` | Branch lifecycle — initialize, finish, and inspect sessions |
|
|
118
|
+
| `kd design` | Manage design documents (`show`, `approve`) |
|
|
119
|
+
| `kd council` | Multi-model council — `ask`, `chat`, `review`, `show`, `list`, `watch`, `reset`, `retry` |
|
|
120
|
+
| `kd ticket` (alias `kd tk`) | Ticket management — `create`, `list`, `show`, `start`, `close`, `deps`, and more |
|
|
121
|
+
| `kd peasant` | Worker agents — `start`, `stop`, `review`, `accept`, `reject`, `msg`, `read`, `watch` |
|
|
122
|
+
| `kd config` | View and manage configuration |
|
|
123
|
+
| `kd doctor` | Check config and agent CLIs |
|
|
124
|
+
|
|
125
|
+
Run `kd <command> --help` for full flags and options.
|
|
126
|
+
|
|
127
|
+
## Development
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
uv sync
|
|
131
|
+
source .venv/bin/activate
|
|
132
|
+
pytest tests/
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
Apache-2.0 — see [LICENSE](LICENSE) for details.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "kingdom-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "A markdown file-based CLI for software development with multi-agent council design, markdown tickets, and background worker loops."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -42,6 +42,7 @@ where = ["src"]
|
|
|
42
42
|
|
|
43
43
|
[tool.setuptools.package-data]
|
|
44
44
|
"kingdom.skill" = ["*.md", "references/*.md"]
|
|
45
|
+
"kingdom.tui" = ["*.tcss"]
|
|
45
46
|
|
|
46
47
|
[dependency-groups]
|
|
47
48
|
dev = [
|
|
@@ -435,13 +435,19 @@ COMMAND_BUILDERS: dict[str, CommandBuilder] = {
|
|
|
435
435
|
}
|
|
436
436
|
|
|
437
437
|
|
|
438
|
-
def clean_agent_env(
|
|
438
|
+
def clean_agent_env(
|
|
439
|
+
role: str | None = None,
|
|
440
|
+
agent_name: str | None = None,
|
|
441
|
+
kd_base: str | None = None,
|
|
442
|
+
) -> dict[str, str]:
|
|
439
443
|
"""Return an env dict safe for spawning agent CLI subprocesses.
|
|
440
444
|
|
|
441
445
|
Strips ``CLAUDECODE`` so child ``claude`` processes don't refuse to start
|
|
442
446
|
with a "nested session" error when ``kd`` is invoked from inside Claude Code.
|
|
443
447
|
|
|
444
|
-
Optionally injects ``KD_ROLE
|
|
448
|
+
Optionally injects ``KD_ROLE``, ``KD_AGENT_NAME``, and ``KD_BASE``.
|
|
449
|
+
``KD_BASE`` ensures worktree agents resolve the project root against the
|
|
450
|
+
main repo, not the worktree's copy of ``.kd/``.
|
|
445
451
|
"""
|
|
446
452
|
import os
|
|
447
453
|
|
|
@@ -450,6 +456,8 @@ def clean_agent_env(role: str | None = None, agent_name: str | None = None) -> d
|
|
|
450
456
|
env["KD_ROLE"] = role
|
|
451
457
|
if agent_name:
|
|
452
458
|
env["KD_AGENT_NAME"] = agent_name
|
|
459
|
+
if kd_base:
|
|
460
|
+
env["KD_BASE"] = kd_base
|
|
453
461
|
return env
|
|
454
462
|
|
|
455
463
|
|
|
@@ -646,3 +654,84 @@ def extract_stream_thinking(line: str, backend: str) -> str | None:
|
|
|
646
654
|
if extractor is None:
|
|
647
655
|
return None
|
|
648
656
|
return extractor(line)
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
# ---------------------------------------------------------------------------
|
|
660
|
+
# Stream tool-use extractors — extract tool invocation names from NDJSON
|
|
661
|
+
# ---------------------------------------------------------------------------
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
def extract_claude_stream_tool_use(line: str) -> str | None:
|
|
665
|
+
"""Extract tool name from a Claude Code stream-json NDJSON line.
|
|
666
|
+
|
|
667
|
+
Claude Code emits ``content_block_start`` with a ``tool_use`` block
|
|
668
|
+
containing the tool name (e.g. "Read", "Bash", "Write").
|
|
669
|
+
"""
|
|
670
|
+
try:
|
|
671
|
+
event = json.loads(line)
|
|
672
|
+
except json.JSONDecodeError:
|
|
673
|
+
return None
|
|
674
|
+
if not isinstance(event, dict):
|
|
675
|
+
return None
|
|
676
|
+
if event.get("type") == "stream_event":
|
|
677
|
+
event = event.get("event", {})
|
|
678
|
+
if event.get("type") == "content_block_start":
|
|
679
|
+
block = event.get("content_block", {})
|
|
680
|
+
if block.get("type") == "tool_use":
|
|
681
|
+
return block.get("name")
|
|
682
|
+
return None
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
def extract_cursor_stream_tool_use(line: str) -> str | None:
|
|
686
|
+
"""Extract tool name from a Cursor stream-json NDJSON line.
|
|
687
|
+
|
|
688
|
+
Cursor emits ``{"type": "tool_call", "subtype": "started", ...}``
|
|
689
|
+
when a tool invocation begins. The ``name`` field may or may not
|
|
690
|
+
be present depending on the Cursor version.
|
|
691
|
+
"""
|
|
692
|
+
try:
|
|
693
|
+
event = json.loads(line)
|
|
694
|
+
except json.JSONDecodeError:
|
|
695
|
+
return None
|
|
696
|
+
if not isinstance(event, dict):
|
|
697
|
+
return None
|
|
698
|
+
if event.get("type") == "tool_call" and event.get("subtype") == "started":
|
|
699
|
+
return event.get("name") or "tool"
|
|
700
|
+
return None
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
def extract_codex_stream_tool_use(line: str) -> str | None:
|
|
704
|
+
"""Extract tool name from a Codex NDJSON line.
|
|
705
|
+
|
|
706
|
+
Codex emits ``item.completed`` events for tool calls with
|
|
707
|
+
``item.type == "function_call"``.
|
|
708
|
+
"""
|
|
709
|
+
try:
|
|
710
|
+
event = json.loads(line)
|
|
711
|
+
except json.JSONDecodeError:
|
|
712
|
+
return None
|
|
713
|
+
if not isinstance(event, dict):
|
|
714
|
+
return None
|
|
715
|
+
if event.get("type") == "item.completed":
|
|
716
|
+
item = event.get("item", {})
|
|
717
|
+
if item.get("type") == "function_call":
|
|
718
|
+
return item.get("name", "tool")
|
|
719
|
+
return None
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
STREAM_TOOL_USE_EXTRACTORS: dict[str, StreamExtractor] = {
|
|
723
|
+
"claude_code": extract_claude_stream_tool_use,
|
|
724
|
+
"codex": extract_codex_stream_tool_use,
|
|
725
|
+
"cursor": extract_cursor_stream_tool_use,
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
def extract_stream_tool_use(line: str, backend: str) -> str | None:
|
|
730
|
+
"""Extract tool name from a single NDJSON line for the given backend.
|
|
731
|
+
|
|
732
|
+
Returns the tool name string, or None for non-tool-use events.
|
|
733
|
+
"""
|
|
734
|
+
extractor = STREAM_TOOL_USE_EXTRACTORS.get(backend)
|
|
735
|
+
if extractor is None:
|
|
736
|
+
return None
|
|
737
|
+
return extractor(line)
|