Files
arboretum/packages/server/src/core/claude-launcher.ts
Johan LEROY c6ea9f7930
All checks were successful
Deploy site (production) / build-and-deploy (push) Successful in 21s
feat(groups): session Claude unique par groupe via --add-dir (P6)
Un groupe lance désormais UNE seule session Claude couvrant tous ses
repos/worktrees (--add-dir) au lieu d'une session par repo, pour
travailler en simultané dans une conversation partagée. Le transport WS,
le flow control et l'attach sont inchangés (toujours 1 session, 1 channel).

- shared: SessionSummary.addedDirs/groupId (champs additifs optionnels) ;
  CreateGroupSessionRequest / GroupSessionResponse.
- server: --add-dir dans claude-launcher ; spawn({addDirs,groupId}) +
  persistance (migration #8 : sessions.added_dirs/group_id) ;
  POST /api/v1/groups/:id/session (résolution des dirs cote serveur) ;
  resume re-relie les dirs ; deleteGroup nullifie group_id.
- web: GroupSessionModal (modes feature / checkouts principaux) ;
  createGroupFeature/createGroupSession ; badge « groupe · N depots » ;
  sessionsInGroup dedupliquee.
- site: textes EN/FR « une seule session Claude » + diagramme hub.
- tests: claude-launcher, pty-manager (groupe), group-manager ;
  acceptation P5 etendue (session de groupe multi-repo). 272 tests verts.
2026-06-22 10:06:23 +02:00

51 lines
1.7 KiB
TypeScript

import { execFileSync } from 'node:child_process';
export interface SpawnSpec {
file: string;
args: string[];
env: NodeJS.ProcessEnv;
}
export interface SpawnOptions {
command: 'claude' | 'bash';
/** reprise d'une session existante (P2) : `--resume <id>`, `--fork-session` si fork. */
resume?: { claudeSessionId: string; fork?: boolean };
/** répertoires supplémentaires à relier dans une seule session (P6) : `--add-dir <path>` répété. */
addDirs?: string[];
}
let cachedClaudeBin: string | null = null;
export function resolveClaudeBin(): string {
if (cachedClaudeBin) return cachedClaudeBin;
try {
cachedClaudeBin = execFileSync('which', ['claude'], { encoding: 'utf8' }).trim();
} catch {
throw new Error(
'Claude Code CLI not found in PATH. Install it first: https://code.claude.com/docs/en/quickstart',
);
}
return cachedClaudeBin;
}
/** Module volontairement abstrait : le plan B « BYO API key / Agent SDK » se brancherait ici. */
export function buildSpawnSpec(opts: SpawnOptions): SpawnSpec {
const env: NodeJS.ProcessEnv = {
...process.env,
TERM: 'xterm-256color',
COLORTERM: 'truecolor',
};
if (opts.command === 'bash') {
return { file: 'bash', args: ['--norc'], env };
}
const args: string[] = [];
if (opts.resume) {
// `--resume` doit toujours s'exécuter dans le cwd d'origine (garanti par l'appelant — spike S1).
args.push('--resume', opts.resume.claudeSessionId);
if (opts.resume.fork) args.push('--fork-session');
}
// Session de groupe : relie plusieurs repos/worktrees dans une seule session (P6).
for (const dir of opts.addDirs ?? []) args.push('--add-dir', dir);
return { file: resolveClaudeBin(), args, env };
}