Skip to content

feat(send): User ClaudeCodeSendComplete event + warn on inert focus_after_send (#228)#265

Merged
ThomasK33 merged 3 commits into
mainfrom
feat/228-send-complete-event
Jun 8, 2026
Merged

feat(send): User ClaudeCodeSendComplete event + warn on inert focus_after_send (#228)#265
ThomasK33 merged 3 commits into
mainfrom
feat/228-send-complete-event

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

Closes #228.

Problem

focus_after_send focuses the in-editor Claude terminal, so it silently does nothing when terminal.provider = "none"/"external" — Claude runs outside Neovim, so there's no window to focus. No warning, and the limitation was undocumented.

What this does

This keeps focus_after_send boolean-only (it still auto-focuses the in-editor snacks/native providers) and adds:

  • User ClaudeCodeSendComplete autocmd — the provider-agnostic hook external-terminal users need. Fired once per file in send_at_mention's connected-success branch, with:

    vim.api.nvim_create_autocmd("User", {
      pattern = "ClaudeCodeSendComplete",
      callback = function(ev)
        -- ev.data = { file_path, start_line, end_line, context }
        if vim.env.TMUX then
          vim.fn.system({ "tmux", "select-pane", "-t", "{last}" }) -- your own target
        end
      end,
    })

    data.file_path is the formatted/cwd-relative path Claude received; start_line/end_line are 0-indexed (Claude convention) and may be nil for whole-file/directory sends. Emitted via a guarded, pcall-wrapped helper so a faulty handler can't break the send path.

  • A one-time setup warning when focus_after_send = true with provider = "none"/"external", pointing at the new event — so the limitation is explicit instead of silent.

Notes on semantics (documented in README "Events")

  • Fires at acceptance time, not delivery (sending is debounced; a later transport failure is logged, not reported here).
  • Fires per file — a multi-file tree send fires it once per file; keep handlers idempotent.
  • Fires only when Claude is already connected; a send that queues while Claude launches is delivered later without firing this event.

Docs

README ("Events" section + focus_after_send limitation + None-provider note), CHANGELOG, CLAUDE.md, and a ClaudeCodeSendCompleteData class in types.lua.

Tests

  • tests/unit/focus_after_send_provider_warning_spec.lua and tests/unit/send_complete_event_spec.lua (warning + event, including a real _broadcast_at_mention case that locks in the formatted-path/0-indexed payload — verified to fail under a raw-path mutation).
  • fixtures/issue-228/ — a deterministic headless regression gate (bash fixtures/issue-228/run.sh, 9/9) plus a live.lua TUI fixture.
  • mise run all: 535 passing / 0 failures, luacheck clean.

Not included

Option of overloading focus_after_send into boolean | function — the event subsumes that use case without overloading the flag; easy to add later if desired.

🤖 Generated with Claude Code

…ter_send (#228)

focus_after_send focuses the in-editor Claude terminal, so it silently did
nothing for terminal.provider = "none"/"external" (Claude runs outside Neovim)
— no warning, no docs (#228).

This adds two things:

(b) A `User ClaudeCodeSendComplete` autocmd, fired once per file in
    send_at_mention's connected-success branch, with
    `data = { file_path, start_line, end_line, context }`. file_path is the
    formatted/cwd-relative path Claude received; lines are 0-indexed and may be
    nil. This is the provider-agnostic hook external-terminal users need, e.g.
    to run `tmux select-pane` after a send. Emitted via a guarded, pcall-wrapped
    helper; _broadcast_at_mention now returns the formatted payload.

(c) A one-time setup warning when focus_after_send = true with
    provider = "none"/"external", pointing at the new event.

focus_after_send stays boolean-only and keeps auto-focusing the in-editor
providers; the warning makes the limitation explicit instead of silent.

Docs: README "Events" section + limitation notes, CHANGELOG, CLAUDE.md, and a
types.lua ClaudeCodeSendCompleteData class. Tests: two new specs (warning +
event, including real-broadcast formatted-path coverage) and the
fixtures/issue-228/ harness repurposed as a regression gate. mise run all: 535
passing, luacheck clean.

Change-Id: I5ec616baf192d0fc48d962c9bb5a637626a5baba
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@claude review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9230d9da68

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lua/claudecode/init.lua Outdated
…review)

Codex review flagged that a misconfigured `terminal.provider = "external"` (no
usable `external_terminal_cmd`) falls back to the native provider, where
`focus_after_send` works — so the #228 setup warning was a false positive there.

`_maybe_warn_unfocusable_provider` now keys off the *effective* provider:
"external" only warns when a usable `external_terminal_cmd` is configured
(mirroring `terminal.lua`'s `has_external_cmd` check); "none" still always warns.
Added regression tests for the string/function command forms (warn) and the
no-usable-command fallback (no warn).

Change-Id: Ia9dda8ebfd64cbba28075b9bcc6bc442f4bc973e
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b9b0081f3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lua/claudecode/init.lua
… review)

Codex review (P2): `nvim_exec_autocmds()` defaults `modeline = true` when no
`buf` is supplied, so firing this notification-only `User` event on every
connected send would re-process the current buffer's modeline — re-applying
buffer options or surfacing modeline warnings/errors unrelated to the send.

Pass `modeline = false` in the opts table, and assert the emitted opts carry it.

Change-Id: I2511d7d55332bb21611ae5ee42419b7edae48134
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ThomasK33 ThomasK33 merged commit 9b69b85 into main Jun 8, 2026
2 checks passed
@ThomasK33 ThomasK33 deleted the feat/228-send-complete-event branch June 8, 2026 12:55
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.

[BUG] focus_after_send has no effect with provider = "none"

1 participant