Skip to content

feat: let Claude Code and Codex bots use Fast mode - #101

Merged
leepokai merged 5 commits into
leepokai:devfrom
icework:feat/fast-mode
Oct 15, 2026
Merged

leepokai merged 5 commits into
leepokai:devfrom
icework:feat/fast-mode

Conversation

@icework

@icework icework commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Claude Code's and Codex's ACP adapters both offer Fast mode (faster replies for more usage) as a session config option, but Codync only ever set the model, so bots always ran at normal speed. This adds Fast mode per bot, switched live, with refusals reported and a toggle in the chat.

Host

  • BotConfig gets fastMode (wire fastMode, default off, additive).
  • Live switch, no restart. The host keeps each live session's Fast mode option as the agent last listed it. Sources: session/new (after the model switch, whose answer can change the options), session/load, session/fork, set_config_option answers and config_option_update. Before every turn it calls session/set_config_option when the value differs from the bot's setting. Both adapters start each session or process at their own default (a resumed session reports off), so resumed sessions are switched again.
  • Options are matched by ID: Claude's fast and Codex's fast-mode, each a select of on/off (booleans handled too).
  • Refusals. If the agent turns Fast mode off right after the bot asked, the host reports fastModeSupport: refused, with the agent's reason in fastModeIssue. Claude does this for an account without extra usage, and appends the reason to the option's description. The host then stops asking until the user changes the setting or the host restarts, instead of re-asking (and Claude re-announcing "turned off") on every session.
  • Bots carry fastModeSupport (unknown/offered/unsupported/refused). offered/unsupported survive host restarts (kv), so clients can show the toggle before a bot's first turn. Groups always report unknown.
  • agentModels returns fastMode: bool (the probe session offered it).
  • Session config-option parsing moves out of auth.rs (near the 500-line limit) into agent/config.rs; the actor side is agent/bot/fast_mode.rs.

