Session lifecycle
Resuming a conversation
Section titled “Resuming a conversation”A conversation lives on disk under its session id, so a later process can continue it.
const command = Command.open(Claude, { workingDir: '/proj' });await command.setMessage('Start the refactor').send();
const sessionId = command.sessionId; // keep thiscommand.close();
// Later, in another process entirely.const resumed = Command.resume(sessionId, Claude, { workingDir: '/proj' });await resumed.setMessage('Carry on where we left off').send();Whether a conversation is new or continued is stated explicitly, never inferred from the id being present. Every command carries an id, so inferring would make every one look like a resume — and asking the CLI to resume an id it has never seen fails outright with No conversation found.
Interrupting and stopping
Section titled “Interrupting and stopping”These are different actions and should not be confused.
command.interrupt(); // stop the turn, keep the conversationcommand.close(); // stop the CLI and everything it spawnedWhat interrupt actually leaves behind
Section titled “What interrupt actually leaves behind”Measured against claude 2.1.170, not assumed. The CLI answers on the control channel and ends the turn with a ResultEvent whose subtype is error_during_execution — which here means interrupted, not broken. The process then stays up but does not serve further messages: a turn sent afterwards gets no reply.
So the sequence a host wants is interrupt, then stop, then resume:
command.interrupt();command.close();
const next = Command.resume(command.sessionId, Claude, { workingDir: '/proj' });await next.setMessage('Try a different approach').send();The conversation survives on disk; only this process is spent. Interrupting still beats calling close() alone, because the CLI writes its result and closes the transcript entry rather than being killed mid-write.
Inspecting the session underneath
Section titled “Inspecting the session underneath”A Command exposes the session it is driving, for inspection rather than for driving.
command.isLive(); // whether a CLI process is running right nowcommand.sessionId; // the conversation's idcommand.session; // Session | null — pid, mode, stderrcommand.session?.diagnostics; // what the CLI wrote to stderrdiagnostics is the one to reach for when a CLI fails to start: the protocol stream carries a result saying the run errored, but the reason — a bad flag, a missing login, a version mismatch — is on stderr and nowhere else.
Where to go next
Section titled “Where to go next”- Permission modes — the other reason a session gets replaced.
- Orphan recovery — what happens when the host dies before
close()runs.