paseo-room 0.3.0 → 0.4.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 +10 -1
- package/dist/index.js +99 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,6 +45,7 @@ interactive stdin/stdout/stderr, and targets exactly one selected agent and role
|
|
|
45
45
|
| `--agent <codex\|claude\|pi>` | `codex` | Which coding agent to seat. Repeat the flag to combine agents. |
|
|
46
46
|
| `--apply` | off | Actually write setup/remove changes; `auth login` does not use it. |
|
|
47
47
|
| `--json` | off | One machine-readable document instead of text. |
|
|
48
|
+
| `--no-claude-memory-contract` | off | Omit the role contract from Claude role `CLAUDE.md` files, leaving the room plugin as the only Claude carrier. Your global memory is still carried. `setup` only. |
|
|
48
49
|
| `--room-home <path>` | `~/.paseo-room` | Where role homes are written. |
|
|
49
50
|
| `--codex-home <path>` | `~/.codex` | Source Codex configuration. |
|
|
50
51
|
| `--claude-home <path>` | `~/.claude` | Source Claude Code configuration. |
|
|
@@ -99,7 +100,7 @@ starts, its exit code is preserved; a signal is returned using the conventional
|
|
|
99
100
|
auth.json # created and owned by Codex after role login, if file-backed
|
|
100
101
|
AGENTS.md, skills, plugins, hooks.json → symlinks into ~/.codex when present (Peer: see below)
|
|
101
102
|
roles/claude/<role>/
|
|
102
|
-
CLAUDE.md # your global memory + role instructions
|
|
103
|
+
CLAUDE.md # your global memory + role instructions (contract omitted with --no-claude-memory-contract)
|
|
103
104
|
settings.json # your settings.json + PASEO_ROOM_ROLE
|
|
104
105
|
.claude.json # seeded once from yours, then owned by Claude
|
|
105
106
|
.credentials.json # created and owned by Claude after role login, if file-backed
|
|
@@ -258,6 +259,14 @@ the plugin is absent, disabled, failed, registered from another path, or drifted
|
|
|
258
259
|
silently missing carrier is not a guarantee. The hook runs for newly created sessions;
|
|
259
260
|
recreate an existing Claude session after setup or an update.
|
|
260
261
|
|
|
262
|
+
`setup --no-claude-memory-contract` leaves the plugin as the only Claude carrier: each role
|
|
263
|
+
`CLAUDE.md` then holds your global memory alone, and the file is not written at all when you
|
|
264
|
+
have none. Only the contract is dropped, never your own memory, and an earlier generation of it
|
|
265
|
+
is removed rather than left behind. The choice is recorded in `room.json`, so `verify` compares
|
|
266
|
+
against it and rejects the flag itself; `setup` without the flag restores the fallback. Keep the
|
|
267
|
+
fallback unless you have a reason not to: the plugin hook is verified, but whether a *resumed*
|
|
268
|
+
session re-enters it is unproven, and `CLAUDE.md` is what covers that case.
|
|
269
|
+
|
|
261
270
|
Pi providers use a strict command tail:
|
|
262
271
|
|
|
263
272
|
```text
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var init_package = __esm({
|
|
|
15
15
|
"package.json"() {
|
|
16
16
|
package_default = {
|
|
17
17
|
name: "paseo-room",
|
|
18
|
-
version: "0.
|
|
18
|
+
version: "0.4.0",
|
|
19
19
|
description: "One CLI that configures Codex, Claude Code, and Pi role homes in $HOME and registers them with your local Paseo daemon.",
|
|
20
20
|
keywords: [
|
|
21
21
|
"paseo",
|
|
@@ -282,6 +282,7 @@ async function staleChildren(entry) {
|
|
|
282
282
|
}
|
|
283
283
|
async function current(entry) {
|
|
284
284
|
const stat2 = await lstatOrAbsent(entry.path);
|
|
285
|
+
if (entry.kind === "absent") return stat2 ? "different" : "same";
|
|
285
286
|
if (!stat2) return "absent";
|
|
286
287
|
if (entry.kind === "dir") return stat2.isDirectory() ? "same" : "different";
|
|
287
288
|
if (entry.kind === "managed-dir") {
|
|
@@ -301,9 +302,9 @@ async function planEntries(entries) {
|
|
|
301
302
|
for (const entry of entries) {
|
|
302
303
|
const state = await current(entry);
|
|
303
304
|
operations.push({
|
|
304
|
-
action: state === "same" ? "noop" : state === "absent" ? "create" : "update",
|
|
305
|
+
action: state === "same" ? "noop" : entry.kind === "absent" ? "remove" : state === "absent" ? "create" : "update",
|
|
305
306
|
// A managed directory is still a directory to everything that reports operations.
|
|
306
|
-
kind: entry.kind === "managed-dir" ? "dir" : entry.kind,
|
|
307
|
+
kind: entry.kind === "managed-dir" ? "dir" : entry.kind === "absent" ? "file" : entry.kind,
|
|
307
308
|
target: entry.path
|
|
308
309
|
});
|
|
309
310
|
}
|
|
@@ -372,6 +373,12 @@ async function applyManagedDirectory(entry) {
|
|
|
372
373
|
await rm(child, { force: true });
|
|
373
374
|
}
|
|
374
375
|
}
|
|
376
|
+
async function removeManagedFile(path) {
|
|
377
|
+
const stat2 = await lstatOrAbsent(path);
|
|
378
|
+
if (!stat2) return;
|
|
379
|
+
if (!stat2.isFile()) refuse(path, "a regular file this room generated", stat2);
|
|
380
|
+
await rm(path, { force: true });
|
|
381
|
+
}
|
|
375
382
|
async function applyEntries(entries) {
|
|
376
383
|
for (const entry of entries) {
|
|
377
384
|
if (await current(entry) === "same") continue;
|
|
@@ -383,6 +390,10 @@ async function applyEntries(entries) {
|
|
|
383
390
|
await applyManagedDirectory(entry);
|
|
384
391
|
continue;
|
|
385
392
|
}
|
|
393
|
+
if (entry.kind === "absent") {
|
|
394
|
+
await removeManagedFile(entry.path);
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
386
397
|
await mkdir(dirname(entry.path), { recursive: true, mode: DIR_MODE });
|
|
387
398
|
await assertReplaceable(entry);
|
|
388
399
|
await replaceAtomically(entry);
|
|
@@ -461,12 +472,14 @@ var init_roles = __esm({
|
|
|
461
472
|
// src/room.ts
|
|
462
473
|
import { join as join3 } from "path";
|
|
463
474
|
import { z } from "zod";
|
|
464
|
-
function renderMarker(version, agents, roles, contract) {
|
|
475
|
+
function renderMarker(version, agents, roles, contract, claudeMemoryContract) {
|
|
465
476
|
return JSON.stringify({
|
|
466
477
|
version,
|
|
467
478
|
agents: [...agents],
|
|
468
479
|
roles: [...roles],
|
|
469
|
-
...contract === void 0 ? {} : { contract }
|
|
480
|
+
...contract === void 0 ? {} : { contract },
|
|
481
|
+
// Written only when it differs from the default, so an unchanged room's marker is unchanged.
|
|
482
|
+
...claudeMemoryContract === false ? { claudeMemoryContract: false } : {}
|
|
470
483
|
}, null, 2) + "\n";
|
|
471
484
|
}
|
|
472
485
|
async function readMarker(layout) {
|
|
@@ -494,7 +507,13 @@ var init_room = __esm({
|
|
|
494
507
|
* written before contract provenance existed has no digest, and such a marker must still
|
|
495
508
|
* parse rather than look like a foreign file.
|
|
496
509
|
*/
|
|
497
|
-
contract: z.string().min(1).optional()
|
|
510
|
+
contract: z.string().min(1).optional(),
|
|
511
|
+
/**
|
|
512
|
+
* False when this room deliberately suppressed the role contract in Claude's `CLAUDE.md`,
|
|
513
|
+
* leaving the plugin as its only Claude carrier. Optional and defaulted to true so a room
|
|
514
|
+
* written before the option existed keeps parsing and keeps its current behaviour.
|
|
515
|
+
*/
|
|
516
|
+
claudeMemoryContract: z.boolean().optional()
|
|
498
517
|
});
|
|
499
518
|
}
|
|
500
519
|
});
|
|
@@ -1098,8 +1117,10 @@ function renderRoleState(source) {
|
|
|
1098
1117
|
for (const key of SEEDED_KEYS) if (key in root) state[key] = root[key];
|
|
1099
1118
|
return JSON.stringify(state, null, 2) + "\n";
|
|
1100
1119
|
}
|
|
1101
|
-
function renderRoleMemory(source, role) {
|
|
1120
|
+
function renderRoleMemory(source, role, contract = true) {
|
|
1102
1121
|
const operator = source?.trim();
|
|
1122
|
+
if (!contract) return operator ? `${operator}
|
|
1123
|
+
` : void 0;
|
|
1103
1124
|
return operator ? `${operator}
|
|
1104
1125
|
|
|
1105
1126
|
${renderInstructions(role)}` : renderInstructions(role);
|
|
@@ -1219,7 +1240,7 @@ var init_claude = __esm({
|
|
|
1219
1240
|
"CronList"
|
|
1220
1241
|
]
|
|
1221
1242
|
},
|
|
1222
|
-
async build(layout, roles) {
|
|
1243
|
+
async build(layout, roles, options = {}) {
|
|
1223
1244
|
const home = layout.agentHome.claude;
|
|
1224
1245
|
const binary = await which(layout.bin.claude, layout.searchPath);
|
|
1225
1246
|
if (!binary) {
|
|
@@ -1272,7 +1293,9 @@ var init_claude = __esm({
|
|
|
1272
1293
|
if (divergence) drift.push(mcpDriftCheck(role, target, statePath, divergence));
|
|
1273
1294
|
}
|
|
1274
1295
|
entries.push({ kind: "dir", path: target });
|
|
1275
|
-
|
|
1296
|
+
const memoryPath = join7(target, "CLAUDE.md");
|
|
1297
|
+
const memory = renderRoleMemory(memorySource, role, options.memoryContract ?? true);
|
|
1298
|
+
entries.push(memory === void 0 ? { kind: "absent", path: memoryPath } : { kind: "file", path: memoryPath, content: memory });
|
|
1276
1299
|
entries.push({ kind: "file", path: join7(target, "settings.json"), content: renderRoleSettings(settingsSource, role, target) });
|
|
1277
1300
|
entries.push({ kind: "file", path: statePath, content: renderRoleState(stateSource), once: true });
|
|
1278
1301
|
entries.push(...await roleResourceEntries({ role, target, home, names: SHARED, shared, executable: EXECUTABLE }));
|
|
@@ -2157,7 +2180,7 @@ function roleProfiles(agent, roles) {
|
|
|
2157
2180
|
notes: ROLE_NOTES[role]
|
|
2158
2181
|
}));
|
|
2159
2182
|
}
|
|
2160
|
-
async function buildDesired(layout, agents, roles) {
|
|
2183
|
+
async function buildDesired(layout, agents, roles, build = {}) {
|
|
2161
2184
|
const entries = [
|
|
2162
2185
|
{ kind: "dir", path: layout.roomHome },
|
|
2163
2186
|
{ kind: "dir", path: sharedRoom(layout) },
|
|
@@ -2169,7 +2192,7 @@ async function buildDesired(layout, agents, roles) {
|
|
|
2169
2192
|
const binaries = {};
|
|
2170
2193
|
for (const id of agents) {
|
|
2171
2194
|
const agent = AGENTS[id];
|
|
2172
|
-
const plan = await agent.build(layout, roles);
|
|
2195
|
+
const plan = await agent.build(layout, roles, build);
|
|
2173
2196
|
entries.push(...plan.entries);
|
|
2174
2197
|
checks.push(...plan.checks);
|
|
2175
2198
|
const credentials = plan.credentials ?? [];
|
|
@@ -2206,7 +2229,7 @@ async function buildDesired(layout, agents, roles) {
|
|
|
2206
2229
|
}
|
|
2207
2230
|
const pluginPath = agents.includes("claude") ? claudeCarrierPluginDir(layout) : void 0;
|
|
2208
2231
|
if (pluginPath !== void 0) entries.push(...claudeCarrierEntries(layout, roles));
|
|
2209
|
-
entries.push({ kind: "file", path: join11(layout.roomHome, MARKER), content: renderMarker(package_default.version, agents, roles, contractDigest()) });
|
|
2232
|
+
entries.push({ kind: "file", path: join11(layout.roomHome, MARKER), content: renderMarker(package_default.version, agents, roles, contractDigest(), markerMemoryContract(agents, build.memoryContract ?? true)) });
|
|
2210
2233
|
return { entries, providers, profiles, checks, ...pluginPath === void 0 ? {} : { pluginPath } };
|
|
2211
2234
|
}
|
|
2212
2235
|
function contractProvenance(previous) {
|
|
@@ -2232,6 +2255,14 @@ function thinkingDiagnostics(live, desired) {
|
|
|
2232
2255
|
`Choose a lower reasoning option for those seats in Paseo if you want the room's own defaults (${ROLE_THINKING.supervisor} for Supervisor, ${ROLE_THINKING.lead} for Lead and Peer).`
|
|
2233
2256
|
)];
|
|
2234
2257
|
}
|
|
2258
|
+
function fileDriftSummary(drifted) {
|
|
2259
|
+
const removals = drifted.filter((operation) => operation.action === "remove").length;
|
|
2260
|
+
const count = String(drifted.length);
|
|
2261
|
+
const subject = drifted.length === 1 ? "managed role file is" : "managed role files are";
|
|
2262
|
+
if (removals === 0) return `${count} ${subject} missing or outdated.`;
|
|
2263
|
+
if (removals === drifted.length) return `${count} ${subject} present but suppressed by this room.`;
|
|
2264
|
+
return `${count} ${subject} missing or outdated, and ${String(removals)} of them are present but suppressed by this room.`;
|
|
2265
|
+
}
|
|
2235
2266
|
function fileDriftDetail(targets) {
|
|
2236
2267
|
const catalogs = targets.filter((target) => target.endsWith(`${sep2}model-catalog.json`));
|
|
2237
2268
|
if (catalogs.length === 0) return "";
|
|
@@ -2394,9 +2425,21 @@ async function reconcilePlugin(session, desired, plan, pending, expectedPath) {
|
|
|
2394
2425
|
}
|
|
2395
2426
|
return [pluginRuntimeCheck(plugin, expectedPath)];
|
|
2396
2427
|
}
|
|
2428
|
+
function markerMemoryContract(agents, memoryContract) {
|
|
2429
|
+
return agents.includes("claude") ? memoryContract : void 0;
|
|
2430
|
+
}
|
|
2431
|
+
function memoryContractDiagnostic(agents, memoryContract) {
|
|
2432
|
+
if (memoryContract || !agents.includes("claude")) return [];
|
|
2433
|
+
return [warn(
|
|
2434
|
+
"claude.memory-contract",
|
|
2435
|
+
"Claude role CLAUDE.md files carry your global memory only: the role contract was not written to them, so the trusted server plugin is this room's only Claude carrier. Only a newly created agent passes through its creation hook, and whether a resumed session re-enters that hook is unproven.",
|
|
2436
|
+
"Drop --no-claude-memory-contract and run setup --apply to restore the file fallback."
|
|
2437
|
+
)];
|
|
2438
|
+
}
|
|
2397
2439
|
async function setup(options = {}) {
|
|
2398
2440
|
const layout = resolveLayout(options, options.env);
|
|
2399
2441
|
const agents = options.agents ?? ["codex"];
|
|
2442
|
+
const memoryContract = options.claudeMemoryContract ?? true;
|
|
2400
2443
|
const invalid = layoutChecks(layout, agents);
|
|
2401
2444
|
if (invalid.length > 0) return failed("setup", invalid);
|
|
2402
2445
|
const rootSafety = await roomPathSafety(layout, [], []);
|
|
@@ -2408,7 +2451,7 @@ async function setup(options = {}) {
|
|
|
2408
2451
|
const compatibilityAgents = [.../* @__PURE__ */ new Set([...agents, ...previous?.agents ?? []])];
|
|
2409
2452
|
const daemon = await checkDaemon(layout, options.env, minimumPaseoVersion(compatibilityAgents));
|
|
2410
2453
|
if (!daemon.daemon) return failed("setup", daemon.checks);
|
|
2411
|
-
const desired = await buildDesired(layout, agents, ROLES);
|
|
2454
|
+
const desired = await buildDesired(layout, agents, ROLES, { memoryContract });
|
|
2412
2455
|
const stale = await staleFrom(layout, previous, agents, ROLES);
|
|
2413
2456
|
const retained = stale.retainedDirectories.length === 0 ? [] : [warn(
|
|
2414
2457
|
"room.stale-role-homes-preserved",
|
|
@@ -2423,7 +2466,7 @@ async function setup(options = {}) {
|
|
|
2423
2466
|
const { operations, liveProfiles } = plan;
|
|
2424
2467
|
const pending = operations.filter((operation) => operation.action !== "noop");
|
|
2425
2468
|
const pluginPreconditions = desired.pluginPath === void 0 ? plan.pluginChecks : [pluginsEnabledCheck(await session.pluginsEnabled()), ...plan.pluginChecks];
|
|
2426
|
-
const preApplyDiagnostics = [...checks, ...pluginPreconditions, ...contractProvenance(previous), ...thinkingDiagnostics(liveProfiles, desired.profiles)];
|
|
2469
|
+
const preApplyDiagnostics = [...checks, ...pluginPreconditions, ...memoryContractDiagnostic(agents, memoryContract), ...contractProvenance(previous), ...thinkingDiagnostics(liveProfiles, desired.profiles)];
|
|
2427
2470
|
if (hasFailure(preApplyDiagnostics) || !options.apply) {
|
|
2428
2471
|
return {
|
|
2429
2472
|
command: "setup",
|
|
@@ -2451,13 +2494,15 @@ async function setup(options = {}) {
|
|
|
2451
2494
|
version: package_default.version,
|
|
2452
2495
|
agents: [...agents],
|
|
2453
2496
|
roles: [...ROLES],
|
|
2454
|
-
contract: contractDigest()
|
|
2497
|
+
contract: contractDigest(),
|
|
2498
|
+
...markerMemoryContract(agents, memoryContract) === false ? { claudeMemoryContract: false } : {}
|
|
2455
2499
|
};
|
|
2456
2500
|
const appliedChecks = [
|
|
2457
2501
|
...checks,
|
|
2458
2502
|
...pluginPreconditions,
|
|
2459
2503
|
...pluginChecks,
|
|
2460
2504
|
pass("room.applied", `Room ready at ${layout.roomHome} with ${String(ids.length)} Paseo providers.`),
|
|
2505
|
+
...memoryContractDiagnostic(agents, memoryContract),
|
|
2461
2506
|
...contractProvenance(appliedMarker),
|
|
2462
2507
|
...thinkingDiagnostics(appliedProfiles, desired.profiles)
|
|
2463
2508
|
];
|
|
@@ -2484,7 +2529,10 @@ async function verify(options = {}) {
|
|
|
2484
2529
|
if (hasFailure(pathSafety)) return failed("verify", pathSafety);
|
|
2485
2530
|
const daemon = await checkDaemon(layout, options.env, minimumPaseoVersion(marker.agents));
|
|
2486
2531
|
if (!daemon.daemon) return failed("verify", daemon.checks);
|
|
2487
|
-
const desired = await buildDesired(layout, marker.agents, marker.roles
|
|
2532
|
+
const desired = await buildDesired(layout, marker.agents, marker.roles, {
|
|
2533
|
+
// The room's own recorded choice, so verify compares against what setup wrote.
|
|
2534
|
+
memoryContract: marker.claudeMemoryContract ?? true
|
|
2535
|
+
});
|
|
2488
2536
|
const checks = [...daemon.checks, ...desired.checks];
|
|
2489
2537
|
if (hasFailure(checks)) return failed("verify", checks);
|
|
2490
2538
|
return withSession(daemon.daemon, async (session) => {
|
|
@@ -2504,11 +2552,12 @@ async function verify(options = {}) {
|
|
|
2504
2552
|
];
|
|
2505
2553
|
const all = [
|
|
2506
2554
|
...checks,
|
|
2507
|
-
files === 0 ? pass("room.files", "Every managed role file matches the current definition.") : fail("room.files", `${
|
|
2555
|
+
files === 0 ? pass("room.files", "Every managed role file matches the current definition.") : fail("room.files", `${fileDriftSummary(driftedFiles)}${fileDriftDetail(driftedFiles.map((operation) => operation.target))}`, "Run: paseo-room setup --apply"),
|
|
2508
2556
|
providers === 0 ? pass("room.providers", `All ${String(Object.keys(desired.providers).length)} Paseo providers are registered as expected.`) : fail("room.providers", `${String(providers)} Paseo providers are missing or differ.`, "Run: paseo-room setup --apply"),
|
|
2509
2557
|
profiles === 0 ? pass("room.profiles", `All ${String(desired.profiles.length)} Paseo agent profiles are registered as expected.`) : fail("room.profiles", `${String(profiles)} Paseo agent profiles are missing or differ.`, "Run: paseo-room setup --apply"),
|
|
2510
2558
|
...pluginChecks,
|
|
2511
2559
|
// Diagnostics last: a warning never precedes the failure it might be mistaken for.
|
|
2560
|
+
...memoryContractDiagnostic(marker.agents, marker.claudeMemoryContract ?? true),
|
|
2512
2561
|
...contractProvenance(marker),
|
|
2513
2562
|
...thinkingDiagnostics(liveProfiles, desired.profiles)
|
|
2514
2563
|
];
|
|
@@ -2658,12 +2707,25 @@ async function runWizard(prompts, emit, write, options = {}, onAction) {
|
|
|
2658
2707
|
options: AGENT_IDS.map((value) => ({ value, label: AGENTS[value].label }))
|
|
2659
2708
|
});
|
|
2660
2709
|
if (typeof agents === "symbol" || agents.length === 0) return cancelled();
|
|
2661
|
-
|
|
2710
|
+
let claudeMemoryContract = true;
|
|
2711
|
+
if (agents.includes("claude")) {
|
|
2712
|
+
const carrier = await prompts.select({
|
|
2713
|
+
message: "Claude role contract carrier: the room plugin is always used. Also write the contract into each role CLAUDE.md?",
|
|
2714
|
+
options: [
|
|
2715
|
+
{ value: "both", label: "Yes \u2014 keep it as a fallback (recommended; resume behaviour is unproven)" },
|
|
2716
|
+
{ value: "plugin", label: "No \u2014 plugin only; CLAUDE.md keeps your global memory alone" }
|
|
2717
|
+
]
|
|
2718
|
+
});
|
|
2719
|
+
if (typeof carrier === "symbol") return cancelled();
|
|
2720
|
+
claudeMemoryContract = carrier === "both";
|
|
2721
|
+
}
|
|
2722
|
+
const setupOptions = { ...options, agents, claudeMemoryContract };
|
|
2723
|
+
const preview = await setup(setupOptions);
|
|
2662
2724
|
const status = emit(preview);
|
|
2663
2725
|
if (preview.outcome !== "changes-planned") return status;
|
|
2664
2726
|
const approved = await prompts.confirm({ message: "Apply these changes? Authentication will not be validated or started." });
|
|
2665
2727
|
if (approved !== true) return cancelled();
|
|
2666
|
-
return emit(await setup({ ...
|
|
2728
|
+
return emit(await setup({ ...setupOptions, apply: true }));
|
|
2667
2729
|
}
|
|
2668
2730
|
var terminalPrompts;
|
|
2669
2731
|
var init_wizard = __esm({
|
|
@@ -2729,7 +2791,14 @@ function optionsFrom(raw, base) {
|
|
|
2729
2791
|
if (typeof value === "string" && value.trim()) paths[flag] = value.trim();
|
|
2730
2792
|
}
|
|
2731
2793
|
const agents = Array.isArray(raw.agent) && raw.agent.length > 0 ? raw.agent : void 0;
|
|
2732
|
-
return {
|
|
2794
|
+
return {
|
|
2795
|
+
...base,
|
|
2796
|
+
...paths,
|
|
2797
|
+
...agents ? { agents } : {},
|
|
2798
|
+
...raw.apply === true ? { apply: true } : {},
|
|
2799
|
+
// Commander defaults a --no- flag to true, so only an explicit opt-out is carried.
|
|
2800
|
+
...raw.claudeMemoryContract === false ? { claudeMemoryContract: false } : {}
|
|
2801
|
+
};
|
|
2733
2802
|
}
|
|
2734
2803
|
function failedFromThrown(command, error) {
|
|
2735
2804
|
if (error instanceof PromptAssetError) {
|
|
@@ -2779,7 +2848,7 @@ async function runCli(argv, output, context = {}) {
|
|
|
2779
2848
|
return emit(failedFromThrown(wizardCommand, error));
|
|
2780
2849
|
}
|
|
2781
2850
|
}
|
|
2782
|
-
const program = new Command().name("paseo-room").description("Configure Codex/Claude/Pi role homes in $HOME and register them with your local Paseo daemon.").version(package_default.version).usage("<setup|verify|remove> [options]\n auth login <codex|claude|pi> <supervisor|lead|peer> [options]").argument("<command>", "setup | verify | remove | auth").argument("[command-arguments...]", "auth login <agent> <role>").option("--agent <agent>", "codex, claude, or pi; repeat to combine (default: codex)", collectAgent).option("--apply", "actually make the changes (default: dry run)").option("--json", "machine-readable output").option("--room-home <path>", "where role homes are written (default: ~/.paseo-room)").option("--codex-home <path>", "source Codex config (default: ~/.codex)").option("--claude-home <path>", "source Claude Code config (default: ~/.claude)").option("--pi-home <path>", "source Pi config (default: ~/.pi/agent)").option("--codex-bin <path>", "Codex executable (default: found on PATH)").option("--claude-bin <path>", "Claude Code executable (default: found on PATH)").option("--pi-bin <path>", "Pi executable (default: found on PATH)").option("--paseo-bin <path>", "Paseo executable (default: found on PATH)").configureOutput({ writeOut: (text) => {
|
|
2851
|
+
const program = new Command().name("paseo-room").description("Configure Codex/Claude/Pi role homes in $HOME and register them with your local Paseo daemon.").version(package_default.version).usage("<setup|verify|remove> [options]\n auth login <codex|claude|pi> <supervisor|lead|peer> [options]").argument("<command>", "setup | verify | remove | auth").argument("[command-arguments...]", "auth login <agent> <role>").option("--agent <agent>", "codex, claude, or pi; repeat to combine (default: codex)", collectAgent).option("--apply", "actually make the changes (default: dry run)").option("--json", "machine-readable output").option("--no-claude-memory-contract", "omit the role contract from Claude role CLAUDE.md files, leaving the room plugin as the only Claude carrier").option("--room-home <path>", "where role homes are written (default: ~/.paseo-room)").option("--codex-home <path>", "source Codex config (default: ~/.codex)").option("--claude-home <path>", "source Claude Code config (default: ~/.claude)").option("--pi-home <path>", "source Pi config (default: ~/.pi/agent)").option("--codex-bin <path>", "Codex executable (default: found on PATH)").option("--claude-bin <path>", "Claude Code executable (default: found on PATH)").option("--pi-bin <path>", "Pi executable (default: found on PATH)").option("--paseo-bin <path>", "Paseo executable (default: found on PATH)").configureOutput({ writeOut: (text) => {
|
|
2783
2852
|
output.stdout(text);
|
|
2784
2853
|
}, writeErr: (text) => {
|
|
2785
2854
|
output.stderr(text);
|
|
@@ -2800,7 +2869,16 @@ async function runCli(argv, output, context = {}) {
|
|
|
2800
2869
|
return 2;
|
|
2801
2870
|
}
|
|
2802
2871
|
try {
|
|
2872
|
+
if (raw.claudeMemoryContract === false && (command === "verify" || command === "remove")) {
|
|
2873
|
+
output.stderr(`paseo-room ${command}: --no-claude-memory-contract is a setup choice recorded in the room marker; ${command} reads it from there.
|
|
2874
|
+
`);
|
|
2875
|
+
return 2;
|
|
2876
|
+
}
|
|
2803
2877
|
if (command === "auth") {
|
|
2878
|
+
if (raw.claudeMemoryContract === false) {
|
|
2879
|
+
output.stderr("paseo-room auth login only authenticates a role and does not use --no-claude-memory-contract.\n");
|
|
2880
|
+
return 2;
|
|
2881
|
+
}
|
|
2804
2882
|
if (raw.apply === true) {
|
|
2805
2883
|
output.stderr("paseo-room auth login is already explicit and does not use --apply.\n");
|
|
2806
2884
|
return 2;
|