codedeck 0.1.8 → 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/README.md +68 -1
- package/dist/cli/commands/open.js +498 -0
- package/dist/cli/commands/open.js.map +1 -0
- package/dist/cli/commands/run.js +25 -18
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/setup.js +182 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/picker-state.js +101 -0
- package/dist/cli/picker-state.js.map +1 -0
- package/dist/cli/picker.js +147 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/ui.js +217 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/config.js +8 -0
- package/dist/config/config.js.map +1 -1
- package/dist/core/models.js +23 -4
- package/dist/core/models.js.map +1 -1
- package/dist/core/roles.js +72 -0
- package/dist/core/roles.js.map +1 -0
- package/dist/plugin/.claude-plugin/plugin.json +11 -0
- package/dist/plugin/agents/auditor.md +30 -0
- package/dist/plugin/agents/general.md +24 -0
- package/dist/plugin/agents/orchestrator.md +32 -0
- package/dist/plugin/agents/reviewer.md +33 -0
- package/dist/plugin/settings.json +7 -0
- package/dist/plugin/statusline.sh +68 -0
- package/dist/plugin/themes/codedeck-ultra.json +68 -0
- package/dist/plugin/ultra.md +9 -0
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -81,8 +81,10 @@ The daemon owns the sessions. The CLI only follows events — closing the termin
|
|
|
81
81
|
|
|
82
82
|
| Command | Description |
|
|
83
83
|
|---------|-------------|
|
|
84
|
+
| `npx codedeck open [role] [--no-bypass] [--no-theme] [-- <claude args>]` | Open an opinionated Claude Code session with the CodeDeck plugin loaded |
|
|
85
|
+
| `npx codedeck setup` | Choose the model each installed agent should use |
|
|
84
86
|
| `npx codedeck doctor` | Check Node, Git, harnesses, daemon, and database |
|
|
85
|
-
| `npx codedeck run "<prompt>" --agent <id> [--model <m>] [--name <n>] [--worktree] [--bg|--detach]` | Start a session; blocks and follows logs by default |
|
|
87
|
+
| `npx codedeck run "<prompt>" --agent <id> [--model <m>] [--role <r>] [--name <n>] [--worktree] [--bg|--detach]` | Start a session; blocks and follows logs by default |
|
|
86
88
|
| `npx codedeck wait <id> [--json]` | Wait for a session to reach a terminal state without polling |
|
|
87
89
|
| `npx codedeck ps [--all] [--json]` | List recent sessions |
|
|
88
90
|
| `npx codedeck show <id> [--json]` | Show session details |
|
|
@@ -91,6 +93,71 @@ The daemon owns the sessions. The CLI only follows events — closing the termin
|
|
|
91
93
|
| `npx codedeck stop <id>` | Graceful interrupt → SIGTERM → SIGKILL |
|
|
92
94
|
| `npx codedeck diff <id> [--stat] [--json]` | Git diff against base commit |
|
|
93
95
|
|
|
96
|
+
## Open
|
|
97
|
+
|
|
98
|
+
`codedeck open` launches Claude Code already configured: the CodeDeck plugin, an appended system prompt, Opus 4.8 at `xhigh` effort, and permissions bypassed. Nothing is written to `~/.claude/`; the plugin is loaded for that session only, from the installed package.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npx codedeck open # asks which role, defaults to general
|
|
102
|
+
npx codedeck open reviewer # straight into a role
|
|
103
|
+
npx codedeck open -- --add-dir ../other-repo # anything after -- goes to claude verbatim
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Four roles. Each is an agent file in the plugin, and the restriction is a tool allowlist rather than an instruction:
|
|
107
|
+
|
|
108
|
+
| Role | Can write? | Can dispatch? | For |
|
|
109
|
+
|------|-----------|---------------|-----|
|
|
110
|
+
| `general` | yes | yes | ordinary work, done here |
|
|
111
|
+
| `orchestrator` | no `Edit`/`Write` | yes | building by spreading the work, proving it with `codedeck diff` |
|
|
112
|
+
| `auditor` | no `Edit`/`Write` | yes | reviewing a scope too large for one pass, sliced by dimension |
|
|
113
|
+
| `reviewer` | no `Edit`/`Write` | no | one pass, no fan-out, says what it did not cover |
|
|
114
|
+
|
|
115
|
+
The allowlist holds even with permissions bypassed, because it is orthogonal to permission bypass. It is not a sandbox either: every role keeps `Bash`, `general` included, so the three that lose `Edit` and `Write` can still write by redirection, and the rest of the boundary rests on the prompt.
|
|
116
|
+
|
|
117
|
+
Two things worth knowing before you edit an agent file. `--agent` layers on top of Claude Code's own system prompt rather than replacing it, and an agent file with no `tools:` key is unrestricted, which is how `general` keeps `Edit` and `Write`. And granting `Bash` drops `Grep` and `Glob` from the resolved toolset, whatever the file lists. Both are measured in [docs/harness-behaviour.md](docs/harness-behaviour.md), along with why `Bash` covering them is a guess about the reason and not part of the measurement.
|
|
118
|
+
|
|
119
|
+
`codedeck run --role <role>` gives a worker the same contract. `--agent` is Claude's flag and no other harness has it, so there the role body is prefixed to the prompt instead, frontmatter stripped. The text travels; the allowlist does not, so a codex or opencode worker is held to the role by prose alone.
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npx codedeck run "review the diff on this branch" --agent codex --role reviewer
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`--no-bypass` drops the bypass flag, `--no-theme` keeps the status line but drops the colours, and `--model`/`--effort`/`--resume`/`--worktree` override the defaults.
|
|
126
|
+
|
|
127
|
+
A launch carrying `-p`/`--print` answers once and exits, so it never asks anything. Checking for a terminal is not enough on its own, since a pty gives a TTY to scripts and CI runners alike.
|
|
128
|
+
|
|
129
|
+
### Choosing a model per agent
|
|
130
|
+
|
|
131
|
+
Launching never asks. Which model each harness should use is a question worth answering deliberately, not one to greet someone with, so it lives in its own command:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
npx codedeck setup
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
╔═╗╔═╗╔╦╗╔═╗╔╦╗╔═╗╔═╗╦╔═
|
|
139
|
+
║ ║ ║║║║╠═ ║║║╠═ ║ ╠╩╗
|
|
140
|
+
╚═╝╚═╝═╩╝╚═╝═╩╝╚═╝╚═╝╩ ╩
|
|
141
|
+
|
|
142
|
+
opencode ~ agente 3 de 4
|
|
143
|
+
|
|
144
|
+
filtrar: sonnet
|
|
145
|
+
opencode/claude-sonnet-4-6 opencode
|
|
146
|
+
› openrouter/anthropic/claude-sonnet-4-6 openrouter
|
|
147
|
+
zai-coding-plan/claude-sonnet-4-6 zai-coding-plan
|
|
148
|
+
3 de 614 move ^ v Enter escolhe ^G pula ^C sai
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Typing filters as you go, which is the answer to opencode proxying some 600 ids: nothing is capped and nothing is hidden. With the filter empty the list is grouped by provider with a count per group. Your current choice, or a default the harness actually declares, is pinned to the top and marked. Only the claude and codex drivers declare one, so opencode and omp pin nothing rather than dress an alphabetical accident up as a recommendation.
|
|
152
|
+
|
|
153
|
+
`^G` skips an agent and leaves its saved choice alone. `^C` walks out and writes nothing. Esc does neither, on purpose: it takes half a second to resolve and a fragmented arrow key arrives looking exactly like it.
|
|
154
|
+
|
|
155
|
+
An id the catalog does not list can still be typed. Enter asks once to confirm, and a second Enter writes it.
|
|
156
|
+
|
|
157
|
+
The catalog is cached for four hours. `codedeck setup --refresh` ignores the cache and rediscovers.
|
|
158
|
+
|
|
159
|
+
Precedence is `--model`, then the agent's saved model, then `defaultModel`, then the driver's own default, so `codedeck run --agent codex` picks up the codex choice without repeating the flag.
|
|
160
|
+
|
|
94
161
|
## Session
|
|
95
162
|
|
|
96
163
|
```ts
|
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import * as readline from "node:readline";
|
|
6
|
+
import { constants } from "node:os";
|
|
7
|
+
import { IpcClient } from "../../daemon/ipc.js";
|
|
8
|
+
import { loadConfig, resolveModel } from "../../config/config.js";
|
|
9
|
+
import { isInteractiveTerminal } from "./setup.js";
|
|
10
|
+
import { renderLogo } from "../ui.js";
|
|
11
|
+
import { getRegistry } from "../../drivers/registry.js";
|
|
12
|
+
import { detectBinary } from "../../drivers/helpers.js";
|
|
13
|
+
import { findClosestModel, getCachedOrDiscoverModels, modelNames, } from "../../core/models.js";
|
|
14
|
+
import { ROLES, parseRole, resolvePluginDir } from "../../core/roles.js";
|
|
15
|
+
export { ROLES, parseRole, resolvePluginDir };
|
|
16
|
+
const DEFAULT_MODEL = "claude-opus-4-8";
|
|
17
|
+
const DEFAULT_EFFORT = "xhigh";
|
|
18
|
+
const PLUGIN_NAME = "codedeck";
|
|
19
|
+
const CLAUDE_NOT_FOUND = "Claude Code was not found on PATH. Install Claude Code and ensure `claude` is available.";
|
|
20
|
+
const execFileAsync = promisify(execFile);
|
|
21
|
+
/**
|
|
22
|
+
* statusLine.command is handed to a shell, so an install directory carrying a
|
|
23
|
+
* space, a `$`, a backtick or a quote would break the command or inject into
|
|
24
|
+
* it. Single quotes take every one of those literally, and the only character
|
|
25
|
+
* that can end them is a quote, which is why that one is spliced.
|
|
26
|
+
*
|
|
27
|
+
* plugin/settings.json quotes the same script with double quotes on purpose and
|
|
28
|
+
* must keep doing so: it names the path through ${CLAUDE_PLUGIN_ROOT}, and
|
|
29
|
+
* single quotes would stop the expansion instead of protecting it.
|
|
30
|
+
*/
|
|
31
|
+
function shellQuote(value) {
|
|
32
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
33
|
+
}
|
|
34
|
+
function settingsArgument(pluginDir, flags) {
|
|
35
|
+
if (flags.theme !== false)
|
|
36
|
+
return path.join(pluginDir, "settings.json");
|
|
37
|
+
// Claude accepts an inline settings JSON value. Keep the status line while
|
|
38
|
+
// removing only the theme, without mutating the plugin's shared settings file.
|
|
39
|
+
return JSON.stringify({
|
|
40
|
+
statusLine: {
|
|
41
|
+
type: "command",
|
|
42
|
+
command: `bash ${shellQuote(path.join(pluginDir, "statusline.sh"))}`,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export function buildOpenArgs(role, flags, pluginDir, passthrough) {
|
|
47
|
+
const args = [
|
|
48
|
+
"--model",
|
|
49
|
+
flags.model ?? DEFAULT_MODEL,
|
|
50
|
+
"--effort",
|
|
51
|
+
flags.effort ?? DEFAULT_EFFORT,
|
|
52
|
+
...(flags.bypass !== false ? ["--dangerously-skip-permissions"] : []),
|
|
53
|
+
"--plugin-dir",
|
|
54
|
+
pluginDir,
|
|
55
|
+
"--append-system-prompt-file",
|
|
56
|
+
path.join(pluginDir, "ultra.md"),
|
|
57
|
+
"--settings",
|
|
58
|
+
settingsArgument(pluginDir, flags),
|
|
59
|
+
// `--agent` layers on top of Claude's own system prompt rather than
|
|
60
|
+
// replacing it, and an agent file with no `tools:` key inherits the whole
|
|
61
|
+
// toolset. So `general` carries its contract the same way the others do,
|
|
62
|
+
// with nothing taken away.
|
|
63
|
+
"--agent",
|
|
64
|
+
`${PLUGIN_NAME}:${role}`,
|
|
65
|
+
"-n",
|
|
66
|
+
`CodeDeck · ${role}`,
|
|
67
|
+
...(flags.resume ? ["--resume", flags.resume] : []),
|
|
68
|
+
...(flags.worktree ? ["-w"] : []),
|
|
69
|
+
...passthrough,
|
|
70
|
+
];
|
|
71
|
+
return args;
|
|
72
|
+
}
|
|
73
|
+
const MODEL_PREFIX = "--model=";
|
|
74
|
+
/**
|
|
75
|
+
* Claude honours the last --model on the line and the passthrough is appended
|
|
76
|
+
* last, so `open --model bad -- --model good` really launches "good". Checking
|
|
77
|
+
* anything but the last one grounds a launch that would have worked.
|
|
78
|
+
*
|
|
79
|
+
* Only the passthrough is scanned, never the built vector. That vector always
|
|
80
|
+
* opens with a --model pair, so scanning it could never answer "the passthrough
|
|
81
|
+
* overrode nothing", and a bare "--model" swallowed as another flag's value (as
|
|
82
|
+
* in `open --resume --model`) would be read as a model of its own.
|
|
83
|
+
*
|
|
84
|
+
* Known limit: a literal "--model" passed as the value of one of Claude's own
|
|
85
|
+
* flags still reads as an override. Telling that apart needs Claude's option
|
|
86
|
+
* arity, which CodeDeck does not have.
|
|
87
|
+
*/
|
|
88
|
+
export function effectiveModel(passthrough) {
|
|
89
|
+
for (let i = passthrough.length - 1; i >= 0; i--) {
|
|
90
|
+
const token = passthrough[i];
|
|
91
|
+
if (token.startsWith(MODEL_PREFIX))
|
|
92
|
+
return token.slice(MODEL_PREFIX.length);
|
|
93
|
+
if (i > 0 && passthrough[i - 1] === "--model")
|
|
94
|
+
return token;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export function sanitizeEnv(env) {
|
|
98
|
+
const sanitized = { ...env };
|
|
99
|
+
delete sanitized.CLAUDE_CODE_CHILD_SESSION;
|
|
100
|
+
return sanitized;
|
|
101
|
+
}
|
|
102
|
+
export function renderBanner(role, model, effort) {
|
|
103
|
+
return `${renderLogo(`${role} · ${model} · ${effort}`)}\n`;
|
|
104
|
+
}
|
|
105
|
+
function selectRole() {
|
|
106
|
+
const rl = readline.createInterface({
|
|
107
|
+
input: process.stdin,
|
|
108
|
+
output: process.stdout,
|
|
109
|
+
});
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
let settled = false;
|
|
112
|
+
const finish = (role) => {
|
|
113
|
+
if (settled)
|
|
114
|
+
return;
|
|
115
|
+
settled = true;
|
|
116
|
+
rl.close();
|
|
117
|
+
resolve(role);
|
|
118
|
+
};
|
|
119
|
+
// Ctrl+D closes the interface without ever answering, so without this the
|
|
120
|
+
// promise stays pending and the command hangs. It is a walk-out, not a
|
|
121
|
+
// choice: EOF here used to launch a permission-bypassed session the user
|
|
122
|
+
// never picked, and the model wizard already treats the same keystroke as
|
|
123
|
+
// leaving. Reaching this needs a TTY, so a piped launch cannot trip it.
|
|
124
|
+
rl.once("close", () => {
|
|
125
|
+
if (settled)
|
|
126
|
+
return;
|
|
127
|
+
settled = true;
|
|
128
|
+
reject(new Error("Role selection was interrupted; nothing was launched."));
|
|
129
|
+
});
|
|
130
|
+
const ask = () => {
|
|
131
|
+
rl.question(`Role [general] (${ROLES.join("/")}): `, (answer) => {
|
|
132
|
+
const role = parseRole(answer || "general");
|
|
133
|
+
if (role) {
|
|
134
|
+
finish(role);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
process.stderr.write(`Invalid role. Available roles: ${ROLES.join(", ")}\n`);
|
|
138
|
+
ask();
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
ask();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* `claude -p` answers one prompt and exits, so there is no session to choose a
|
|
146
|
+
* role for. A terminal check alone does not catch this: under a pty (CI scripts,
|
|
147
|
+
* `script`, most CI runners) stdout is a TTY and the prompt would block forever.
|
|
148
|
+
*/
|
|
149
|
+
export function isNonInteractiveLaunch(passthrough) {
|
|
150
|
+
return passthrough.some((arg) => arg === "-p" || arg === "--print");
|
|
151
|
+
}
|
|
152
|
+
function resolveRole(input, interactive) {
|
|
153
|
+
if (input !== undefined) {
|
|
154
|
+
const role = parseRole(input);
|
|
155
|
+
if (!role) {
|
|
156
|
+
return Promise.reject(new Error(`Invalid role "${input}". Available roles: ${ROLES.join(", ")}`));
|
|
157
|
+
}
|
|
158
|
+
return Promise.resolve(role);
|
|
159
|
+
}
|
|
160
|
+
if (!interactive || !isInteractiveTerminal())
|
|
161
|
+
return Promise.resolve("general");
|
|
162
|
+
return selectRole();
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Unknown options have to be allowed so the passthrough can carry Claude's own
|
|
166
|
+
* flags, but that acceptance must stop at the separator. Without this check a
|
|
167
|
+
* typo in a safety flag is silent: `open --no-bypas` looks like it turned the
|
|
168
|
+
* permission bypass off and launches with it still on.
|
|
169
|
+
*
|
|
170
|
+
* The rule enforced is commander's own: reject exactly what commander would
|
|
171
|
+
* treat as unknown under allowUnknownOption(). Looser lets a dropped flag
|
|
172
|
+
* through, which is the bug this exists to catch; stricter refuses a command
|
|
173
|
+
* line commander parses happily.
|
|
174
|
+
*
|
|
175
|
+
* Returns the operands, meaning the tokens commander did not swallow as an
|
|
176
|
+
* option or an option's value, so the caller can tell a role from a value that
|
|
177
|
+
* happens to spell one.
|
|
178
|
+
*
|
|
179
|
+
* The known set is read from commander's registry so it cannot drift from the
|
|
180
|
+
* declared options. Help is the exception: commander keeps its help option out
|
|
181
|
+
* of `command.options`, so those two spellings are mirrored from the
|
|
182
|
+
* `.helpOption()` call in src/cli/index.ts and change with it.
|
|
183
|
+
*/
|
|
184
|
+
export function scanOptions(tokens, command) {
|
|
185
|
+
const takesValue = new Map([
|
|
186
|
+
["-h", false],
|
|
187
|
+
["--help", false],
|
|
188
|
+
]);
|
|
189
|
+
for (const option of command.options) {
|
|
190
|
+
const wantsValue = option.required || option.optional;
|
|
191
|
+
if (option.short)
|
|
192
|
+
takesValue.set(option.short, wantsValue);
|
|
193
|
+
if (option.long)
|
|
194
|
+
takesValue.set(option.long, wantsValue);
|
|
195
|
+
}
|
|
196
|
+
const operands = [];
|
|
197
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
198
|
+
const token = tokens[i];
|
|
199
|
+
if (!token.startsWith("-") || token === "-") {
|
|
200
|
+
operands.push(token);
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const separator = token.indexOf("=");
|
|
204
|
+
const name = separator >= 0 ? token.slice(0, separator) : token;
|
|
205
|
+
const wantsValue = takesValue.get(name);
|
|
206
|
+
if (wantsValue === undefined) {
|
|
207
|
+
throw new Error(`Unknown option "${name}" for codedeck open. Options for Claude go after "--".`);
|
|
208
|
+
}
|
|
209
|
+
// Commander honours "=" only on options declared with a value and drops the
|
|
210
|
+
// whole token otherwise, so `--no-bypass=false` would read as accepted and
|
|
211
|
+
// launch with the bypass still on.
|
|
212
|
+
if (separator >= 0 && !wantsValue) {
|
|
213
|
+
throw new Error(`Option "${name}" for codedeck open takes no value.`);
|
|
214
|
+
}
|
|
215
|
+
// The next token belongs to this option even when it looks like a flag,
|
|
216
|
+
// which is what keeps `--model -weird` from reading as an unknown option.
|
|
217
|
+
if (wantsValue && separator < 0)
|
|
218
|
+
i += 1;
|
|
219
|
+
}
|
|
220
|
+
return operands;
|
|
221
|
+
}
|
|
222
|
+
function getInvocation(command, roleArg) {
|
|
223
|
+
const rawArgs = command.parent?.rawArgs ?? [];
|
|
224
|
+
// Searching forward from the executable and script entries, never backwards:
|
|
225
|
+
// `open -- --print open` would otherwise match the passthrough word instead
|
|
226
|
+
// of the command and lose the separator behind it.
|
|
227
|
+
const commandIndex = rawArgs.indexOf(command.name(), 2);
|
|
228
|
+
const separatorIndex = commandIndex >= 0 ? rawArgs.indexOf("--", commandIndex + 1) : -1;
|
|
229
|
+
const beforeSeparator = commandIndex >= 0
|
|
230
|
+
? rawArgs.slice(commandIndex + 1, separatorIndex >= 0 ? separatorIndex : undefined)
|
|
231
|
+
: [];
|
|
232
|
+
const operands = scanOptions(beforeSeparator, command);
|
|
233
|
+
if (separatorIndex >= 0) {
|
|
234
|
+
// Commander folds the separator away, so roleArg can just as easily have
|
|
235
|
+
// come from the passthrough. It counts as a role only when it really stood
|
|
236
|
+
// before the separator as an operand, never as some option's value:
|
|
237
|
+
// `open --resume reviewer -- reviewer` asks for no role at all.
|
|
238
|
+
const explicitRole = roleArg !== undefined && operands.includes(roleArg) ? roleArg : undefined;
|
|
239
|
+
return {
|
|
240
|
+
roleInput: explicitRole,
|
|
241
|
+
passthrough: rawArgs.slice(separatorIndex + 1),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
const parsedArgs = command.args.slice();
|
|
245
|
+
if (roleArg !== undefined && parsedArgs[0] === roleArg) {
|
|
246
|
+
parsedArgs.shift();
|
|
247
|
+
}
|
|
248
|
+
if (parsedArgs.length > 0) {
|
|
249
|
+
throw new Error('Arguments for Claude must follow "--" so CodeDeck can forward them verbatim.');
|
|
250
|
+
}
|
|
251
|
+
return { roleInput: roleArg, passthrough: [] };
|
|
252
|
+
}
|
|
253
|
+
function assertPluginDirectory(pluginDir) {
|
|
254
|
+
try {
|
|
255
|
+
if (fs.statSync(pluginDir).isDirectory())
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
catch { }
|
|
259
|
+
throw new Error(`CodeDeck plugin directory not found at ${pluginDir}. Rebuild or reinstall CodeDeck before running open.`);
|
|
260
|
+
}
|
|
261
|
+
function currentWorkingDirectory() {
|
|
262
|
+
try {
|
|
263
|
+
const cwd = process.cwd();
|
|
264
|
+
if (fs.statSync(cwd).isDirectory())
|
|
265
|
+
return cwd;
|
|
266
|
+
}
|
|
267
|
+
catch { }
|
|
268
|
+
throw new Error("Cannot launch Claude Code: the current working directory no longer exists.");
|
|
269
|
+
}
|
|
270
|
+
function errorDetails(error) {
|
|
271
|
+
if (typeof error !== "object" || error === null)
|
|
272
|
+
return { text: String(error) };
|
|
273
|
+
const value = error;
|
|
274
|
+
const text = [value.stderr, value.stdout, value.message]
|
|
275
|
+
.filter((part) => typeof part === "string" && part.length > 0)
|
|
276
|
+
.join("\n");
|
|
277
|
+
return {
|
|
278
|
+
code: typeof value.code === "string" ? value.code : undefined,
|
|
279
|
+
text: text || String(error),
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* What the catalog can say about a model. Reachable is not the same as allowed:
|
|
284
|
+
* the catalog lists what Claude Code knows about, never what this account may
|
|
285
|
+
* use, so an entitlement problem only surfaces at launch (see launchClaude).
|
|
286
|
+
*/
|
|
287
|
+
const catalogWarning = (model, state) => `Warning: Claude model catalog is ${state}; continuing with "${model}".`;
|
|
288
|
+
/**
|
|
289
|
+
* Pure so all three outcomes are testable without touching the disk cache or
|
|
290
|
+
* spawning a harness.
|
|
291
|
+
*/
|
|
292
|
+
export function judgeModel(model, catalogs, fromConfig) {
|
|
293
|
+
const keepGoing = (reason) => ({
|
|
294
|
+
kind: "unknown-catalog",
|
|
295
|
+
warning: catalogWarning(model, `unavailable${reason}`),
|
|
296
|
+
});
|
|
297
|
+
const catalog = catalogs?.find((item) => item.agent === "claude");
|
|
298
|
+
if (!catalog || !catalog.available || catalog.error) {
|
|
299
|
+
return keepGoing(catalog?.error ? ` (${catalog.error})` : "");
|
|
300
|
+
}
|
|
301
|
+
const candidates = modelNames(catalog);
|
|
302
|
+
if (candidates.length === 0) {
|
|
303
|
+
return { kind: "unknown-catalog", warning: catalogWarning(model, "empty") };
|
|
304
|
+
}
|
|
305
|
+
if (candidates.includes(model))
|
|
306
|
+
return { kind: "ok" };
|
|
307
|
+
const suggestion = findClosestModel(model, candidates);
|
|
308
|
+
const hint = suggestion ? ` Did you mean "${suggestion}"?` : " No close model was found.";
|
|
309
|
+
// A model can leave the catalog on its own, with nobody having typed it
|
|
310
|
+
// wrong, and `needsModelSetup` never asks again, so the way out has to be
|
|
311
|
+
// spelled out.
|
|
312
|
+
const recovery = fromConfig ? " Run `codedeck setup` to pick another." : "";
|
|
313
|
+
return { kind: "rejected", error: `Model "${model}" is not in the Claude catalog.${hint}${recovery}` };
|
|
314
|
+
}
|
|
315
|
+
async function preflightModel(model, fromConfig) {
|
|
316
|
+
let catalogs;
|
|
317
|
+
try {
|
|
318
|
+
catalogs = await getCachedOrDiscoverModels(getRegistry(), { agent: "claude" });
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
// A catalog that cannot be reached is not evidence against the model, so
|
|
322
|
+
// this warns and lets the launch decide.
|
|
323
|
+
const details = errorDetails(error);
|
|
324
|
+
console.warn(catalogWarning(model, `unavailable (${details.text})`));
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const verdict = judgeModel(model, catalogs, fromConfig);
|
|
328
|
+
if (verdict.kind === "ok")
|
|
329
|
+
return;
|
|
330
|
+
if (verdict.kind === "unknown-catalog") {
|
|
331
|
+
console.warn(verdict.warning);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
throw new Error(verdict.error);
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Returns the resolved path rather than a boolean so everything downstream
|
|
338
|
+
* launches the exact binary that was checked, instead of asking PATH again and
|
|
339
|
+
* hoping it answers the same way.
|
|
340
|
+
*/
|
|
341
|
+
async function resolveClaudeBinary() {
|
|
342
|
+
// detectBinary reports failure in its result and never rejects, so there is
|
|
343
|
+
// nothing here to catch.
|
|
344
|
+
const installation = await detectBinary("claude");
|
|
345
|
+
if (!installation.installed || !installation.path) {
|
|
346
|
+
throw new Error(CLAUDE_NOT_FOUND);
|
|
347
|
+
}
|
|
348
|
+
return installation.path;
|
|
349
|
+
}
|
|
350
|
+
async function assertSystemPromptFlagSupported(claudeBin, cwd) {
|
|
351
|
+
try {
|
|
352
|
+
await execFileAsync(claudeBin, ["--append-system-prompt-file"], {
|
|
353
|
+
cwd,
|
|
354
|
+
env: sanitizeEnv(process.env),
|
|
355
|
+
timeout: 5000,
|
|
356
|
+
maxBuffer: 1024 * 1024,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
const details = errorDetails(error);
|
|
361
|
+
if (details.code === "ENOENT") {
|
|
362
|
+
throw new Error(CLAUDE_NOT_FOUND);
|
|
363
|
+
}
|
|
364
|
+
if (/unknown option|unknown argument|unrecognized option|invalid option/i.test(details.text)) {
|
|
365
|
+
throw new Error("This Claude Code version does not support --append-system-prompt-file. Upgrade Claude Code and retry.");
|
|
366
|
+
}
|
|
367
|
+
// A supported Commander option reports a missing argument for this probe.
|
|
368
|
+
// Other probe failures are left to the real launch, which can provide the
|
|
369
|
+
// harness-specific diagnostic without blocking a valid installation.
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Only stderr is piped, and only because Claude Code reports an unusable model
|
|
374
|
+
* there as a tagged line rather than a distinct exit code. stdout stays
|
|
375
|
+
* inherited so the TUI paints straight to the terminal, which also means
|
|
376
|
+
* `child.stdout` is null and there is nothing to relay.
|
|
377
|
+
*/
|
|
378
|
+
function relayStderr(child, output) {
|
|
379
|
+
const stream = child.stderr;
|
|
380
|
+
if (!stream)
|
|
381
|
+
return;
|
|
382
|
+
stream.setEncoding?.("utf8");
|
|
383
|
+
stream.on("data", (chunk) => {
|
|
384
|
+
output.value += typeof chunk === "string" ? chunk : chunk.toString();
|
|
385
|
+
process.stderr.write(chunk);
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* A signalled death carries no exit code, and collapsing it to 1 tells a caller
|
|
390
|
+
* the session failed rather than that it was killed. Shells report this as
|
|
391
|
+
* 128 plus the signal number, so Ctrl+C stays 130 and a SIGKILL stays 137.
|
|
392
|
+
*/
|
|
393
|
+
export function exitCodeFor(code, signal) {
|
|
394
|
+
if (code !== null)
|
|
395
|
+
return code;
|
|
396
|
+
if (!signal)
|
|
397
|
+
return 1;
|
|
398
|
+
const number = constants.signals[signal];
|
|
399
|
+
return typeof number === "number" ? 128 + number : 1;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* The catalog knows which models exist, not which ones this account may use, so
|
|
403
|
+
* an entitlement problem can only be read off the launch itself. Claude Code
|
|
404
|
+
* reports it as a tagged error rather than a distinct exit code.
|
|
405
|
+
*/
|
|
406
|
+
export function entitlementError(model, output) {
|
|
407
|
+
const tag = /\[claude-code:unrecognized_model\]\s*(\{.*\})?/i.exec(output);
|
|
408
|
+
if (!tag)
|
|
409
|
+
return undefined;
|
|
410
|
+
// The passthrough can carry its own --model, which wins over the one CodeDeck
|
|
411
|
+
// resolved, so the name in the payload is the one that was actually rejected.
|
|
412
|
+
let rejected = model;
|
|
413
|
+
if (tag[1]) {
|
|
414
|
+
try {
|
|
415
|
+
const payload = JSON.parse(tag[1]);
|
|
416
|
+
if (typeof payload.model === "string" && payload.model)
|
|
417
|
+
rejected = payload.model;
|
|
418
|
+
}
|
|
419
|
+
catch { }
|
|
420
|
+
}
|
|
421
|
+
return `Claude Code rejected model "${rejected}" because this account is not entitled to it. Check the Claude plan or model access for the account.`;
|
|
422
|
+
}
|
|
423
|
+
function launchClaude(claudeBin, model, args, cwd) {
|
|
424
|
+
return new Promise((resolve, reject) => {
|
|
425
|
+
let settled = false;
|
|
426
|
+
const output = { value: "" };
|
|
427
|
+
const child = spawn(claudeBin, args, {
|
|
428
|
+
cwd,
|
|
429
|
+
env: sanitizeEnv(process.env),
|
|
430
|
+
stdio: ["inherit", "inherit", "pipe"],
|
|
431
|
+
});
|
|
432
|
+
relayStderr(child, output);
|
|
433
|
+
child.once("error", (error) => {
|
|
434
|
+
if (settled)
|
|
435
|
+
return;
|
|
436
|
+
settled = true;
|
|
437
|
+
const details = errorDetails(error);
|
|
438
|
+
if (details.code === "ENOENT") {
|
|
439
|
+
reject(new Error(CLAUDE_NOT_FOUND));
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
reject(error);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
child.once("close", (code, signal) => {
|
|
446
|
+
if (settled)
|
|
447
|
+
return;
|
|
448
|
+
settled = true;
|
|
449
|
+
const entitlement = entitlementError(model, output.value);
|
|
450
|
+
if (entitlement) {
|
|
451
|
+
reject(new Error(entitlement));
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
process.exitCode = exitCodeFor(code, signal);
|
|
455
|
+
resolve();
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
export function registerOpenCommand(program) {
|
|
460
|
+
program
|
|
461
|
+
.command("open [role]")
|
|
462
|
+
.description("Open a configured Claude Code session")
|
|
463
|
+
.option("--model <model>", `model to use (default: ${DEFAULT_MODEL})`)
|
|
464
|
+
.option("--effort <level>", `reasoning effort (default: ${DEFAULT_EFFORT})`)
|
|
465
|
+
.option("--resume <session>", "resume a Claude Code session")
|
|
466
|
+
.option("--worktree", "ask Claude Code to create an isolated worktree")
|
|
467
|
+
.option("--no-bypass", "do not skip Claude Code permission prompts")
|
|
468
|
+
.option("--no-theme", "keep the CodeDeck status line without applying its theme")
|
|
469
|
+
.allowUnknownOption()
|
|
470
|
+
.action(async (roleArg, opts, command) => {
|
|
471
|
+
const invocation = getInvocation(command, roleArg);
|
|
472
|
+
const interactive = !isNonInteractiveLaunch(invocation.passthrough);
|
|
473
|
+
const role = await resolveRole(invocation.roleInput, interactive);
|
|
474
|
+
const pluginDir = resolvePluginDir();
|
|
475
|
+
assertPluginDirectory(pluginDir);
|
|
476
|
+
const cwd = currentWorkingDirectory();
|
|
477
|
+
const client = new IpcClient();
|
|
478
|
+
await client.ensureDaemonStarted();
|
|
479
|
+
// Launching never opens the wizard. Asking a model per harness was the
|
|
480
|
+
// wrong question to greet someone with, and `codedeck setup` is the place
|
|
481
|
+
// to answer it deliberately.
|
|
482
|
+
const config = loadConfig();
|
|
483
|
+
const resolved = resolveModel("claude", opts.model, config) ?? DEFAULT_MODEL;
|
|
484
|
+
const args = buildOpenArgs(role, { ...opts, model: resolved }, pluginDir, invocation.passthrough);
|
|
485
|
+
const model = effectiveModel(invocation.passthrough) ?? resolved;
|
|
486
|
+
// It came from config only when nobody typed a model just now, neither by
|
|
487
|
+
// flag nor by passthrough, and the config actually had one.
|
|
488
|
+
const fromConfig = opts.model === undefined &&
|
|
489
|
+
effectiveModel(invocation.passthrough) === undefined &&
|
|
490
|
+
resolveModel("claude", undefined, config) !== undefined;
|
|
491
|
+
await preflightModel(model, fromConfig);
|
|
492
|
+
const claudeBin = await resolveClaudeBinary();
|
|
493
|
+
await assertSystemPromptFlagSupported(claudeBin, cwd);
|
|
494
|
+
process.stdout.write(renderBanner(role, model, opts.effort ?? DEFAULT_EFFORT));
|
|
495
|
+
await launchClaude(claudeBin, model, args, cwd);
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../../src/cli/commands/open.ts"],"names":[],"mappings":"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"}
|