fix(panes): /tui works in panes with workspace instructions
Claude refused `/tui` ("Cannot switch renderers in this session — it has
restrictions a restart can't carry over") in every pane started with
--append-system-prompt-file, i.e. any workspace with instructions (member
panes usually have the owner's). The instructions are now written as the only
CLAUDE.md of a folder of their own (<data dir>/workspace-prompts/<id>/, a
member's prompt-<id>/ in the handoff dir via write-as), passed as one more
--add-dir with CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1. Verified with
Claude Code 2.1.301: the file is listed in /memory and /tui switches. Codex
is unchanged (its pointer line names the same file).
This commit is contained in:
@@ -181,12 +181,16 @@ describe("lane-sources instructions and launch", () => {
|
||||
assert.equal(lanesLib.getLane(lane.id).instructions, "- always answer in Vietnamese");
|
||||
});
|
||||
|
||||
it("starts a claude pane with --add-dir first and the instructions from a file", () => {
|
||||
it("starts a claude pane with --add-dir first and the instructions as a CLAUDE.md there", () => {
|
||||
let argv = null;
|
||||
let newSession = null;
|
||||
tmux.__setExecImpl((args) => {
|
||||
if (args[0] === "has-session") throw Object.assign(new Error("gone"), { status: 1 });
|
||||
// The CLI rides behind `sh -c <cd; wait for a client> sh <cwd>` (pty-run.js).
|
||||
if (args[0] === "new-session") argv = args.slice(args.indexOf("--") + 6);
|
||||
if (args[0] === "new-session") {
|
||||
newSession = args;
|
||||
argv = args.slice(args.indexOf("--") + 6);
|
||||
}
|
||||
return "";
|
||||
});
|
||||
pty.spawnRun({ laneId: lane.id, cwd: ws, initialPrompt: "-c fix it" });
|
||||
@@ -194,11 +198,15 @@ describe("lane-sources instructions and launch", () => {
|
||||
assert.equal(argv[0], "claude");
|
||||
assert.equal(argv[1], "--add-dir");
|
||||
assert.deepEqual(argv.slice(2, 4), [extra, src.contextDir(lane.id)]);
|
||||
assert.equal(argv[4], "--permission-mode");
|
||||
const flag = argv.find((a) => a.startsWith("--append-system-prompt-file="));
|
||||
const file = flag.slice("--append-system-prompt-file=".length);
|
||||
assert.ok(file.startsWith(process.env.DASHBOARD_DATA_DIR));
|
||||
const text = fs.readFileSync(file, "utf8");
|
||||
// The instructions' own folder, read as memory: a custom system prompt
|
||||
// (`--append-system-prompt-file`) made Claude refuse `/tui` in the pane.
|
||||
const dir = argv[4];
|
||||
assert.ok(dir.startsWith(process.env.DASHBOARD_DATA_DIR));
|
||||
assert.equal(argv[5], "--permission-mode");
|
||||
assert.ok(!argv.some((a) => a.startsWith("--append-system-prompt")));
|
||||
assert.ok(newSession.includes("CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1"));
|
||||
assert.deepEqual(fs.readdirSync(dir), ["CLAUDE.md"]);
|
||||
const text = fs.readFileSync(path.join(dir, "CLAUDE.md"), "utf8");
|
||||
assert.match(text, /^- always answer in Vietnamese/);
|
||||
assert.match(text, /pass wd\.md/);
|
||||
// A prompt that looks like flags stays one positional, never `claude -c`.
|
||||
|
||||
@@ -114,7 +114,7 @@ describe("a member pane's files live in the member's handoff dir", () => {
|
||||
assert.deepEqual(x.addDirs, [ctx]);
|
||||
assert.equal(fs.readFileSync(path.join(ctx, "spec.md"), "utf8"), "# spec\n");
|
||||
assert.equal(mode(path.join(ctx, "spec.md")), 0o644);
|
||||
assert.equal(x.systemPromptFile, path.join(HANDOFF, `prompt-${laneId}.md`));
|
||||
assert.equal(x.systemPromptFile, path.join(HANDOFF, `prompt-${laneId}`, "CLAUDE.md"));
|
||||
assert.equal(mode(x.systemPromptFile), 0o644);
|
||||
const text = fs.readFileSync(x.systemPromptFile, "utf8");
|
||||
assert.match(text, /Be brief\./);
|
||||
|
||||
Reference in New Issue
Block a user