agentxchain 2.149.1 → 2.149.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/README.md +1 -1
- package/package.json +1 -1
- package/src/commands/doctor.js +4 -4
- package/src/commands/init.js +1 -1
- package/src/lib/adapters/local-cli-adapter.js +2 -1
- package/src/lib/claude-local-auth.js +183 -7
- package/src/lib/connector-probe.js +12 -23
- package/src/lib/connector-validate.js +5 -5
- package/src/templates/governed/enterprise-app.json +1 -1
- package/src/templates/governed/full-local-cli.json +4 -4
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ agentxchain step --role pm
|
|
|
89
89
|
|
|
90
90
|
If you skipped `--goal` during scaffold, run `agentxchain config --set project.goal "Build an API change planner for release teams"` before the first governed turn instead of re-running init in place.
|
|
91
91
|
|
|
92
|
-
The default governed dev runtime is `claude --print --dangerously-skip-permissions` with stdin prompt delivery. The non-interactive governed path needs write access, so do not pretend
|
|
92
|
+
The default governed dev runtime is `claude --print --dangerously-skip-permissions --bare` with stdin prompt delivery. The non-interactive governed path needs write access and env-based auth, so do not pretend plain `claude --print` is sufficient for unattended implementation turns. If your local coding agent uses a different launch contract, set it during scaffold creation:
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
95
|
agentxchain init --governed --dir my-agentxchain-project --dev-command ./scripts/dev-agent.sh --dev-prompt-transport dispatch_bundle_only -y
|
package/package.json
CHANGED
package/src/commands/doctor.js
CHANGED
|
@@ -59,7 +59,7 @@ export async function doctorCommand(opts = {}) {
|
|
|
59
59
|
|
|
60
60
|
// ── Governed (v4) Doctor ────────────────────────────────────────────────────
|
|
61
61
|
|
|
62
|
-
function governedDoctor(root, rawConfig, opts) {
|
|
62
|
+
async function governedDoctor(root, rawConfig, opts) {
|
|
63
63
|
const checks = [];
|
|
64
64
|
const cliVersionHealth = getCliVersionHealth();
|
|
65
65
|
let stateRunId = null;
|
|
@@ -93,7 +93,7 @@ function governedDoctor(root, rawConfig, opts) {
|
|
|
93
93
|
const runtimes = (normalized && normalized.runtimes) || rawConfig.runtimes || {};
|
|
94
94
|
const rolesByRuntime = buildRolesByRuntime(normalized?.roles || {});
|
|
95
95
|
for (const [rtId, rt] of Object.entries(runtimes)) {
|
|
96
|
-
const check = checkRuntimeReachable(root, rtId, rt, rolesByRuntime[rtId] || []);
|
|
96
|
+
const check = await checkRuntimeReachable(root, rtId, rt, rolesByRuntime[rtId] || []);
|
|
97
97
|
checks.push(check);
|
|
98
98
|
}
|
|
99
99
|
const connectorProbe = getConnectorProbeRecommendation(runtimes);
|
|
@@ -488,7 +488,7 @@ function buildCliVersionCheck(cliVersionHealth) {
|
|
|
488
488
|
};
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
-
function checkRuntimeReachable(root, rtId, rt, boundRoleEntries = []) {
|
|
491
|
+
async function checkRuntimeReachable(root, rtId, rt, boundRoleEntries = []) {
|
|
492
492
|
const base = { id: `runtime_${rtId}`, name: `Runtime: ${rtId}` };
|
|
493
493
|
|
|
494
494
|
if (!rt || !rt.type) {
|
|
@@ -502,7 +502,7 @@ function checkRuntimeReachable(root, rtId, rt, boundRoleEntries = []) {
|
|
|
502
502
|
case 'local_cli': {
|
|
503
503
|
const probe = probeRuntimeSpawnContext(root, rt, { runtimeId: rtId });
|
|
504
504
|
if (probe.ok) {
|
|
505
|
-
const claudeAuthIssue = getClaudeSubprocessAuthIssue(rt);
|
|
505
|
+
const claudeAuthIssue = await getClaudeSubprocessAuthIssue(rt);
|
|
506
506
|
if (claudeAuthIssue) {
|
|
507
507
|
return attachRuntimeContract({
|
|
508
508
|
...base,
|
package/src/commands/init.js
CHANGED
|
@@ -98,7 +98,7 @@ const GOVERNED_ROLES = {
|
|
|
98
98
|
|
|
99
99
|
const DEFAULT_GOVERNED_LOCAL_DEV_RUNTIME = Object.freeze({
|
|
100
100
|
type: 'local_cli',
|
|
101
|
-
command: ['claude', '--print', '--dangerously-skip-permissions'],
|
|
101
|
+
command: ['claude', '--print', '--dangerously-skip-permissions', '--bare'],
|
|
102
102
|
cwd: '.',
|
|
103
103
|
prompt_transport: 'stdin',
|
|
104
104
|
});
|
|
@@ -128,13 +128,14 @@ export async function dispatchLocalCli(root, state, config, options = {}) {
|
|
|
128
128
|
const spawnEnv = { ...process.env, AGENTXCHAIN_TURN_ID: turn.turn_id };
|
|
129
129
|
const stdinBytes = transport === 'stdin' ? Buffer.byteLength(fullPrompt, 'utf8') : 0;
|
|
130
130
|
const diagnosticArgs = redactPromptArgs(args, fullPrompt, transport);
|
|
131
|
-
const claudeAuthIssue = getClaudeSubprocessAuthIssue(runtime, spawnEnv);
|
|
131
|
+
const claudeAuthIssue = await getClaudeSubprocessAuthIssue(runtime, spawnEnv);
|
|
132
132
|
|
|
133
133
|
if (claudeAuthIssue) {
|
|
134
134
|
appendDiagnostic(logs, 'claude_auth_preflight_failed', {
|
|
135
135
|
runtime_id: runtimeId,
|
|
136
136
|
turn_id: turn.turn_id,
|
|
137
137
|
auth_env_present: claudeAuthIssue.auth_env_present,
|
|
138
|
+
smoke_probe: claudeAuthIssue.smoke_probe,
|
|
138
139
|
recommendation: claudeAuthIssue.fix,
|
|
139
140
|
});
|
|
140
141
|
return {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
|
|
1
3
|
const CLAUDE_ENV_AUTH_KEYS = [
|
|
2
4
|
'ANTHROPIC_API_KEY',
|
|
3
5
|
'CLAUDE_API_KEY',
|
|
@@ -6,6 +8,9 @@ const CLAUDE_ENV_AUTH_KEYS = [
|
|
|
6
8
|
'CLAUDE_CODE_USE_BEDROCK',
|
|
7
9
|
];
|
|
8
10
|
|
|
11
|
+
const DEFAULT_SMOKE_PROBE_TIMEOUT_MS = 10_000;
|
|
12
|
+
const DEFAULT_SMOKE_PROBE_STDIN = 'ok';
|
|
13
|
+
|
|
9
14
|
function normalizeCommandTokens(runtime) {
|
|
10
15
|
if (Array.isArray(runtime?.command)) {
|
|
11
16
|
return runtime.command.flatMap((element) =>
|
|
@@ -41,7 +46,26 @@ export function hasClaudeEnvAuth(env = process.env) {
|
|
|
41
46
|
return Object.values(getClaudeEnvAuthPresence(env)).some(Boolean);
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
function buildClaudeSubprocessAuthIssue(env, smokeProbe = null) {
|
|
50
|
+
const auth_env_present = getClaudeEnvAuthPresence(env);
|
|
51
|
+
return {
|
|
52
|
+
auth_env_present,
|
|
53
|
+
smoke_probe: smokeProbe,
|
|
54
|
+
detail: 'Claude local_cli runtime has no env-based auth and is missing "--bare"; non-interactive subprocesses can hang on macOS keychain reads.',
|
|
55
|
+
fix: 'Export ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN before running AgentXchain, or add "--bare" to the Claude command if you intentionally want env-only auth.',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function resolveSmokeProbeTimeoutMs(env, options = {}) {
|
|
60
|
+
if (Number.isFinite(options?.timeoutMs) && options.timeoutMs > 0) {
|
|
61
|
+
return options.timeoutMs;
|
|
62
|
+
}
|
|
63
|
+
const raw = env?.AGENTXCHAIN_CLAUDE_AUTH_PROBE_TIMEOUT_MS;
|
|
64
|
+
const parsed = Number.parseInt(raw, 10);
|
|
65
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_SMOKE_PROBE_TIMEOUT_MS;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function getClaudeSubprocessAuthIssue(runtime, env = process.env, options = {}) {
|
|
45
69
|
if (!isClaudeLocalCliRuntime(runtime)) {
|
|
46
70
|
return null;
|
|
47
71
|
}
|
|
@@ -50,12 +74,164 @@ export function getClaudeSubprocessAuthIssue(runtime, env = process.env) {
|
|
|
50
74
|
return null;
|
|
51
75
|
}
|
|
52
76
|
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
77
|
+
const smokeProbe = await runClaudeSmokeProbe({
|
|
78
|
+
runtime,
|
|
79
|
+
env,
|
|
80
|
+
timeoutMs: resolveSmokeProbeTimeoutMs(env, options),
|
|
81
|
+
stdinPayload: options?.stdinPayload,
|
|
82
|
+
spawnImpl: options?.spawnImpl,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (smokeProbe.kind === 'stdout_observed' || smokeProbe.kind === 'spawn_error' || smokeProbe.kind === 'skipped') {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (smokeProbe.kind === 'hang' || smokeProbe.kind === 'exit_nonzero' || smokeProbe.kind === 'stderr_only') {
|
|
90
|
+
return buildClaudeSubprocessAuthIssue(env, smokeProbe);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Bounded smoke probe that spawns the runtime's actual Claude command with a
|
|
98
|
+
* tiny prompt on stdin and a watchdog. Returns a classification:
|
|
99
|
+
*
|
|
100
|
+
* { kind: 'stdout_observed' } — real stdout arrived before watchdog;
|
|
101
|
+
* the setup is NOT hanging on auth.
|
|
102
|
+
* { kind: 'hang', elapsed_ms } — watchdog fired with no stdout/stderr
|
|
103
|
+
* bytes; the keychain-hang shape (BUG-54).
|
|
104
|
+
* { kind: 'stderr_only', ... } — process wrote stderr but no stdout
|
|
105
|
+
* before watchdog (auth error or similar).
|
|
106
|
+
* { kind: 'exit_nonzero', ... } — process exited non-zero with no stdout
|
|
107
|
+
* (explicit auth failure — not a hang).
|
|
108
|
+
* { kind: 'spawn_error', ... } — spawn itself failed (ENOENT / EPERM).
|
|
109
|
+
* { kind: 'skipped', reason } — probe disabled or unavailable.
|
|
110
|
+
*
|
|
111
|
+
* This is the positive-case-testable alternative to the static shape-check in
|
|
112
|
+
* `getClaudeSubprocessAuthIssue`: it observes what the subprocess actually
|
|
113
|
+
* does rather than predicting what it *might* do from config shape alone.
|
|
114
|
+
*
|
|
115
|
+
* Added 2026-04-21 for the BUG-56 false-positive fix. See
|
|
116
|
+
* `.planning/BUG_56_FALSE_POSITIVE_RETRO.md` for the decision trail.
|
|
117
|
+
*
|
|
118
|
+
* @param {{ runtime: object, env?: object, timeoutMs?: number, stdinPayload?: string, spawnImpl?: Function }} opts
|
|
119
|
+
* @returns {Promise<object>}
|
|
120
|
+
*/
|
|
121
|
+
export async function runClaudeSmokeProbe(opts) {
|
|
122
|
+
const runtime = opts?.runtime ?? null;
|
|
123
|
+
const env = opts?.env ?? process.env;
|
|
124
|
+
const timeoutMs = Number.isFinite(opts?.timeoutMs) ? opts.timeoutMs : DEFAULT_SMOKE_PROBE_TIMEOUT_MS;
|
|
125
|
+
const stdinPayload = typeof opts?.stdinPayload === 'string' ? opts.stdinPayload : DEFAULT_SMOKE_PROBE_STDIN;
|
|
126
|
+
const spawnImpl = typeof opts?.spawnImpl === 'function' ? opts.spawnImpl : spawn;
|
|
127
|
+
|
|
128
|
+
if (!isClaudeLocalCliRuntime(runtime)) {
|
|
129
|
+
return { kind: 'skipped', reason: 'not_claude_local_cli' };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const tokens = normalizeCommandTokens(runtime);
|
|
133
|
+
if (tokens.length === 0) {
|
|
134
|
+
return { kind: 'skipped', reason: 'empty_command' };
|
|
135
|
+
}
|
|
136
|
+
const [command, ...args] = tokens;
|
|
137
|
+
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
let child;
|
|
140
|
+
try {
|
|
141
|
+
child = spawnImpl(command, args, {
|
|
142
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
143
|
+
env,
|
|
144
|
+
});
|
|
145
|
+
} catch (error) {
|
|
146
|
+
resolve({
|
|
147
|
+
kind: 'spawn_error',
|
|
148
|
+
errno: error?.errno ?? null,
|
|
149
|
+
code: error?.code ?? null,
|
|
150
|
+
message: error?.message ?? String(error),
|
|
151
|
+
});
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!child || typeof child.on !== 'function') {
|
|
156
|
+
resolve({ kind: 'spawn_error', code: 'NO_CHILD_HANDLE', message: 'spawn returned no child handle' });
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const start = Date.now();
|
|
161
|
+
let stdoutBytes = 0;
|
|
162
|
+
let stderrBytes = 0;
|
|
163
|
+
let stderrBuf = '';
|
|
164
|
+
let settled = false;
|
|
165
|
+
|
|
166
|
+
const finish = (result) => {
|
|
167
|
+
if (settled) return;
|
|
168
|
+
settled = true;
|
|
169
|
+
try { child.kill('SIGTERM'); } catch { /* ignore */ }
|
|
170
|
+
resolve(result);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const watchdog = setTimeout(() => {
|
|
174
|
+
const elapsed_ms = Date.now() - start;
|
|
175
|
+
if (stdoutBytes > 0) {
|
|
176
|
+
finish({ kind: 'stdout_observed', elapsed_ms });
|
|
177
|
+
} else if (stderrBytes > 0) {
|
|
178
|
+
finish({ kind: 'stderr_only', elapsed_ms, stderr_snippet: stderrBuf.slice(0, 500) });
|
|
179
|
+
} else {
|
|
180
|
+
finish({ kind: 'hang', elapsed_ms });
|
|
181
|
+
}
|
|
182
|
+
}, timeoutMs);
|
|
183
|
+
if (typeof watchdog.unref === 'function') watchdog.unref();
|
|
184
|
+
|
|
185
|
+
child.stdout?.on('data', (chunk) => {
|
|
186
|
+
stdoutBytes += chunk.length;
|
|
187
|
+
if (stdoutBytes > 0 && !settled) {
|
|
188
|
+
clearTimeout(watchdog);
|
|
189
|
+
finish({ kind: 'stdout_observed', elapsed_ms: Date.now() - start });
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
child.stderr?.on('data', (chunk) => {
|
|
194
|
+
stderrBytes += chunk.length;
|
|
195
|
+
stderrBuf += chunk.toString('utf8');
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
child.on('error', (error) => {
|
|
199
|
+
clearTimeout(watchdog);
|
|
200
|
+
finish({
|
|
201
|
+
kind: 'spawn_error',
|
|
202
|
+
errno: error?.errno ?? null,
|
|
203
|
+
code: error?.code ?? null,
|
|
204
|
+
message: error?.message ?? String(error),
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
child.on('exit', (code, signal) => {
|
|
209
|
+
if (settled) return;
|
|
210
|
+
clearTimeout(watchdog);
|
|
211
|
+
const elapsed_ms = Date.now() - start;
|
|
212
|
+
if (stdoutBytes > 0) {
|
|
213
|
+
finish({ kind: 'stdout_observed', elapsed_ms });
|
|
214
|
+
} else if (code !== 0) {
|
|
215
|
+
finish({
|
|
216
|
+
kind: 'exit_nonzero',
|
|
217
|
+
elapsed_ms,
|
|
218
|
+
exit_code: code,
|
|
219
|
+
exit_signal: signal,
|
|
220
|
+
stderr_snippet: stderrBuf.slice(0, 500),
|
|
221
|
+
});
|
|
222
|
+
} else if (stderrBytes > 0) {
|
|
223
|
+
finish({ kind: 'stderr_only', elapsed_ms, stderr_snippet: stderrBuf.slice(0, 500) });
|
|
224
|
+
} else {
|
|
225
|
+
finish({ kind: 'hang', elapsed_ms });
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
child.stdin?.end(`${stdinPayload}\n`);
|
|
231
|
+
} catch {
|
|
232
|
+
// best-effort; error will surface via 'error' event if real
|
|
233
|
+
}
|
|
234
|
+
});
|
|
59
235
|
}
|
|
60
236
|
|
|
61
237
|
export { CLAUDE_ENV_AUTH_KEYS, normalizeCommandTokens };
|
|
@@ -165,30 +165,30 @@ async function probeLocalCommand(runtimeId, runtime, probeKindLabel, options = {
|
|
|
165
165
|
};
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
// else. If they fix auth (or add --bare) but still do not have claude
|
|
177
|
-
// installed, the next connector check surfaces command_presence after they
|
|
178
|
-
// fix the config — that is the correct operator progression.
|
|
168
|
+
const claudeAuthIssue = await getClaudeSubprocessAuthIssue(runtime, process.env, {
|
|
169
|
+
timeoutMs: options.claudeAuthProbeTimeoutMs,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// DEC-BUG56-PREFLIGHT-PROBE-OVER-SHAPE-CHECK-001
|
|
173
|
+
// Auth-preflight is observation-based: a no-env/no-bare Claude runtime is
|
|
174
|
+
// only refused when a bounded smoke probe actually hangs or fails without
|
|
175
|
+
// stdout. Working Claude Max keychain setups must pass this gate.
|
|
179
176
|
if (claudeAuthIssue) {
|
|
180
177
|
return {
|
|
181
178
|
...base,
|
|
182
179
|
level: 'fail',
|
|
183
180
|
probe_kind: 'auth_preflight',
|
|
184
|
-
command:
|
|
181
|
+
command: formatTarget(runtime) || head,
|
|
185
182
|
error_code: 'claude_auth_preflight_failed',
|
|
186
183
|
detail: claudeAuthIssue.detail,
|
|
187
184
|
fix: claudeAuthIssue.fix,
|
|
188
185
|
auth_env_present: claudeAuthIssue.auth_env_present,
|
|
186
|
+
smoke_probe: claudeAuthIssue.smoke_probe,
|
|
189
187
|
};
|
|
190
188
|
}
|
|
191
189
|
|
|
190
|
+
const spawnProbe = probeRuntimeSpawnContext(options.root || process.cwd(), runtime, { runtimeId });
|
|
191
|
+
|
|
192
192
|
if (!spawnProbe.ok) {
|
|
193
193
|
return {
|
|
194
194
|
...base,
|
|
@@ -401,8 +401,6 @@ function analyzeLocalCliAuthorityIntent(runtimeId, runtime, roles) {
|
|
|
401
401
|
// Prompt transport validation
|
|
402
402
|
const transport = runtime.prompt_transport || 'dispatch_bundle_only';
|
|
403
403
|
const knownTransports = KNOWN_CLI_TRANSPORTS[binaryName];
|
|
404
|
-
const claudeAuthIssue = getClaudeSubprocessAuthIssue(runtime);
|
|
405
|
-
|
|
406
404
|
if (transport === 'argv' && !commandTokens.some((token) => token.includes('{prompt}'))) {
|
|
407
405
|
warnings.push({
|
|
408
406
|
probe_kind: 'transport_intent',
|
|
@@ -422,15 +420,6 @@ function analyzeLocalCliAuthorityIntent(runtimeId, runtime, roles) {
|
|
|
422
420
|
});
|
|
423
421
|
}
|
|
424
422
|
|
|
425
|
-
if (claudeAuthIssue) {
|
|
426
|
-
warnings.push({
|
|
427
|
-
probe_kind: 'auth_preflight',
|
|
428
|
-
level: 'warn',
|
|
429
|
-
detail: claudeAuthIssue.detail,
|
|
430
|
-
fix: claudeAuthIssue.fix,
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
|
|
434
423
|
return { warnings };
|
|
435
424
|
}
|
|
436
425
|
|
|
@@ -105,11 +105,10 @@ export async function validateConfiguredConnector(sourceRoot, options = {}) {
|
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
// DEC-
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
const claudeAuthIssue = getClaudeSubprocessAuthIssue(runtime);
|
|
108
|
+
// DEC-BUG56-PREFLIGHT-PROBE-OVER-SHAPE-CHECK-001 — refuse Claude local_cli
|
|
109
|
+
// auth-hang shapes only after a bounded smoke probe observes no stdout.
|
|
110
|
+
// Working Claude Max keychain setups must pass instead of false-positive.
|
|
111
|
+
const claudeAuthIssue = await getClaudeSubprocessAuthIssue(runtime);
|
|
113
112
|
if (claudeAuthIssue) {
|
|
114
113
|
return {
|
|
115
114
|
ok: false,
|
|
@@ -131,6 +130,7 @@ export async function validateConfiguredConnector(sourceRoot, options = {}) {
|
|
|
131
130
|
error_code: 'claude_auth_preflight_failed',
|
|
132
131
|
error: claudeAuthIssue.detail,
|
|
133
132
|
auth_env_present: claudeAuthIssue.auth_env_present,
|
|
133
|
+
smoke_probe: claudeAuthIssue.smoke_probe,
|
|
134
134
|
fix: claudeAuthIssue.fix,
|
|
135
135
|
dispatch: null,
|
|
136
136
|
validation: null,
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"manual-pm": { "type": "manual" },
|
|
81
81
|
"local-dev": {
|
|
82
82
|
"type": "local_cli",
|
|
83
|
-
"command": ["claude", "--print", "--dangerously-skip-permissions"],
|
|
83
|
+
"command": ["claude", "--print", "--dangerously-skip-permissions", "--bare"],
|
|
84
84
|
"cwd": ".",
|
|
85
85
|
"prompt_transport": "stdin"
|
|
86
86
|
},
|
|
@@ -44,25 +44,25 @@
|
|
|
44
44
|
"runtimes": {
|
|
45
45
|
"local-pm": {
|
|
46
46
|
"type": "local_cli",
|
|
47
|
-
"command": ["claude", "--print", "--dangerously-skip-permissions"],
|
|
47
|
+
"command": ["claude", "--print", "--dangerously-skip-permissions", "--bare"],
|
|
48
48
|
"cwd": ".",
|
|
49
49
|
"prompt_transport": "stdin"
|
|
50
50
|
},
|
|
51
51
|
"local-dev": {
|
|
52
52
|
"type": "local_cli",
|
|
53
|
-
"command": ["claude", "--print", "--dangerously-skip-permissions"],
|
|
53
|
+
"command": ["claude", "--print", "--dangerously-skip-permissions", "--bare"],
|
|
54
54
|
"cwd": ".",
|
|
55
55
|
"prompt_transport": "stdin"
|
|
56
56
|
},
|
|
57
57
|
"local-qa": {
|
|
58
58
|
"type": "local_cli",
|
|
59
|
-
"command": ["claude", "--print", "--dangerously-skip-permissions"],
|
|
59
|
+
"command": ["claude", "--print", "--dangerously-skip-permissions", "--bare"],
|
|
60
60
|
"cwd": ".",
|
|
61
61
|
"prompt_transport": "stdin"
|
|
62
62
|
},
|
|
63
63
|
"local-director": {
|
|
64
64
|
"type": "local_cli",
|
|
65
|
-
"command": ["claude", "--print", "--dangerously-skip-permissions"],
|
|
65
|
+
"command": ["claude", "--print", "--dangerously-skip-permissions", "--bare"],
|
|
66
66
|
"cwd": ".",
|
|
67
67
|
"prompt_transport": "stdin"
|
|
68
68
|
}
|