E535 Make control_timeout configurable via session opts by john-walter · Pull Request #22 · guess/claude_code · GitHub
[go: up one dir, main page]

Skip to content

Make control_timeout configurable via session opts#22

Open
john-walter wants to merge 4 commits intoguess:mainfrom
bright-harbor:develop
Open

Make control_timeout configurable via session opts#22
john-walter wants to merge 4 commits intoguess:mainfrom
bright-harbor:develop

Conversation

@john-walter
Copy link
@john-walter john-walter commented Mar 9, 2026

Allow overriding the 30s default control timeout via a session opt. Maintains a fixed upper limit to the user defined timeout (120s) to support the GenServer client exit timeout.

Allow overriding the 30s default control timeout by setting:

    config :claude_code, control_timeout: 60_000

Falls back to the existing @control_timeout module attribute (30s)
when not configured.
@john-walter
Copy link
Author

We have encountered issues with the hardcoded value when using certain mcp servers that take longer to launch

@guess
Copy link
Owner
guess commented Mar 10, 2026

Thanks for the contribution @john-walter! A few things to address before merging:

  1. Consider a session option – A global app config works, but I'm wondering if it would also make sense to support control_timeout as a session option via start_link (stored in the GenServer state). Since this is happening when certain MCP servers take longer to launch, it might make sense for different sessions to define different timeouts depending on their mcp config looks like.
  2. Tests — Please add a test that verifies the timeout is respected when passed as a session option.
  3. Documentation — The new option should be documented in ClaudeCode.Options, consistent with where the other app-level / session-level options are defined.

@john-walter
Copy link
Author
john-walter commented Mar 10, 2026

Thanks for the contribution @john-walter! A few things to address before merging:

  1. Consider a session option – A global app config works, but I'm wondering if it would also make sense to support control_timeout as a session option via start_link (stored in the GenServer state). Since this is happening when certain MCP servers take longer to launch, it might make sense for different sessions to define different timeouts depending on their mcp config looks like.
  2. Tests — Please add a test that verifies the timeout is respected when passed as a session option.
  3. Documentation — The new option should be documented in ClaudeCode.Options, consistent with where the other app-level / session-level options are defined.

Alright I 8000 updated it - by making the control timeout a session specific detail and not global does mean that the overarching genserver call timeout no longer can be something directly derived from a given session timeout. I just decided to set a sane upper limit (120s) for the happy path control timeout and defaulted the genserver timeout to be slightly higher than that. Let me know if you want a different approach here. In our particular case the mcp server init ranges between 25-50 seconds so fine with bringing the max down lower. I was considering making the client_control_exit_timeout configurable but it seems like its more of a failsafe implementation detail than something a user really should be aware of.

@john-walter john-walter changed the title Make control_timeout configurable via application config Make control_timeout configurable via session opts Mar 10, 2026
@guess
Copy link
Owner
guess commented Mar 10, 2026

Nice, thanks for the quick turnaround!

Couple suggestions–

  1. Use :infinity for the GenServer.call timeout instead of a hard-coded upper bound – safe because Process.send_after always fires, so the caller can't block indefinitely. Then we can get rid of the validation cap.
def send_control_request(adapter, subtype, params) do
  GenServer.call(adapter, {:control_request, subtype, params}, :infinity)
end
def validate_control_timeout(value) when is_integer(value) and value > 0, do: {:ok, value}
def validate_control_timeout(value), do: {:error, "expected a positive integer, got: #{inspect(value)}"}
  1. Move the default into the NimbleOptions schema (default: 30_000) rather than Keyword.get(opts, :control_timeout, 30_000) in Port.init/1 — then it's always set after validation and the fallback in init/1 can be removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0