better-grill 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +6 -3
- package/README.md +39 -106
- package/package.json +10 -4
- package/skills/better-grill/SKILL.md +1 -161
- package/skills/better-grill-base/SKILL.md +182 -0
- package/skills/{better-grill → better-grill-base}/dist/cli.js +21 -19
- package/skills/{better-grill → better-grill-base}/dist/server.js +30 -30
- package/skills/better-grill-base/dist/web/assets/index-Ba23v93I.css +2 -0
- package/skills/better-grill-base/dist/web/assets/index-CXkY56al.js +39 -0
- package/skills/{better-grill → better-grill-base}/dist/web/index.html +2 -2
- package/skills/better-grill-docs/SKILL.md +7 -0
- package/skills/better-grill/dist/web/assets/index-DFidMC-C.js +0 -39
- package/skills/better-grill/dist/web/assets/index-XcpPYDgs.css +0 -2
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- /package/skills/{better-grill → better-grill-base}/dist/web/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-grill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Run grill sessions in a local browser UI instead of the terminal: rounds of questions with options and a recommendation, a discussion thread per question, driven by your open Claude Code session.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Jakub Stastny",
|
|
@@ -10,9 +10,12 @@
|
|
|
10
10
|
"repository": "https://github.com/devbaj-stastny-jakub/better-grill",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"keywords": [
|
|
13
|
+
"ai",
|
|
14
|
+
"browser-ui",
|
|
15
|
+
"claude",
|
|
16
|
+
"claude-code-skill",
|
|
13
17
|
"grill",
|
|
14
18
|
"interview",
|
|
15
|
-
"planning"
|
|
16
|
-
"browser-ui"
|
|
19
|
+
"planning"
|
|
17
20
|
]
|
|
18
21
|
}
|
package/README.md
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
-
# better
|
|
1
|
+
# better-grill
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/better-grill)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
7
|
+
Grill sessions for Claude Code, in your browser instead of the terminal.
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
A grill session is Claude interviewing you about a plan until nothing is left unsaid. It maps the decisions as a tree, asks every question it can answer right now in one round with a recommended answer each, and keeps going until every branch is settled. The method comes from Matt Pocock's [`grilling`](https://github.com/mattpocock/skills) skill; better-grill gives it a proper UI.
|
|
12
|
+
|
|
13
|
+
Why a browser:
|
|
14
|
+
|
|
15
|
+
- **Options side by side**, each with a description and Claude's pick marked, instead of a wall of terminal text.
|
|
16
|
+
- **A discussion thread per question.** Push back on one question without derailing the rest; Claude can reword, resolve, drop or add questions from the talk.
|
|
17
|
+
- **Answer at your own pace.** Lock in questions in any order, change your mind, then send the whole round at once.
|
|
18
|
+
- **Runs on your Claude Code session.** Uses your existing subscription. No API key, no hosted service.
|
|
4
19
|
|
|
5
20
|
## Requirements
|
|
6
21
|
|
|
7
22
|
- [Claude Code](https://code.claude.com)
|
|
8
23
|
- [Node.js](https://nodejs.org) 20 or newer on your `PATH`
|
|
9
|
-
-
|
|
24
|
+
- The `grilling` skill from [mattpocock/skills](https://github.com/mattpocock/skills). better-grill brings the UI; `grilling` brings the method.
|
|
25
|
+
- For the docs variant, also `domain-modeling` from the same repo.
|
|
10
26
|
|
|
11
27
|
## Install
|
|
12
28
|
|
|
@@ -17,125 +33,42 @@ In Claude Code:
|
|
|
17
33
|
/plugin install better-grill@better-grill
|
|
18
34
|
```
|
|
19
35
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
```
|
|
23
|
-
/better-grill:better-grill <what you want grilled>
|
|
24
|
-
```
|
|
36
|
+
## Usage
|
|
25
37
|
|
|
26
|
-
|
|
38
|
+
In any Claude Code session:
|
|
27
39
|
|
|
28
|
-
Several Claude sessions can grill at the same time; each gets its own bridge, port and browser tab.
|
|
29
|
-
|
|
30
|
-
## How it talks to Claude Code
|
|
31
|
-
|
|
32
|
-
Claude Code has no port or socket to call, so the browser cannot reach it. A small local **bridge** sits between them:
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
Claude Code session bridge (node, 127.0.0.1) browser
|
|
36
|
-
─────────────────── ──────────────────────── ───────
|
|
37
|
-
grill round ── POST /api/rounds ─▶ session state ── SSE /api/stream ─▶ UI
|
|
38
|
-
grill wait ── GET /api/wait ───▶ (held open)
|
|
39
|
-
◀── POST answer / chat ──────────── click
|
|
40
|
-
◀── events JSON ───── releases the wait
|
|
41
|
-
grill reply ── POST /reply ──────▶ ── SSE ────────────────────────────▶ chat thread
|
|
42
40
|
```
|
|
43
|
-
|
|
44
|
-
- Claude drives the bridge with the `grill` CLI from its Bash tool.
|
|
45
|
-
- `grill wait` is a long-poll Claude runs in the background. It returns when you press Send or write in a discussion, and Claude Code wakes the session with the events.
|
|
46
|
-
- The bridge never calls Claude. It only holds state and releases waits.
|
|
47
|
-
- A bridge exits on its own after 30 minutes with no wait running, no browser tab open and no requests.
|
|
48
|
-
|
|
49
|
-
### Security
|
|
50
|
-
|
|
51
|
-
The bridge listens on `127.0.0.1` only and:
|
|
52
|
-
|
|
53
|
-
- refuses requests whose `Host` isn't localhost (DNS rebinding),
|
|
54
|
-
- refuses requests whose `Origin` isn't the page it serves, and requires JSON bodies, so other websites open in your browser can't post into the session,
|
|
55
|
-
- refuses Claude-side calls without its session id (see below).
|
|
56
|
-
|
|
57
|
-
## CLI
|
|
58
|
-
|
|
59
|
-
The plugin runs it as `node <skill dir>/dist/cli.js`; outside Claude Code it is also `npx better-grill`.
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
grill start [--title T] [--port N] [--no-open] # prints {"session":"62950-a1b2c3","url","log"}
|
|
63
|
-
grill round -s SESSION < round.json
|
|
64
|
-
grill add -s SESSION < questions.json # into the latest round, while unsent
|
|
65
|
-
grill wait -s SESSION
|
|
66
|
-
grill reply -s SESSION Q3 < text.md
|
|
67
|
-
grill resolve -s SESSION Q3 < resolution.json # {"options":[1],"text":"…"}
|
|
68
|
-
grill edit -s SESSION Q3 < patch.json
|
|
69
|
-
grill drop -s SESSION Q3 < reason.txt
|
|
70
|
-
grill summary -s SESSION < summary.md
|
|
71
|
-
grill state -s SESSION
|
|
72
|
-
grill stop -s SESSION
|
|
41
|
+
/better-grill:better-grill <what you want grilled>
|
|
73
42
|
```
|
|
74
43
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Exit codes: 0 ok, 1 bridge rejected the input, 2 usage error or bridge unreachable.
|
|
78
|
-
|
|
79
|
-
## Development
|
|
80
|
-
|
|
81
|
-
Needs Node 24 (`.nvmrc`) and pnpm.
|
|
44
|
+
Or, to also keep a glossary (`CONTEXT.md`) and ADRs as decisions settle, like `grill-with-docs`:
|
|
82
45
|
|
|
83
|
-
```sh
|
|
84
|
-
pnpm install
|
|
85
|
-
pnpm dev # bridge from TypeScript on :4777 as session 4777-dev (node --watch) + Vite on :5173 proxying /api
|
|
86
|
-
pnpm demo # fake Claude: posts rounds, echoes chat replies, ends in a summary
|
|
87
|
-
pnpm check-types
|
|
88
|
-
pnpm build # web UI + bridge bundle into skills/better-grill/dist
|
|
89
46
|
```
|
|
90
|
-
|
|
91
|
-
Open http://localhost:5173 after `pnpm dev`, then run `pnpm demo` in a second terminal.
|
|
92
|
-
|
|
93
|
-
To use your checkout from real Claude Code sessions, either load it as a plugin with `claude --plugin-dir .`, or symlink the skill:
|
|
94
|
-
|
|
95
|
-
```sh
|
|
96
|
-
ln -s "$PWD/skills/better-grill" ~/.claude/skills/better-grill
|
|
47
|
+
/better-grill:better-grill-docs <what you want grilled>
|
|
97
48
|
```
|
|
98
49
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
50
|
+
1. Your browser opens on the session. The terminal stays quiet; everything happens in the UI.
|
|
51
|
+
2. Claude posts a round of questions. For each one, pick an option, write your own answer, or both, then **Lock in**.
|
|
52
|
+
3. Not sure about a question? Hit **Discuss** and talk it through. Claude answers in the thread and updates the question when you agree on something.
|
|
53
|
+
4. When every question is locked in, **Send to Claude**. The next round builds on your answers.
|
|
54
|
+
5. When nothing is left open, Claude posts a summary of every decision. Confirm it, or say what's wrong and the grilling continues.
|
|
102
55
|
|
|
103
|
-
|
|
104
|
-
| ----------------------- | ----------------------------------------------------------------------------- |
|
|
105
|
-
| `packages/protocol` | Zod schemas and types shared by bridge and UI: rounds, answers, events |
|
|
106
|
-
| `apps/bridge` | Node server (`server.ts`), session logic, `grill` CLI, demo and build scripts |
|
|
107
|
-
| `apps/web` | Vite + React + Tailwind + shadcn/ui (Base UI) UI |
|
|
108
|
-
| `skills/better-grill` | `SKILL.md`, plus the built `dist/` (bridge bundle and web UI) it runs |
|
|
109
|
-
| `.claude-plugin` | Plugin manifest and the marketplace that points at the npm package |
|
|
56
|
+

|
|
110
57
|
|
|
111
|
-
|
|
58
|
+
Several Claude sessions can grill at the same time; each gets its own browser tab.
|
|
112
59
|
|
|
113
|
-
|
|
60
|
+
## How it works
|
|
114
61
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
| `components/ui/` | shadcn components (Base UI, `base-nova` style). Add more with `pnpm dlx shadcn@latest add <name>` in `apps/web` |
|
|
120
|
-
| `components/` | Shared app components: markdown, errors, feedback notes, brand, theme toggle |
|
|
121
|
-
| `hooks/` `lib/` `utils/` `types/` `config/` | Shared hooks, bridge client + theme + lock, pure helpers, types, constants |
|
|
62
|
+
- Claude Code has no port the browser could call, so better-grill starts a small local **bridge** server for each session.
|
|
63
|
+
- Claude talks to the bridge with a CLI from its Bash tool: it posts rounds, then waits in the background until you send a round or write in a discussion.
|
|
64
|
+
- The bridge never calls Claude or any API. It holds the session state and hands your answers back.
|
|
65
|
+
- It listens on `127.0.0.1` only, rejects requests from other websites, and shuts down on its own after 30 idle minutes.
|
|
122
66
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
### Releasing
|
|
126
|
-
|
|
127
|
-
The plugin ships as the `better-grill` npm package; the marketplace in `.claude-plugin/marketplace.json` points at it, so nothing built is committed.
|
|
128
|
-
|
|
129
|
-
```sh
|
|
130
|
-
npm version patch # bumps package.json and .claude-plugin/plugin.json together
|
|
131
|
-
npm publish # prepublishOnly runs check-types and build
|
|
132
|
-
git push --follow-tags
|
|
133
|
-
```
|
|
67
|
+
Details, security model, CLI reference and known limits: [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
134
68
|
|
|
135
|
-
##
|
|
69
|
+
## Contributing
|
|
136
70
|
|
|
137
|
-
|
|
138
|
-
- One Claude session per bridge. Events queue while Claude is busy and arrive as one batch.
|
|
71
|
+
Issues and pull requests welcome. Dev setup: [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
139
72
|
|
|
140
73
|
## License
|
|
141
74
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-grill",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Grill sessions for Claude Code, in your browser instead of the terminal.",
|
|
5
5
|
"keywords": [
|
|
6
|
+
"ai",
|
|
7
|
+
"claude",
|
|
6
8
|
"claude-code",
|
|
7
9
|
"claude-code-plugin",
|
|
10
|
+
"claude-code-skill",
|
|
8
11
|
"grill",
|
|
9
12
|
"interview",
|
|
10
13
|
"planning"
|
|
@@ -23,16 +26,19 @@
|
|
|
23
26
|
"node": ">=20"
|
|
24
27
|
},
|
|
25
28
|
"bin": {
|
|
26
|
-
"better-grill": "skills/better-grill/dist/cli.js"
|
|
29
|
+
"better-grill": "skills/better-grill-base/dist/cli.js"
|
|
27
30
|
},
|
|
28
31
|
"files": [
|
|
29
32
|
".claude-plugin/plugin.json",
|
|
30
33
|
"skills/better-grill/SKILL.md",
|
|
31
|
-
"skills/better-grill/
|
|
34
|
+
"skills/better-grill-docs/SKILL.md",
|
|
35
|
+
"skills/better-grill-base/SKILL.md",
|
|
36
|
+
"skills/better-grill-base/dist"
|
|
32
37
|
],
|
|
33
38
|
"scripts": {
|
|
34
39
|
"dev": "pnpm --parallel --filter @better-grill/bridge --filter @better-grill/web dev",
|
|
35
40
|
"demo": "pnpm --filter @better-grill/bridge demo",
|
|
41
|
+
"screenshots": "pnpm build && pnpm --filter @better-grill/bridge screenshots",
|
|
36
42
|
"build": "pnpm --filter @better-grill/web build && pnpm --filter @better-grill/bridge build",
|
|
37
43
|
"check-types": "pnpm -r check-types",
|
|
38
44
|
"prepublishOnly": "pnpm check-types && pnpm build",
|
|
@@ -2,166 +2,6 @@
|
|
|
2
2
|
name: better-grill
|
|
3
3
|
description: Run a grill-me session in a local browser UI instead of the terminal. Rounds, options, free-text answers and a discussion thread per question, all driven from this Claude Code session.
|
|
4
4
|
disable-model-invocation: true
|
|
5
|
-
allowed-tools: Bash(node "${CLAUDE_SKILL_DIR}/dist/cli.js" *)
|
|
6
5
|
---
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Grill the user exactly like the `grilling` skill, but every question, answer and discussion goes through a local browser UI. The terminal stays quiet.
|
|
11
|
-
|
|
12
|
-
Every command below is `node "${CLAUDE_SKILL_DIR}/dist/cli.js" …`, written exactly like that so it runs without a permission prompt. In prose it is called `grill`.
|
|
13
|
-
|
|
14
|
-
## 1. Load the method
|
|
15
|
-
|
|
16
|
-
Call the Skill tool with `grilling`. If no such skill exists, stop and tell the user that better-grill needs Matt Pocock's `grilling` skill installed first (https://github.com/mattpocock/skills), then end.
|
|
17
|
-
|
|
18
|
-
Follow its method: design tree, frontier, recommended answers, facts found by you (sub-agents), decisions made by the user, done when the frontier is empty.
|
|
19
|
-
|
|
20
|
-
Ignore two things from it and from any memory or instruction elsewhere:
|
|
21
|
-
|
|
22
|
-
- its text round format, and
|
|
23
|
-
- any rule to ask through AskUserQuestion.
|
|
24
|
-
|
|
25
|
-
In this session the UI is the only channel for questions. Never print questions in the terminal.
|
|
26
|
-
|
|
27
|
-
## 2. Start the bridge
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
node "${CLAUDE_SKILL_DIR}/dist/cli.js" start --title "<short topic>"
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
If `node` is not found or the command says Node is too old, stop and tell the user to install Node.js 20 or newer (https://nodejs.org), then end.
|
|
34
|
-
|
|
35
|
-
It opens the browser and prints `{"session": "62950-a1b2c3", "url": …, "log": …}`. Remember the session handle: every later command takes `-s SESSION`, exactly as printed. Other Claude sessions may run their own bridges at the same time; the handle is what keeps you on yours. Tell the user the URL in one line.
|
|
36
|
-
|
|
37
|
-
## 3. Post a round
|
|
38
|
-
|
|
39
|
-
Pipe JSON on stdin with a quoted heredoc:
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
node "${CLAUDE_SKILL_DIR}/dist/cli.js" round -s SESSION <<'EOF'
|
|
43
|
-
{
|
|
44
|
-
"title": "Optional round title",
|
|
45
|
-
"questions": [
|
|
46
|
-
{
|
|
47
|
-
"title": "Short question, ends with ?",
|
|
48
|
-
"body": "Markdown. Context, why it matters, what hangs off it.",
|
|
49
|
-
"options": [
|
|
50
|
-
{ "label": "Option", "description": "What it means, trade-off" }
|
|
51
|
-
],
|
|
52
|
-
"recommended": 0,
|
|
53
|
-
"recommendation": "Markdown. Your recommended answer and why.",
|
|
54
|
-
"multiSelect": false
|
|
55
|
-
}
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
EOF
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
- The bridge numbers questions `Q1`, `Q2`, … across the whole session and prints the ids. Use them in later commands.
|
|
62
|
-
- `recommended` is an index into `options`. Do not write "(Recommended)" into labels; the UI marks it.
|
|
63
|
-
- Do not add an "Other" option. The user can always type an own answer and open a discussion.
|
|
64
|
-
- `options` may be empty for an open question.
|
|
65
|
-
|
|
66
|
-
## 4. Wait for the user
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
node "${CLAUDE_SKILL_DIR}/dist/cli.js" wait -s SESSION
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
**Always run it with `run_in_background: true`.** It blocks until the user does something, which can take hours. You are notified when it exits; then read its output. Keep exactly one wait running: after handling events, start the next wait straight away. While a wait runs you may do other work (sub-agents for facts).
|
|
73
|
-
|
|
74
|
-
Output:
|
|
75
|
-
|
|
76
|
-
```json
|
|
77
|
-
{
|
|
78
|
-
"events": [
|
|
79
|
-
{ "type": "answer", "questionId": "Q2", "title": "…", "choices": ["Label"], "text": "note or own answer", "revised": false, "by": "user" },
|
|
80
|
-
{ "type": "chat", "questionId": "Q3", "title": "…", "text": "user message" }
|
|
81
|
-
],
|
|
82
|
-
"open": [{ "id": "Q3", "title": "…" }]
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
`open` lists questions still unanswered after these events. A wait that returns only `chat` events means the round is still in progress: handle the chat, then wait again.
|
|
87
|
-
|
|
88
|
-
## 5. Handle events
|
|
89
|
-
|
|
90
|
-
- **answer**: the user pressed **Send**, which only works when every question is answered, so answers arrive together as one complete round. Recompute the frontier and post the next round, exactly as in `grilling`.
|
|
91
|
-
- `by: "claude"`: your own resolution (below), which the user sent back unchanged.
|
|
92
|
-
- `revised: true`: the user changed an answer you already had. Re-check everything that depended on it.
|
|
93
|
-
- **chat**: the user wants to talk about that question. Reply in its thread:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
node "${CLAUDE_SKILL_DIR}/dist/cli.js" reply -s SESSION Q3 <<'EOF'
|
|
97
|
-
Markdown reply.
|
|
98
|
-
EOF
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Keep replies conversational and short. Then act on what the talk settled (next section). Never tell the user to go lock in an answer the two of you already agreed on.
|
|
102
|
-
- **summary_confirmed / summary_rejected / ended**: see step 6.
|
|
103
|
-
|
|
104
|
-
## 5b. Shape questions from the discussion
|
|
105
|
-
|
|
106
|
-
The UI is yours to keep accurate. After a chat, change the questions to match what was said:
|
|
107
|
-
|
|
108
|
-
- **Settled in the discussion** → resolve it for the user. Pick option indexes, write text, or both. Use text alone when the agreed answer is none of the options (a custom solution). The user sees "resolved by Claude" and can still change it before Send.
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
node "${CLAUDE_SKILL_DIR}/dist/cli.js" resolve -s SESSION Q6 <<'EOF'
|
|
112
|
-
{ "options": [1], "text": "TanStack Query, and the SSE stream writes into the `['session']` cache." }
|
|
113
|
-
EOF
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
- **Question was framed wrong, or options need changing** → edit it. Send only the fields that change. `null` clears `recommended` / `recommendation`. Sending `options` clears any answer on it, because the answer may point at old options.
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
node "${CLAUDE_SKILL_DIR}/dist/cli.js" edit -s SESSION Q4 <<'EOF'
|
|
120
|
-
{ "title": "Better title?", "options": [{ "label": "A" }, { "label": "B" }], "recommended": 0 }
|
|
121
|
-
EOF
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
- **No longer matters** → drop it (it stays visible, struck through, with your reason):
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
node "${CLAUDE_SKILL_DIR}/dist/cli.js" drop -s SESSION Q4 <<'EOF'
|
|
128
|
-
Moot: you chose memory-only state.
|
|
129
|
-
EOF
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
- **Discussion surfaced a new question for this round** → add it to the current round instead of starting a new one. Fails once the user has sent that round; then it belongs in the next round.
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
node "${CLAUDE_SKILL_DIR}/dist/cli.js" add -s SESSION <<'EOF'
|
|
136
|
-
{ "questions": [{ "title": "…?", "body": "…", "options": [] }] }
|
|
137
|
-
EOF
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
In the thread, say in one line what you changed ("Resolved Q6 as TanStack Query + SSE cache.").
|
|
141
|
-
|
|
142
|
-
## 6. Finish
|
|
143
|
-
|
|
144
|
-
When the frontier is empty and `open` is empty, post a summary of every settled decision (by question id) and remaining risks, then wait:
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
node "${CLAUDE_SKILL_DIR}/dist/cli.js" summary -s SESSION <<'EOF'
|
|
148
|
-
### Settled
|
|
149
|
-
- **Q1 First user:** solo developers
|
|
150
|
-
EOF
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
- `summary_confirmed`: run `grill stop -s SESSION`, then print the summary in the terminal as your final output. Act on it only if the user asks.
|
|
154
|
-
- `summary_rejected`: its `text` is new input. Keep grilling, then post a new summary.
|
|
155
|
-
- `ended` (user closed the session in the UI, at any time): run `grill stop -s SESSION` and print what was settled so far.
|
|
156
|
-
|
|
157
|
-
## Terminal etiquette
|
|
158
|
-
|
|
159
|
-
Between tool calls print at most one short line (for example "Round 3 posted."). All content belongs in the UI.
|
|
160
|
-
|
|
161
|
-
## Troubleshooting
|
|
162
|
-
|
|
163
|
-
- `No bridge for session …` (exit 2): the bridge is gone. It exits on its own after 30 minutes with no wait running and no browser tab open, and it can crash. Start a new one; the old session state is gone.
|
|
164
|
-
- `Wrong session: …` (exit 1): you used a handle that isn't yours, and it reached another session's bridge. Find the `session` your own `grill start` printed and retry with it. Never take a handle from `ps`, a log file or another session. If you can't find yours, start a new bridge.
|
|
165
|
-
- Exit 1 with a validation message: fix the JSON and post again.
|
|
166
|
-
- `grill state -s SESSION` prints the full session state.
|
|
167
|
-
- Bridge log path is printed by `grill start`.
|
|
7
|
+
Call the Skill tool with `better-grill-base` (listed as `better-grill:better-grill-base` when installed as a plugin) and args `plain`, then follow it. The user's request above is the topic to grill.
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: better-grill-base
|
|
3
|
+
description: Internal. Shared instructions loaded by the better-grill and better-grill-docs skills. Do not invoke directly.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
allowed-tools: Bash(node "${CLAUDE_SKILL_DIR}/dist/cli.js" *)
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Better Grill
|
|
9
|
+
|
|
10
|
+
Grill the user exactly like the `grilling` skill, but every question, answer and discussion goes through a local browser UI. The terminal stays quiet.
|
|
11
|
+
|
|
12
|
+
Every command below is `node "${CLAUDE_SKILL_DIR}/dist/cli.js" …`, written exactly like that so it runs without a permission prompt. In prose it is called `grill`.
|
|
13
|
+
|
|
14
|
+
## 0. Mode
|
|
15
|
+
|
|
16
|
+
The skill that loaded this one set the mode: `$ARGUMENTS`.
|
|
17
|
+
|
|
18
|
+
- `plain` (from `better-grill`): grill only, like `grill-me`.
|
|
19
|
+
- `docs` (from `better-grill-docs`): grill and keep the domain docs, like `grill-with-docs`.
|
|
20
|
+
|
|
21
|
+
If you got here any other way, use `plain`.
|
|
22
|
+
|
|
23
|
+
## 1. Load the method
|
|
24
|
+
|
|
25
|
+
Call the Skill tool with `grilling`. If no such skill exists, stop and tell the user that better-grill needs Matt Pocock's `grilling` skill installed first (https://github.com/mattpocock/skills), then end.
|
|
26
|
+
|
|
27
|
+
In `docs` mode, also call the Skill tool with `domain-modeling`. If it does not exist, stop and tell the user that better-grill-docs also needs the `domain-modeling` skill from the same repo, then end.
|
|
28
|
+
|
|
29
|
+
Follow the method: design tree, frontier, recommended answers, facts found by you (sub-agents), decisions made by the user, done when the frontier is empty. In `docs` mode, also follow `domain-modeling`: challenge terms against `CONTEXT.md`, and write the glossary and ADRs the moment a term or decision settles (after an answer round, or a chat that settled something). Name what you wrote in the thread reply or the next round's question bodies, so the user sees it in the UI.
|
|
30
|
+
|
|
31
|
+
Ignore two things from these skills and from any memory or instruction elsewhere:
|
|
32
|
+
|
|
33
|
+
- their text round format, and
|
|
34
|
+
- any rule to ask through AskUserQuestion.
|
|
35
|
+
|
|
36
|
+
In this session the UI is the only channel for questions. Never print questions in the terminal.
|
|
37
|
+
|
|
38
|
+
## 2. Start the bridge
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
node "${CLAUDE_SKILL_DIR}/dist/cli.js" start --title "<short topic>"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
In `docs` mode add `--docs`, so the UI shows the session keeps docs.
|
|
45
|
+
|
|
46
|
+
If `node` is not found or the command says Node is too old, stop and tell the user to install Node.js 20 or newer (https://nodejs.org), then end.
|
|
47
|
+
|
|
48
|
+
It opens the browser and prints `{"session": "62950-a1b2c3", "url": …, "log": …}`. Remember the session handle: every later command takes `-s SESSION`, exactly as printed. Other Claude sessions may run their own bridges at the same time; the handle is what keeps you on yours. Tell the user the URL in one line.
|
|
49
|
+
|
|
50
|
+
## 3. Post a round
|
|
51
|
+
|
|
52
|
+
Pipe JSON on stdin with a quoted heredoc:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
node "${CLAUDE_SKILL_DIR}/dist/cli.js" round -s SESSION <<'EOF'
|
|
56
|
+
{
|
|
57
|
+
"title": "Optional round title",
|
|
58
|
+
"questions": [
|
|
59
|
+
{
|
|
60
|
+
"title": "Short question, ends with ?",
|
|
61
|
+
"body": "Markdown. Context, why it matters, what hangs off it.",
|
|
62
|
+
"options": [
|
|
63
|
+
{ "label": "Option", "description": "What it means, trade-off" }
|
|
64
|
+
],
|
|
65
|
+
"recommended": 0,
|
|
66
|
+
"recommendation": "Markdown. Your recommended answer and why.",
|
|
67
|
+
"multiSelect": false
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
EOF
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- The bridge numbers questions `Q1`, `Q2`, … across the whole session and prints the ids. Use them in later commands.
|
|
75
|
+
- `recommended` is an index into `options`. Do not write "(Recommended)" into labels; the UI marks it.
|
|
76
|
+
- Do not add an "Other" option. The user can always type an own answer and open a discussion.
|
|
77
|
+
- `options` may be empty for an open question.
|
|
78
|
+
|
|
79
|
+
## 4. Wait for the user
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
node "${CLAUDE_SKILL_DIR}/dist/cli.js" wait -s SESSION
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Always run it with `run_in_background: true`.** It blocks until the user does something, which can take hours. You are notified when it exits; then read its output. Keep exactly one wait running: after handling events, start the next wait straight away. While a wait runs you may do other work (sub-agents for facts).
|
|
86
|
+
|
|
87
|
+
Output:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"events": [
|
|
92
|
+
{ "type": "answer", "questionId": "Q2", "title": "…", "choices": ["Label"], "text": "note or own answer", "revised": false, "by": "user" },
|
|
93
|
+
{ "type": "chat", "questionId": "Q3", "title": "…", "text": "user message" }
|
|
94
|
+
],
|
|
95
|
+
"open": [{ "id": "Q3", "title": "…" }]
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`open` lists questions still unanswered after these events. A wait that returns only `chat` events means the round is still in progress: handle the chat, then wait again.
|
|
100
|
+
|
|
101
|
+
## 5. Handle events
|
|
102
|
+
|
|
103
|
+
- **answer**: the user pressed **Send**, which only works when every question is answered, so answers arrive together as one complete round. Recompute the frontier and post the next round, exactly as in `grilling`.
|
|
104
|
+
- `by: "claude"`: your own resolution (below), which the user sent back unchanged.
|
|
105
|
+
- `revised: true`: the user changed an answer you already had. Re-check everything that depended on it.
|
|
106
|
+
- **chat**: the user wants to talk about that question. Reply in its thread:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
node "${CLAUDE_SKILL_DIR}/dist/cli.js" reply -s SESSION Q3 <<'EOF'
|
|
110
|
+
Markdown reply.
|
|
111
|
+
EOF
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Keep replies conversational and short. Then act on what the talk settled (next section). Never tell the user to go lock in an answer the two of you already agreed on.
|
|
115
|
+
- **summary_confirmed / summary_rejected / ended**: see step 6.
|
|
116
|
+
|
|
117
|
+
## 5b. Shape questions from the discussion
|
|
118
|
+
|
|
119
|
+
The UI is yours to keep accurate. After a chat, change the questions to match what was said:
|
|
120
|
+
|
|
121
|
+
- **Settled in the discussion** → resolve it for the user. Pick option indexes, write text, or both. Use text alone when the agreed answer is none of the options (a custom solution). The user sees "resolved by Claude" and can still change it before Send.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
node "${CLAUDE_SKILL_DIR}/dist/cli.js" resolve -s SESSION Q6 <<'EOF'
|
|
125
|
+
{ "options": [1], "text": "TanStack Query, and the SSE stream writes into the `['session']` cache." }
|
|
126
|
+
EOF
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- **Question was framed wrong, or options need changing** → edit it. Send only the fields that change. `null` clears `recommended` / `recommendation`. Sending `options` clears any answer on it, because the answer may point at old options.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
node "${CLAUDE_SKILL_DIR}/dist/cli.js" edit -s SESSION Q4 <<'EOF'
|
|
133
|
+
{ "title": "Better title?", "options": [{ "label": "A" }, { "label": "B" }], "recommended": 0 }
|
|
134
|
+
EOF
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
- **No longer matters** → drop it (it stays visible, struck through, with your reason):
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
node "${CLAUDE_SKILL_DIR}/dist/cli.js" drop -s SESSION Q4 <<'EOF'
|
|
141
|
+
Moot: you chose memory-only state.
|
|
142
|
+
EOF
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
- **Discussion surfaced a new question for this round** → add it to the current round instead of starting a new one. Fails once the user has sent that round; then it belongs in the next round.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
node "${CLAUDE_SKILL_DIR}/dist/cli.js" add -s SESSION <<'EOF'
|
|
149
|
+
{ "questions": [{ "title": "…?", "body": "…", "options": [] }] }
|
|
150
|
+
EOF
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
In the thread, say in one line what you changed ("Resolved Q6 as TanStack Query + SSE cache.").
|
|
154
|
+
|
|
155
|
+
## 6. Finish
|
|
156
|
+
|
|
157
|
+
When the frontier is empty and `open` is empty, post a summary of every settled decision (by question id) and remaining risks, then wait:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
node "${CLAUDE_SKILL_DIR}/dist/cli.js" summary -s SESSION <<'EOF'
|
|
161
|
+
### Settled
|
|
162
|
+
- **Q1 First user:** solo developers
|
|
163
|
+
EOF
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
In `docs` mode, end the summary with a `### Docs` section listing every file you created or changed (`CONTEXT.md`, each ADR).
|
|
167
|
+
|
|
168
|
+
- `summary_confirmed`: run `grill stop -s SESSION`, then print the summary in the terminal as your final output. Act on it only if the user asks.
|
|
169
|
+
- `summary_rejected`: its `text` is new input. Keep grilling, then post a new summary.
|
|
170
|
+
- `ended` (user closed the session in the UI, at any time): run `grill stop -s SESSION` and print what was settled so far.
|
|
171
|
+
|
|
172
|
+
## Terminal etiquette
|
|
173
|
+
|
|
174
|
+
Between tool calls print at most one short line (for example "Round 3 posted." or "ADR 0003 written."). All content belongs in the UI.
|
|
175
|
+
|
|
176
|
+
## Troubleshooting
|
|
177
|
+
|
|
178
|
+
- `No bridge for session …` (exit 2): the bridge is gone. It exits on its own after 30 minutes with no wait running and no browser tab open, and it can crash. Start a new one; the old session state is gone.
|
|
179
|
+
- `Wrong session: …` (exit 1): you used a handle that isn't yours, and it reached another session's bridge. Find the `session` your own `grill start` printed and retry with it. Never take a handle from `ps`, a log file or another session. If you can't find yours, start a new bridge.
|
|
180
|
+
- Exit 1 with a validation message: fix the JSON and post again.
|
|
181
|
+
- `grill state -s SESSION` prints the full session state.
|
|
182
|
+
- Bridge log path is printed by `grill start`.
|