How Nodeterm Implements Session ID Minting for Resumable Agent Sessions
Nodeterm mints a unique session ID using uuid() only during the initial creation of a Claude agent node when the underlying CLI advertises --session-id support, persisting this identifier in the node state to enable seamless session resumption across restarts.
The eneskirca/nodeterm project enables persistent agent sessions by implementing a sophisticated session ID minting system that bridges the gap between the Electron-based UI and CLI-based AI agents. This mechanism ensures that agents like Claude can resume interrupted conversations after the application restarts or the terminal node is reopened. Understanding how nodeterm generates, stores, and retrieves these identifiers requires examining the capability detection logic, workspace state management, and launch sequence coordination.
Understanding Session ID Capability Detection
Before minting any identifiers, nodeterm verifies that the target agent CLI actually supports session resumption. This capability check prevents incompatible flag injection and ensures backward compatibility.
The SESSION_ID_CAPABLE Flag
In src/shared/agents/config.ts, the system defines which agents can handle session IDs. Lines 281-285 declare the SESSION_ID_CAPABLE constant and the mintsSessionId(id) helper function, which returns true only for Claude-based agents:
// src/shared/agents/config.ts (lines 281-285)
export const SESSION_ID_CAPABLE = ['claude'];
export const mintsSessionId = (id: string) => SESSION_ID_CAPABLE.includes(id);
This strict whitelist ensures that session IDs are only generated for agents that explicitly advertise resumption support.
Caching CLI Capabilities
The capability probe claudeFlagSupported executes once and caches the result in the core process, exposing it through window.nodeTerminal.claude.cliCaps(). This cached value determines whether the workspace state manager should generate a UUID during node creation.
How Nodeterm Mints New Session IDs
Session ID generation occurs within the workspace state initialization logic in src/renderer/state/workspace.ts. When constructing a new agent node, the system checks the cached capability flag before minting.
Around line 575, the code evaluates whether to generate a fresh identifier:
// src/renderer/state/workspace.ts (approx. line 575)
const mintedSessionId = sessionIdFlagSupported ? uuid() : undefined;
// The minted ID is stored on the node so it survives reloads
{
// ... other node properties
sessionId: mintedSessionId,
}
// Later the node data is enriched:
...(mintedSessionId ? { agentSessionId: mintedSessionId } : {}),
The uuid() function generates a standard v4 UUID (e.g., 12f3e8d4-a1b2-4c3d-9e5f-6b7c8d9e0f12), which persists in the node's data structure. This identifier remains stable across application restarts, serving as the anchor for session resumption.
Injecting the Session ID into the Launch Command
After minting, the session ID must reach the CLI process. The launch sequence in src/shared/agents/launch.ts handles this injection dynamically.
Around lines 179-182, the code constructs the final command arguments:
// src/shared/agents/launch.ts (lines 179-182)
if (inputs.sessionId && mintsSessionId(capId) && inputs.sessionIdFlagSupported) {
return withAgentModel(
withSessionId(withMode, capId, inputs.sessionId),
capId,
inputs.model
);
}
The withSessionId utility appends the --session-id flag (or equivalent syntax for the specific agent) to the CLI invocation. This ensures the external agent process receives the persistent identifier, allowing it to associate its internal state with the specific nodeterm node.
Resuming Sessions with Live Hook IDs
The minted ID serves as a fallback mechanism. When a node restarts, the agent may supply a different session identifier through its /session-start hook, which takes precedence over the originally minted UUID.
The resolution logic lives in src/renderer/terminal/agent-restart.ts:
import { restartSessionId } from 'src/renderer/terminal/agent-restart';
// During node restart:
const idToUse = restartSessionId(liveHookId, node.data.agentSessionId);
// Returns: liveHookId if present, otherwise falls back to the minted ID
This prioritization ensures that if the agent generates its own session identifier during runtime, nodeterm respects that live ID while retaining the minted value as a persistent fallback for true cold starts.
Reading the Session Display Name
While the minted UUID maintains the technical session continuity, the user-facing title displayed in the node header derives from a different source. src/core/agent-session-name.ts extracts the readable session name from the transcript associated with the provider's session ID (whether live or minted), ensuring the UI reflects the actual conversation content rather than the raw UUID.
Summary
- Capability-gated generation: Nodeterm only mints session IDs in
src/renderer/state/workspace.tswhensessionIdFlagSupportedis true and the agent appears in theSESSION_ID_CAPABLEwhitelist. - UUID persistence: The minted identifier is generated once using
uuid()and stored in the node'sagentSessionIdproperty to survive application reloads. - Conditional CLI injection:
src/shared/agents/launch.tsappends--session-idonly when the node carries a minted ID and the CLI supports the flag. - Live ID precedence: During restarts,
src/renderer/terminal/agent-restart.tsprioritizes hook-supplied session IDs over the originally minted UUID. - Display abstraction: Session titles are resolved separately from the technical ID via
src/core/agent-session-name.ts.
Frequently Asked Questions
Which agents support session ID minting in nodeterm?
Currently, only Claude-based agents support session ID minting. The SESSION_ID_CAPABLE array in src/shared/agents/config.ts explicitly whitelists 'claude', and the mintsSessionId(id) helper returns true only for these agent types. Other agents skip the minting process entirely and launch without persistent session identifiers.
When is a session ID generated versus reused?
A new UUID is generated exactly once during the initial creation of the agent node in src/renderer/state/workspace.ts if sessionIdFlagSupported is true. On subsequent launches or restarts, nodeterm reuses the existing agentSessionId stored in the node data. If the agent's /session-start hook returns a live session ID during restart, that live identifier takes precedence for the runtime session while the minted ID remains in persistent storage.
What happens if the CLI doesn't support the --session-id flag?
If the capability probe fails or the cached sessionIdFlagSupported flag is false, src/renderer/state/workspace.ts sets mintedSessionId to undefined. Consequently, src/shared/agents/launch.ts skips the withSessionId wrapper, launching the agent without the flag. The session operates in ephemeral mode without resumption capabilities across restarts.
How does nodeterm handle session IDs after a restart?
During restart, src/renderer/terminal/agent-restart.ts calls restartSessionId(liveId, mintedId), which implements a fallback strategy: if the agent provided a liveId through its startup hook, that value is used; otherwise, the function returns the originally mintedId. This ensures continuity when possible while gracefully degrading to the persistent minted identifier when the agent doesn't supply a runtime session ID.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →