Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
95b7160
test(mention): reproduce the mention-queue findings A to H
ThomasK33 Nov 10, 2026
e209cac
fix(mention): deliver queued @mentions once, in order, or report an e…
ThomasK33 Nov 10, 2026
986f31b
test(mention): cover a stop that races a pending timeout, the stop re…
ThomasK33 Nov 10, 2026
fe78698
fix(mention): trust only the broadcast result in a flush, and cover t…
ThomasK33 Nov 10, 2026
cf7190d
Merge remote-tracking branch 'origin/main' into fix/mention-queue-del…
ThomasK33 Nov 10, 2026
fc19b4b
docs(mention): describe the queue that delivers or reports, and re-re…
ThomasK33 Nov 10, 2026
16dce7b
fix(mention): relativize a path only when it is inside the cwd, and m…
ThomasK33 Nov 10, 2026
68233f8
docs(mention): state when a mention path becomes relative, and re-rec…
ThomasK33 Nov 10, 2026
f7b139f
test(mention): pin the bad-path refusal and the timeout anchor, and a…
ThomasK33 Nov 10, 2026
dd981a5
test(mention): drop the randomized check from the suite
ThomasK33 Nov 10, 2026
d6f3d06
Merge remote-tracking branch 'origin/main' into fix/mention-queue-del…
ThomasK33 Nov 10, 2026
ae8385b
test(server): pin the mock broadcast result, and fix the connection_w…
ThomasK33 Nov 10, 2026
dcfecdc
fix(mention): show an error when a mention's write fails after a clie…
ThomasK33 Nov 10, 2026
e50cbff
docs(mention): describe the write report, and re-record the diff model
ThomasK33 Nov 10, 2026
20a429e
Merge remote-tracking branch 'origin/main' into fix/mention-queue-del…
ThomasK33 Nov 10, 2026
be31e96
Merge remote-tracking branch 'origin/main' into fix/mention-queue-del…
ThomasK33 Nov 10, 2026
7a8a657
Merge remote-tracking branch 'origin/main' into fix/mention-queue-del…
ThomasK33 Nov 10, 2026
f9b45c6
Merge remote-tracking branch 'origin/main' into fix/mention-queue-del…
ThomasK33 Nov 10, 2026
ee2a87b
test(mention): cover the write report of the immediate send, and a mi…
ThomasK33 Nov 10, 2026
1257489
Merge remote-tracking branch 'origin/main' into fix/mention-queue-del…
ThomasK33 Nov 10, 2026
3f42e01
Merge remote-tracking branch 'origin/main' into fix/mention-queue-del…
ThomasK33 Nov 10, 2026
2cf9bc4
fix(mention): do not postpone a due flush on another client's handshake
ThomasK33 Nov 10, 2026
aefe6dd
chore(skills): re-record the diff model for the handshake flush change
ThomasK33 Nov 10, 2026
7ee279f
fix(server): report a write that libuv refuses at once to its callback
ThomasK33 Nov 10, 2026
4ba9342
chore(skills): re-record the diff model for the refused-write report
ThomasK33 Nov 10, 2026
b7b5aa3
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 10, 2026
7e8860c
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 10, 2026
42bb41e
fix(mention): send a flush only once a connected client has had conne…
ThomasK33 Nov 10, 2026
c97b612
chore(skills): re-record the diff model for the flush readiness change
ThomasK33 Nov 10, 2026
0585211
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 10, 2026
e96a298
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 10, 2026
e0131fb
fix(mention): bound the wait for a ready Claude, and pin the readines…
ThomasK33 Nov 10, 2026
7bc97b9
test(mention): the bound on the wait for a ready Claude starts again …
ThomasK33 Nov 10, 2026
d1a6724
chore(skills): re-record the diff model after the readiness bound and…
ThomasK33 Nov 10, 2026
9673160
fix(mention): give each queued mention a deadline that no handshake m…
ThomasK33 Nov 10, 2026
a063770
test(mention): a flush that the deadline cancelled does not send a la…
ThomasK33 Nov 10, 2026
46add4e
test(mention): fail a run whose timers keep firing without letting ti…
ThomasK33 Nov 10, 2026
3539f86
test(mention): fail fast when the timers keep firing at one moment
ThomasK33 Nov 10, 2026
cde121b
chore(skills): re-record the diff model after the mention deadline ch…
ThomasK33 Nov 10, 2026
d13f93d
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 11, 2026
3391909
chore(skills): re-record the diff model after merging main into the m…
ThomasK33 Nov 11, 2026
cefe258
docs(fixtures): name the mention deadline in the issue-70 notes
ThomasK33 Nov 11, 2026
5f35b11
fix(server): stop a large frame at a piece that libuv refuses at once
ThomasK33 Nov 11, 2026
cf824cd
chore(skills): re-record the diff model after the refused-piece fix
ThomasK33 Nov 11, 2026
ad864db
fix(mention): let a ready Claude drain the queue past the deadline
ThomasK33 Nov 11, 2026
4f1c2e2
chore(skills): re-record the diff model after the drain rule
ThomasK33 Nov 11, 2026
5b00e9f
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 11, 2026
e625545
fix(mention): keep a flush due when the deadline spares the queue for…
ThomasK33 Nov 11, 2026
3de15f5
chore(skills): re-record the diff model after the spared-queue flush
ThomasK33 Nov 11, 2026
d514686
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 11, 2026
eb40d51
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 11, 2026
59eccb9
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 11, 2026
a439472
Merge remote-tracking branch 'origin/main' into fix/mention-flush-han…
ThomasK33 Nov 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .agents/skills/verify-diff-lifecycle/covered.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
== lua/claudecode/config.lua
file lua/claudecode/config.lua b4eaec92b6d04b40
file lua/claudecode/config.lua 787fa0432d1d77d7
== lua/claudecode/cwd.lua
file lua/claudecode/cwd.lua 55d26ea362173afa
== lua/claudecode/diff.lua
Expand Down Expand Up @@ -125,7 +125,7 @@ site lua/claudecode/diff_inline.lua: resolution_callback = resolution_callback,
== lua/claudecode/health.lua
file lua/claudecode/health.lua 5ab73bf388f3ac97
== lua/claudecode/init.lua
file lua/claudecode/init.lua f7c7fff32489cedd
file lua/claudecode/init.lua fc28de832b4056df
block user_close_all 10e024fd8ada1c16
site lua/claudecode/init.lua: local pending = diff.close_pending_diffs("user command") @ function M._create_commands()
site lua/claudecode/init.lua: local rejected = diff.close_rejected_diffs("user command") @ function M._create_commands()
Expand All @@ -139,7 +139,7 @@ file lua/claudecode/logger.lua 17b404dda41c3591
== lua/claudecode/selection.lua
file lua/claudecode/selection.lua 4d6678af786fa69f
== lua/claudecode/server/client.lua
file lua/claudecode/server/client.lua d630d84ea8ce44a7
file lua/claudecode/server/client.lua b8165df16f194471
block create_client 24fa2a266b76e6ad
== lua/claudecode/server/frame.lua
file lua/claudecode/server/frame.lua 3c50766875878d56
Expand Down Expand Up @@ -211,7 +211,7 @@ file lua/claudecode/tools/open_file.lua 6c7154d5427af9df
== lua/claudecode/tools/save_document.lua
file lua/claudecode/tools/save_document.lua df68d71e47300988
== lua/claudecode/types.lua
file lua/claudecode/types.lua 8028e6f291700f28
file lua/claudecode/types.lua dbd0dcb8b70c8107
== lua/claudecode/utils.lua
file lua/claudecode/utils.lua c4a21fe74858afe2
== lua/claudecode/visual_commands.lua
Expand Down
2 changes: 1 addition & 1 deletion dev-config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ return {

-- Connection Management
-- connection_wait_delay = 600, -- Wait time after Claude's handshake before sending queued @ mentions (ms)
-- connection_timeout = 10000, -- Max time queued @ mentions wait for Claude Code to connect (ms)
-- connection_timeout = 10000, -- Time Claude Code has to connect before queued @ mentions time out (ms)
-- queue_timeout = 5000, -- Unused, still accepted: queued @ mentions wait up to connection_timeout

-- Diff Integration
Expand Down
9 changes: 5 additions & 4 deletions fixtures/issue-70/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
## The one fact behind every report

`:ClaudeCodeSend` (and the file/buffer/tree senders) call `send_at_mention`. When
Claude is not connected, the mention is **queued** and a `connection_timeout`
timer (default **10s**, `lua/claudecode/init.lua`) is armed. If Claude has not
opened a WebSocket back to the plugin's server by then, the queue is cleared with
the error above (`start_connection_timeout_if_needed`).
Claude is not connected, the mention is **queued** with a deadline,
`connection_timeout + connection_wait_delay` after the send (default **10.6s**,
`lua/claudecode/init.lua`). If no Claude has opened a WebSocket back to the
plugin's server and taken the mention by then, the mention is cleared with the
error above (`expire_mentions`).

So the bug is never really "send is broken" — it is always **"the Claude CLI that
the plugin launched never connected back to the plugin's WebSocket server."** The
Expand Down
4 changes: 2 additions & 2 deletions lua/claudecode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Module map (direct files):
- `M.state`: `config`, `server`, `port`, `auth_token`, `initialized`, `mention_queue`, `mention_timer`, and `connection_timer` [init.lua:M.state]
- `M.is_claude_connected()`: false when the server is not running. When `get_status().clients` is non-empty, true only when a client is in state `connected` with `handshake_complete`, so a `closing` client does not count. When it is empty, true when `client_count > 0`, with no handshake check [init.lua:M.is_claude_connected]
- `M.send_at_mention(file_path, start_line?, end_line?, context?) -> ok, err?`: line numbers are 0-indexed [init.lua:M.send_at_mention]
- `M.process_mention_queue(from_new_connection?)`: the server's `on_open` callback calls it with `true` once a client completed its WebSocket handshake. Without the argument it sends the oldest queued mention now [init.lua:M.process_mention_queue]
- `M.process_mention_queue(from_new_connection?)`: the server's `on_open` callback calls it with `true` once a client completed its WebSocket handshake. Without the argument it flushes the queue now. A flush sends the oldest mention only once some connected client has been connected for `connection_wait_delay` ms, and otherwise waits for that moment [init.lua:M.process_mention_queue]
- `M.open_with_model(args)`, `M.get_version()`, and `M.version`, read from the repository's `VERSION` file at load [init.lua:M.version]
- Internal API: `M._create_commands`, `M._broadcast_at_mention`, `M._add_paths_to_claude` (default `max_files` 100, `batch_size` 10), `M._format_path_for_at_mention`, `M._ensure_terminal_visible_if_connected`, and `M._maybe_warn_unfocusable_provider` [init.lua:M._add_paths_to_claude]

Expand Down Expand Up @@ -111,7 +111,7 @@ Module map (direct files):

- Line numbers sent to Claude are 0-indexed. `:ClaudeCodeAdd` converts the 1-indexed input [init.lua:M._create_commands]
- A mention sent while disconnected goes to the queue with the same absolute path as a connected send, and the terminal opens. A connected send goes to the queue too, unless broadcast debouncing is off and the queue is empty [init.lua:M._broadcast_at_mention]
- The queue sends each mention once, oldest first: 50 ms after a send, `connection_wait_delay` ms after a client completed its handshake, and 25 ms apart. A mention leaves the queue only when a connected client took it. When the write of that frame then fails on every client, the error "Claude's connection failed while the @ mention <path> was sent" appears, and the mention is not sent again. When Claude is not connected, the mentions wait up to `connection_timeout` ms for a handshake, then the queue is cleared with the error "Connection timeout - clearing N queued @ mentions". A handshake stops that timeout, and a flush that finds no connected client starts it again. `queue_timeout` is accepted but unused [init.lua:schedule_mention_flush]
- The queue sends each mention once, oldest first: 50 ms after a send, `connection_wait_delay` ms after a client completed its handshake, and 25 ms apart. A mention goes out only once some connected client completed its handshake `connection_wait_delay` ms ago, so another client's handshake does not postpone it [init.lua:ms_until_a_client_is_ready]. The broadcast then reaches every connected client, also one that connected later and is still in its own wait. A mention leaves the queue only when a connected client took it. When the write of that frame then fails on every client, the error "Claude's connection failed while the @ mention <path> was sent" appears, and the mention is not sent again. Each mention has a deadline, `connection_timeout + connection_wait_delay` ms after its send, and no handshake or disconnect moves it. At its deadline, a mention still in the queue is cleared with the error "Connection timeout - clearing N queued @ mentions", or with "Send timeout - clearing N queued @ mentions that the connected Claude did not take in time" while a client that is not ready yet is connected [init.lua:expire_mentions]. While a ready client is connected, no deadline clears a mention: the queue drains to it, 25 ms apart. When that client leaves, the next flush clears the mentions whose deadline passed meanwhile [init.lua:flush_mention_queue]. A client that completes its handshake less than `connection_timeout` ms after the send, and stays connected, is ready before the deadline and gets every queued mention. `queue_timeout` is accepted but unused [init.lua:schedule_mention_flush]
- `M.stop` clears the queue and stops its timers. A queue timer's callback does nothing once its timer was stopped or replaced, so nothing queued before a stop reaches Claude [init.lua:start_timer]
- Selection tracking is a no-op unless it is enabled. Updates are debounced by 100 ms, except that leaving visual mode, editing or consuming the held text and moving the cursor away from a held selection report at once [selection.lua:M.flush_visual_selection] [selection.lua:reconcile_held_selection]. The held text can also change while you are in the Claude terminal (a reload, a plugin's edit), where `TextChanged` does not fire for its buffer: a listener from `nvim_buf_attach` on that buffer sends the file's cursor then [selection.lua:watch_selection_buffer]. Entering another file waits for the debounce. Claude terminal buffers are skipped [selection.lua:M.update_selection]
- The automatic paths send `selection_changed` only when the selection differs from the last one sent [selection.lua:M.update_selection] [selection.lua:M.flush_visual_selection]. `send_current_selection` sends with no change check [selection.lua:M.send_current_selection]
Expand Down
4 changes: 3 additions & 1 deletion lua/claudecode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ M.defaults = {
focus_after_send = false,
visual_demotion_delay_ms = 50, -- Milliseconds to wait before demoting a visual selection
connection_wait_delay = 600, -- Milliseconds to wait after connection before sending queued @ mentions
connection_timeout = 10000, -- Maximum time queued @ mentions wait for Claude Code to connect (milliseconds)
-- Milliseconds Claude Code has to connect for queued @ mentions. Each one leaves with an error connection_timeout +
-- connection_wait_delay ms after its send, unless a ready Claude takes the queue first.
connection_timeout = 10000,
queue_timeout = 5000, -- Unused, kept so that configs that set it stay valid (connection_timeout bounds the wait)
diff_opts = {
layout = "vertical",
Expand Down
119 changes: 86 additions & 33 deletions lua/claudecode/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,31 @@ function M.is_claude_connected()
end
end

---@return number|nil wait Milliseconds until some connected client completed its handshake connection_wait_delay ms
--- ago: 0 when one did, nil when no connected client reports when it connected
local function ms_until_a_client_is_ready()
local wait
for _, info in ipairs(require("claudecode.server.init").get_status().clients or {}) do
if info.state == "connected" and info.handshake_complete == true and info.connected_at then
local left = math.max(0, info.connected_at + M.state.config.connection_wait_delay - vim.loop.now())
wait = wait and math.min(wait, left) or left
end
end
return wait
end

-- The @ mention queue. A send that does not go out at once waits in M.state.mention_queue, oldest first. A mention
-- leaves the queue only when a connected Claude took it, when its wait timed out with an error, or when the
-- integration stops. While the queue holds a mention, one of two timers runs:
-- - M.state.mention_timer is the next flush: 50 ms after a send, connection_wait_delay ms after Claude's handshake,
-- or 25 ms after the previous mention went out. A flush sends only the oldest mention, so the order holds.
-- - M.state.connection_timer runs while the mentions wait for Claude to connect. After connection_timeout ms it clears
-- them with an error. Claude's handshake stops it, and a flush that finds no connected Claude starts it.
-- leaves the queue only when a connected Claude took it, when its deadline passed while no client was ready, or when
-- the integration stops. Two timers move it on:
-- - M.state.mention_timer is the next flush, while Claude is connected: 50 ms after a send, connection_wait_delay ms
-- after Claude's handshake, or 25 ms after the previous mention went out. A flush sends only the oldest mention, so
-- the order holds, and only once some connected client is ready: it completed its handshake connection_wait_delay
-- ms ago.
-- - M.state.connection_timer clears the mentions whose deadline passed, connection_timeout + connection_wait_delay ms
-- after their send, with an error. No handshake or disconnect moves a deadline. A Claude that completes its
-- handshake less than connection_timeout ms after the send, and stays connected, is ready before the deadline.
-- While a ready client is connected, no deadline clears a mention: the queue drains to it, 25 ms apart. A flush that
-- finds no ready client clears the mentions whose deadline passed meanwhile, and starts the timer again.
-- A timer's callback runs on the main loop and does nothing once its timer was stopped or replaced, so a stop cancels
-- every pending flush and timeout.
local debounce_delay = 50 -- ms from a send to its flush, so a burst of sends goes out as one batch
Expand Down Expand Up @@ -141,21 +159,42 @@ end

local schedule_mention_flush

---Start the timeout of the mentions that wait for Claude to connect, unless it runs already.
local function start_connection_timeout_if_needed()
if M.state.connection_timer then
---Clear the queued mentions whose deadline passed, with an error, then wait for the deadline of the oldest one left.
---The connection_timer callback: the timer may fire for a mention that went out since, and then clears nothing.
---While a ready client is connected, it clears nothing and stops: the queue drains to that client, and a flush that
---finds no ready client calls it again.
local function expire_mentions()
if ms_until_a_client_is_ready() == 0 then
-- A flush must be due, so that the drain goes on, or finds the client gone and calls this again. The handshake's
-- own flush can come later than this: Neovim runs the scheduled callbacks in order, late when its loop was busy.
schedule_mention_flush(inter_message_delay)
return
end
start_timer("connection_timer", M.state.config.connection_timeout, function()
local queue = mention_queue()
if #queue > 0 and not M.is_claude_connected() then
logger.error("queue", "Connection timeout - clearing " .. #queue .. " queued @ mentions")
clear_mention_queue()
local queue = mention_queue()
local now = vim.loop.now()
local expired = 0
-- Deadlines grow with the queue order, so the mentions whose deadline passed are the oldest ones.
while expired < #queue and queue[expired + 1].deadline <= now do
expired = expired + 1
end
if expired > 0 then
if M.is_claude_connected() then
logger.error(
"queue",
"Send timeout - clearing " .. expired .. " queued @ mentions that the connected Claude did not take in time"
)
else
-- Claude completed its handshake, and the flush that the handshake schedules has not run yet.
schedule_mention_flush(M.state.config.connection_wait_delay)
logger.error("queue", "Connection timeout - clearing " .. expired .. " queued @ mentions")
end
end)
for _ = 1, expired do
table.remove(queue, 1)
end
end
if #queue == 0 then
clear_mention_queue()
else
start_timer("connection_timer", queue[1].deadline - now, expire_mentions)
end
end

---A server.broadcast callback that shows an error when no write of the mention succeeded: the connection failed after
Expand All @@ -180,35 +219,41 @@ local function flush_mention_queue()
end
-- M.stop clears the queue when it drops the server, and the stop cancels this flush too.
local server = assert(M.state.server, "the @ mention queue holds mentions while the integration is stopped")
-- A mention goes out only once some connected client has been connected for connection_wait_delay ms. The broadcast
-- then reaches every connected client, also one that connected later. Another client's handshake cannot postpone it.
local wait = ms_until_a_client_is_ready()
if wait and wait > 0 then
-- A ready client that took the queue may have left: the mentions whose deadline passed meanwhile leave now.
expire_mentions()
if #mention_queue() > 0 then
start_timer("mention_timer", wait, flush_mention_queue)
end
return
end

local mention = queue[1]
local params = { filePath = mention.file_path, lineStart = mention.start_line, lineEnd = mention.end_line }
if not server.broadcast("at_mentioned", params, report_unwritten("queue", mention.file_path)) then
-- No connected client took the frame, as Claude went away since this flush was scheduled. The mention waits for
-- Claude's next handshake, or times out with an error.
-- Claude's next handshake, or for its deadline. One that passed while a ready client took the queue leaves now.
logger.debug("queue", "No connected client took queued @ mention: " .. mention.file_path)
start_connection_timeout_if_needed()
expire_mentions()
return
end
table.remove(queue, 1)
logger.debug("queue", "Sent queued @ mention: " .. mention.file_path)
schedule_mention_flush(inter_message_delay)
end

---Keep the queue moving. While Claude is connected, a flush is due: in delay ms, unless one is due already. Otherwise
---the connection timeout runs. An empty queue stops both timers.
---Keep the queue moving. While Claude is connected, a flush is due: in delay ms, unless one is due already. An empty
---queue stops both timers.
---@param delay number Milliseconds to the flush when Claude is connected and no flush is due yet
schedule_mention_flush = function(delay)
if #mention_queue() == 0 then
stop_timer("mention_timer")
stop_timer("connection_timer")
elseif M.is_claude_connected() then
stop_timer("connection_timer")
if not M.state.mention_timer then
start_timer("mention_timer", delay, flush_mention_queue)
end
else
start_connection_timeout_if_needed()
elseif M.is_claude_connected() and not M.state.mention_timer then
start_timer("mention_timer", delay, flush_mention_queue)
end
end

Expand All @@ -218,17 +263,25 @@ end
---@param end_line number|nil Optional end line
local function queue_mention(file_path, start_line, end_line)
local queue = mention_queue()
table.insert(queue, { file_path = file_path, start_line = start_line, end_line = end_line })
-- Claude has connection_timeout ms to complete its handshake, and connection_wait_delay ms after it to get ready.
local timeout = M.state.config.connection_timeout + M.state.config.connection_wait_delay
local deadline = vim.loop.now() + timeout
table.insert(queue, { file_path = file_path, start_line = start_line, end_line = end_line, deadline = deadline })
logger.debug("queue", "Queued @ mention: " .. file_path .. " (queue size: " .. #queue .. ")")
if not M.state.connection_timer then
start_timer("connection_timer", timeout, expire_mentions)
end
schedule_mention_flush(debounce_delay)
end

---Process the mention queue. Claude completed its WebSocket handshake when from_new_connection is true (the server's
---on_open callback): the queue then flushes connection_wait_delay ms later, so that Claude is ready for the mentions.
---@param from_new_connection boolean|nil true after a handshake; otherwise the oldest mention goes out now
---on_open callback): a flush is due in connection_wait_delay ms unless one is due already. Without the argument, the
---flush runs now.
---Either way, a flush sends the oldest mention only once some connected client has been connected for
---connection_wait_delay ms, and otherwise waits for that moment (see flush_mention_queue).
---@param from_new_connection boolean|nil true after a handshake; otherwise the queue flushes now
function M.process_mention_queue(from_new_connection)
if from_new_connection then
stop_timer("mention_timer")
schedule_mention_flush(M.state.config.connection_wait_delay)
else
flush_mention_queue()
Expand Down Expand Up @@ -1343,7 +1396,7 @@ function M._broadcast_at_mention(file_path, start_line, end_line)
queue_mention(formatted_path, start_line, end_line)

-- Always return success since we're queuing the message. The queue sends it to a connected Claude, or shows an
-- error when Claude does not connect within connection_timeout.
-- error when no ready Claude took it by its deadline, connection_timeout + connection_wait_delay ms after the send.
return true, nil, sent
end

Expand Down
Loading
Loading