feat(cli): add 'ccam lanes shell' to attach a real terminal to a lane's tmux session
This commit is contained in:
+33
@@ -2300,6 +2300,31 @@ async function cmdLanesPipeline(args) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a real terminal to the exact tmux session the dashboard uses for
|
||||
* this lane's run. Creates it if it doesn't exist yet (`tmux new-session -A`
|
||||
* is create-or-attach, the same idempotent semantics as clicking Start on
|
||||
* the dashboard). The user types `claude` themselves inside — this command's
|
||||
* only job is landing them in the right named session.
|
||||
*/
|
||||
async function cmdLanesShell(args) {
|
||||
const resolved = await resolveLaneArg(args);
|
||||
if (!resolved) return;
|
||||
const { lane } = await get(`/api/lanes/${resolved.laneId}`);
|
||||
const sessionName = `ccam-lane-${lane.id}`;
|
||||
const child = spawn("tmux", ["new-session", "-A", "-s", sessionName, "-c", lane.cwd], {
|
||||
stdio: "inherit",
|
||||
});
|
||||
await new Promise((resolve) => {
|
||||
child.on("close", resolve);
|
||||
child.on("error", (err) => {
|
||||
console.error(c.red(`✖ ${err?.message || err}`));
|
||||
process.exitCode = 1;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function cmdFeatureShow(args) {
|
||||
const slug = args.find((arg) => !arg.startsWith("--"));
|
||||
if (!slug) {
|
||||
@@ -2484,6 +2509,11 @@ const COMMAND_GROUPS = [
|
||||
"[<template-id>] [<id>]",
|
||||
"Show, or switch, which pipeline template a lane renders against",
|
||||
],
|
||||
[
|
||||
"lanes shell",
|
||||
"[<id>]",
|
||||
"Attach a real terminal to the exact tmux session the dashboard uses for a lane's run",
|
||||
],
|
||||
[
|
||||
"lanes reset|remove|purge",
|
||||
"<id> [--force] [--keep-db] --yes",
|
||||
@@ -3362,6 +3392,9 @@ async function runCommand(argv) {
|
||||
if (rest[0] === "pipeline") {
|
||||
return cmdLanesPipeline(rest.slice(1));
|
||||
}
|
||||
if (rest[0] === "shell") {
|
||||
return cmdLanesShell(rest.slice(1));
|
||||
}
|
||||
if (rest[0] === "gc") {
|
||||
return cmdLanesGc(rest.slice(1));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user