diff --git a/docs/features/session-persistence.md b/docs/features/session-persistence.md
index 19e53c385..a790a117a 100644
--- a/docs/features/session-persistence.md
+++ b/docs/features/session-persistence.md
@@ -433,14 +433,26 @@ await client.deleteSession("user-123-task-456");
## Automatic Cleanup: Idle Timeout
-The CLI has a built-in 30-minute idle timeout. Sessions without activity are automatically cleaned up:
+By default, sessions have **no idle timeout** and live indefinitely until explicitly disconnected or deleted. You can optionally configure a server-wide idle timeout via `CopilotClientOptions.sessionIdleTimeoutSeconds`:
+
+```typescript
+const client = new CopilotClient({
+ sessionIdleTimeoutSeconds: 30 * 60, // 30 minutes
+});
+```
+
+When a timeout is configured, sessions without activity for that duration are automatically cleaned up. The minimum value is 300 seconds (5 minutes). Set to `0` or omit to disable.
+
+> **Note:** This option only applies when the SDK spawns the runtime process. When connecting to an existing server via `cliUrl`, the server's own timeout configuration applies.
```mermaid
flowchart LR
- A["⚡ Last Activity"] --> B["⏳ 25 min
timeout_warning"] --> C["🧹 30 min
destroyed"]
+ A["⚡ Last Activity"] --> B["⏳ ~5 min before
timeout_warning"] --> C["🧹 Timeout
destroyed"]
```
-Listen for idle events to know when work completes:
+Sessions with active work (running commands, background agents) are always protected from idle cleanup, regardless of the timeout setting.
+
+Listen for idle events to react to session inactivity:
```typescript
session.on("session.idle", (event) => {
diff --git a/nodejs/src/client.ts b/nodejs/src/client.ts
index c5b84a6d4..fad4e7054 100644
--- a/nodejs/src/client.ts
+++ b/nodejs/src/client.ts
@@ -339,6 +339,7 @@ export class CopilotClient {
// Default useLoggedInUser to false when githubToken is provided, otherwise true
useLoggedInUser: options.useLoggedInUser ?? (options.githubToken ? false : true),
telemetry: options.telemetry,
+ sessionIdleTimeoutSeconds: options.sessionIdleTimeoutSeconds ?? 0,
};
}
@@ -1385,6 +1386,16 @@ export class CopilotClient {
args.push("--no-auto-login");
}
+ if (
+ this.options.sessionIdleTimeoutSeconds !== undefined &&
+ this.options.sessionIdleTimeoutSeconds > 0
+ ) {
+ args.push(
+ "--session-idle-timeout",
+ this.options.sessionIdleTimeoutSeconds.toString()
+ );
+ }
+
// Suppress debug/trace output that might pollute stdout
const envWithoutNodeDebug = { ...this.options.env };
delete envWithoutNodeDebug.NODE_DEBUG;
diff --git a/nodejs/src/types.ts b/nodejs/src/types.ts
index 0c901f989..59cbffac9 100644
--- a/nodejs/src/types.ts
+++ b/nodejs/src/types.ts
@@ -182,6 +182,15 @@ export interface CopilotClientOptions {
* instead of the server's default local filesystem storage.
*/
sessionFs?: SessionFsConfig;
+
+ /**
+ * Server-wide idle timeout for sessions in seconds.
+ * Sessions without activity for this duration are automatically cleaned up.
+ * Set to 0 or omit to disable (sessions live indefinitely).
+ * Minimum value: 300 (5 minutes).
+ * @default undefined (disabled)
+ */
+ sessionIdleTimeoutSeconds?: number;
}
/**