Summary
Two production-deployment guides state, in their Limitations tables, that the CLI automatically cleans up idle sessions after 30 minutes:
docs/setup/scaling.md — | **30-minute idle timeout** | Sessions without activity are auto-cleaned by the CLI |
docs/setup/backend-services.md — | **30-minute idle timeout** | Sessions without activity are auto-cleaned |
There is no such timeout. Idle-session cleanup is opt-in and off by default: sessions are cleaned up for inactivity only when a positive idle timeout is configured on the server, and nothing is configured by default.
Both guides target long-running, self-hosted, multi-user deployments — exactly the readers who check a Limitations table before deciding whether they need to implement session cleanup themselves.
Expected vs actual
|
|
| Expected, per both Limitations tables |
A session idle for 30 minutes is automatically cleaned up by the CLI. |
| Actual |
Nothing is cleaned up for inactivity unless a positive --session-idle-timeout is passed to the server. |
The rest of the documentation already says the opposite
docs/features/session-persistence.md — "By default, sessions have no idle timeout and live indefinitely until explicitly disconnected or deleted", and "Set to 0 or omit to disable." The sessionIdleTimeoutSeconds: 30 * 60 shown there is an example opt-in value, not a default.
docs/setup/multi-tenancy.md, under Common pitfalls — "Not setting sessionIdleTimeoutSeconds. Long-running servers can accumulate idle sessions if they do not clean them up." That pitfall only exists because there is no default.
nodejs/src/types.ts documents the option as @default undefined (disabled).
Both guides also contradict themselves within a few lines of the offending row:
docs/setup/scaling.md recommends "Run periodic cleanup to delete sessions older than your TTL" in its Production checklist, immediately above the Limitations table.
docs/setup/backend-services.md has an entire ## Session cleanup section with a hand-written cleanupSessions(maxAgeMs) on an interval, immediately above its Limitations table.
In both files the surrounding guidance matches reality; only the Limitations row is wrong.
Reproduction
The CLI logs a line at --log-level debug when it starts its idle-session checker, so a positive/negative pair settles this in seconds — there is no need to wait out an idle period.
Tested with CLI 1.0.81-10, the version pinned in nodejs/package-lock.json. Note that --session-idle-timeout does not appear in copilot --help, the same as --port and --headless, which these guides already instruct readers to pass.
mkdir -p logs-a logs-b
# Arm A (control): idle timeout configured
timeout 12 copilot --headless --no-auto-update --port 47321 \
--log-level debug --log-dir "$PWD/logs-a" --session-idle-timeout 300
# Arm B: the default, option not passed
timeout 12 copilot --headless --no-auto-update --port 47322 \
--log-level debug --log-dir "$PWD/logs-b"
grep -rh "Started session timeout checker" logs-a/ | wc -l
grep -rh "Started session timeout checker" logs-b/ | wc -l
Result:
Arm A logs:
[DEBUG] Started session timeout checker (timeout: 300000ms, check interval: 300000ms)
[DEBUG] Stopped session timeout checker
Arm B logs no such line, and no idle- or stale-session activity of any kind.
Debug logging is live in both arms: this run produced 22 and 20 [DEBUG] lines, differing by exactly arm A's two checker lines, so arm B's zero is a real absence rather than a logging gap. Exact counts vary by version and environment; the point is that arm B logs normally and simply never mentions a checker. (timeout exits 124 in both arms because the server runs until it is stopped; that is expected.)
This reproduces the same way through the SDK: with sessionIdleTimeoutSeconds set, the SDK spawns the CLI with --session-idle-timeout and the checker starts; with the option omitted, the flag is absent and no checker is started.
Suggested fix
Docs-only, one row in each file. Replace both rows with the opt-in framing already used by docs/features/session-persistence.md.
Note that sessionIdleTimeoutSeconds is not the right lever to name in these two guides specifically: both describe connecting to a separately launched CLI server, and nodejs/src/types.ts documents the SDK option as "Ignored when connecting to an existing runtime via RuntimeConnection.forUri". docs/setup/multi-tenancy.md already states the same rule — with RuntimeConnection.forUri(...), configure the idle timeout on the runtime process itself. The server flag is also language-neutral, which matters because backend-services.md carries Python, Go, C# and Java examples.
Summary
Two production-deployment guides state, in their Limitations tables, that the CLI automatically cleans up idle sessions after 30 minutes:
docs/setup/scaling.md—| **30-minute idle timeout** | Sessions without activity are auto-cleaned by the CLI |docs/setup/backend-services.md—| **30-minute idle timeout** | Sessions without activity are auto-cleaned |There is no such timeout. Idle-session cleanup is opt-in and off by default: sessions are cleaned up for inactivity only when a positive idle timeout is configured on the server, and nothing is configured by default.
Both guides target long-running, self-hosted, multi-user deployments — exactly the readers who check a Limitations table before deciding whether they need to implement session cleanup themselves.
Expected vs actual
--session-idle-timeoutis passed to the server.The rest of the documentation already says the opposite
docs/features/session-persistence.md— "By default, sessions have no idle timeout and live indefinitely until explicitly disconnected or deleted", and "Set to0or omit to disable." ThesessionIdleTimeoutSeconds: 30 * 60shown there is an example opt-in value, not a default.docs/setup/multi-tenancy.md, under Common pitfalls — "Not settingsessionIdleTimeoutSeconds. Long-running servers can accumulate idle sessions if they do not clean them up." That pitfall only exists because there is no default.nodejs/src/types.tsdocuments the option as@default undefined (disabled).Both guides also contradict themselves within a few lines of the offending row:
docs/setup/scaling.mdrecommends "Run periodic cleanup to delete sessions older than your TTL" in its Production checklist, immediately above the Limitations table.docs/setup/backend-services.mdhas an entire## Session cleanupsection with a hand-writtencleanupSessions(maxAgeMs)on an interval, immediately above its Limitations table.In both files the surrounding guidance matches reality; only the Limitations row is wrong.
Reproduction
The CLI logs a line at
--log-level debugwhen it starts its idle-session checker, so a positive/negative pair settles this in seconds — there is no need to wait out an idle period.Tested with CLI
1.0.81-10, the version pinned innodejs/package-lock.json. Note that--session-idle-timeoutdoes not appear incopilot --help, the same as--portand--headless, which these guides already instruct readers to pass.Result:
Arm A logs:
Arm B logs no such line, and no idle- or stale-session activity of any kind.
Debug logging is live in both arms: this run produced 22 and 20
[DEBUG]lines, differing by exactly arm A's two checker lines, so arm B's zero is a real absence rather than a logging gap. Exact counts vary by version and environment; the point is that arm B logs normally and simply never mentions a checker. (timeoutexits 124 in both arms because the server runs until it is stopped; that is expected.)This reproduces the same way through the SDK: with
sessionIdleTimeoutSecondsset, the SDK spawns the CLI with--session-idle-timeoutand the checker starts; with the option omitted, the flag is absent and no checker is started.Suggested fix
Docs-only, one row in each file. Replace both rows with the opt-in framing already used by
docs/features/session-persistence.md.Note that
sessionIdleTimeoutSecondsis not the right lever to name in these two guides specifically: both describe connecting to a separately launched CLI server, andnodejs/src/types.tsdocuments the SDK option as "Ignored when connecting to an existing runtime viaRuntimeConnection.forUri".docs/setup/multi-tenancy.mdalready states the same rule — withRuntimeConnection.forUri(...), configure the idle timeout on the runtime process itself. The server flag is also language-neutral, which matters becausebackend-services.mdcarries Python, Go, C# and Java examples.