Clients (shown for an agent bot whose runtime says offered/refused, or while it's on; never groups)

  • Desktop: a ⚡ button next to the composer's +, filled while on and warning-tinted while refused (the tooltip gives the reason). The settings switch row sits under Model; while refused, its detail gives the reason. Model loading moved into a useAgentModels hook so the switch can be its own card row.
  • iPhone: a "Fast mode" item (with checkmark) in the composer's + menu, and a ⚡ badge on + while on. The iPhone's + is a full-height button, so a second one would squeeze the field. The settings switch is its own card row, with the refusal reason.
  • Terminal UI: F toggles it for the selected bot (listed in help), the chat header shows ⚡ fast / ⚡ refused, and the form has a Fast mode field whose hint shows the refusal.

Docs: docs/features/marketplace.md (Fast mode section, including the fastModeSupport table), ui-conventions.md, file-structure.md. Version 2.15.0 (minor: feature plus additive protocol fields), with What's New.

Validation

  • Host: cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test pass. Unit tests cover option matching, value changes, refusal-reason parsing and support persistence. The wire shape was re-recorded (added fastMode, fastModeSupport, fastModeIssue). e2e::wire_shape_matches_the_snapshot failed once with an unrelated event:usage addition (this machine's real usage data landing in catch-up) and passed 3/3 on rerun.

  • e2e with a scripted ACP agent (turns_e2e):

    • fast_mode_switches_live_sessions_without_a_restart: on, then off, then on, all within one agent process; no session/load; exactly one on/off/on sequence.
    • a_refused_fast_mode_is_reported_and_not_asked_for_again: the agent turns it off mid-prompt the way Claude does. The bot reports refused with the reason and isn't asked again on the next turn; toggling the setting asks again.
  • Real agents, on an isolated host (own CODYNC_HOME and port) on macOS, with an ACP traffic logger in front of the adapters:

    • Codex (codex-acp 2.2.2): fast-mode=on accepted and kept through the turn. Turning it off and then on switched the same live session (set_config_option off, then on) with no new initialize/session/load, and the bot still remembered the first message.
    • Claude Code (claude-agent-acp 0.89.1, Claude Pro, Opus 5.5):
      • Without extra usage: Claude turned it back off mid-turn ("requires extra usage to be enabled for this account"), the case the refusal handling is for. The refusal path itself is covered by the scripted e2e test that mirrors Claude's config_option_update.
      • With extra usage on: four turns ran as on, on, off, on. Each was a live set_config_option on the same session (no restart or reload), there was no refusal, and context was kept ("Your first message asked me to reply with "ok 1""). A direct claude -p --settings '{"fastMode":true}' on the same account reports fast_mode_state: "on".
  • Desktop: npm run typecheck and npm test pass. In the renderer's web demo with stubbed bots: the composer ⚡ toggles between on and off, the refused state shows the warning tint with the reason in its tooltip, and the settings row shows the reason without a model list.

  • iPhone: xcodebuild test -scheme CodyncKit-Package on an iOS simulator passes (CodyncKit and CodyncUI, with new tests for decoding, the update payload and composer visibility).

  • All three clients against a real host (a codync-host built from this branch, with its own CODYNC_HOME and port). Its bots ran the scripted fast-mode agent, so no provider usage: one with Fast mode on, one off, and one the agent refuses.

    • Terminal UI (codync-host tui --url …, in tmux):
      • The header shows ⚡ fast / ⚡ refused and nothing when off.
      • F toggles the selected bot, and the host followed each press. On the refused bot, F clears the refusal.
      • The form's Fast mode field shows "The agent turned it off: requires extra usage…".
    • Desktop (unpackaged Codync Dev via CODYNC_PORT/CODYNC_HOME, driven over CODYNC_REMOTE_DEBUG):
      • The composer ⚡ shows on (filled), off, and refused (warning tint, with the reason in its tooltip).
      • Clicking it toggled the bot on the host both ways.
      • The refused bot's settings row shows the reason.
    • iPhone (iOS Dev simulator build in build/dd, paired with a codync-dev://pair link):
      • The + button has a ⚡ badge while on (orange while refused).
      • The + menu has "Fast mode" with a checkmark. Choosing it turned the bot off on the host, and the badge went away.
      • The refused bot's settings show Fast mode as its own row with the reason.

Not tested: Linux and Windows desktop. The renderer code is platform-neutral; the only platform-specific piece is the bolt symbol, which has a Lucide fallback.

What's New

zh-Hant

  • Claude Code 和 Codex 的 bot 可以開啟快速模式:回覆更快,用量也較多。在輸入框的 + 選單或 bot 設定裡切換,開啟時 + 按鈕上會出現閃電。帳號不能使用時,設定裡會說明原因。

en-US

  • Turn on Fast mode for Claude Code and Codex bots: faster replies for more usage. Switch it from the composer's + menu or the bot's settings; a bolt on the + button shows it's on. If your account can't use it, the settings say why.

icework and others added 3 commits October 11, 2026 19:01
Claude Code's and Codex's ACP adapters offer Fast mode (faster replies
for more usage) as a session config option, but Codync only ever set
the model, so bots always ran at normal speed.

- Bots get a `fastMode` setting. The host applies it after every
  session/new, session/load and session/fork, since the adapters start
  each session or process at their own default, and only sends
  session/set_config_option when the value differs.
- Changing it resumes the bot's sessions in a restarted agent, so the
  conversation context is kept.
- `agentModels` reports whether the agent offers Fast mode. The iPhone
  and desktop editors show a Fast mode switch under Model when it
  does (or while it's on); the terminal UI form gets the field too.
- Session config option parsing moves from auth.rs to agent/config.rs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Live switch: the host keeps each live session's Fast mode option (from
  every agent answer and config_option_update) and switches the session
  before its next turn, so changing the setting no longer restarts the
  agent.
- Refusals: when the agent turns Fast mode off right after the bot asked
  (Claude does this for an account without extra usage), the host
  reports it as `fastModeSupport: refused` with the agent's reason in
  `fastModeIssue`, and stops asking until the setting changes or the
  host restarts. Bots carry `fastModeSupport` (unknown, offered,
  unsupported, refused); offered/unsupported survive host restarts.
- Chat toggle: a ⚡ button by the composer's + on the desktop, a Fast
  mode item and ⚡ badge on the + menu on iPhone, and `F` plus a header
  badge in the terminal UI. Settings show the refusal reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@icework
icework marked this pull request as ready for review October 12, 2026 02:49
@leepokai

leepokai commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Hi @icework, thanks for this PR! We just opened a Discord server for Codync: https://discord.gg/JzMXd7gHAJ

It should make it much easier to talk through PRs and plans going forward, so it'd be great to have you there. This link gives you the Contributor role automatically when you join.

leepokai and others added 2 commits October 15, 2026 15:00
Brings the branch up to dev, whose code wins wherever the two overlap:
Cursor's per-model options (`modelOptions`) stay as dev has them, and
Fast mode is added on top.

- Fast mode only takes an on/off (or boolean) option, as Claude Code
  and Codex offer it. Cursor's `fast` (true/false) is one of a model's
  options, so it stays with the bot's model options; before this,
  Cursor bots showed the bolt and every turn tried to set `fast=off`,
  which Cursor rejects.
- The model list stays in `agent/auth.rs` as on dev; `agent/config.rs`
  holds only Fast mode.
- The model's options and Fast mode both show under Model in the
  desktop, iPhone and terminal editors.
- The Fast mode tests read bot state from the event stream (`sync` is
  gone on dev).
- Version 2.17.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QdZYFgoEZxruQEn7gcYMN2
@leepokai

Copy link
Copy Markdown
Owner

Thanks @icework, this is a great feature, and the validation write-up made it easy to check.

dev had moved a lot since this was opened (69 commits, 29 conflicting files), mostly from #112's per-model options for Cursor, so I merged dev into the branch myself, keeping dev's code where the two overlapped and your Fast mode on top:

  • Cursor fix. With parameterizedModelPicker, Cursor's sessions list a fast option too, but as true/false. Matching on the ID alone would have shown ⚡ on Cursor bots and sent fast=off before every turn, which Cursor rejects with Invalid params. Fast mode now only takes a boolean or an on/off select (what Claude's and Codex's adapters send); Cursor's fast stays one of the model's options (modelOptions).
  • The model list stays in agent/auth.rs as on dev; agent/config.rs holds only Fast mode. select_model also sets the model's options and returns the latest config options.
  • The editors on all three clients show the model's options and the Fast mode row under Model.
  • The Fast mode e2e tests read bot state from the event stream (sync is gone on dev).
  • Version files are left as on dev; the release bump follows there.

Checked on the real apps (Codync Dev desktop + iPhone simulator + terminal UI against a 2.17.0 dev host): live on/off switching on one session from each client, the refused state and its reason, a real Codex bot with Fast mode on, and a Cursor-shaped agent that no longer gets the toggle or the fast=off calls. CI is green on the merge commit.

@leepokai
leepokai merged commit d753e31 into leepokai:dev Oct 15, 2026
@github-actions

Copy link
Copy Markdown

Thanks for your first merged contribution, @icework! Join the Codync Discord with the Contributor role in one step: https://discord.codync.dev

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