Skip to content

Add post-flush command hook - #277

Merged
umputun merged 5 commits into
umputun:masterfrom
mishamsk:feat/post-flush-hook
Jul 20, 2026
Merged

Add post-flush command hook#277
umputun merged 5 commits into
umputun:masterfrom
mishamsk:feat/post-flush-hook

Conversation

@mishamsk

Copy link
Copy Markdown
Contributor

Source: #113 (reply in thread)

Summary

  • add an optional post-flush shell command configured by CLI, environment, or config file
  • pass the exact annotation snapshot to the command on stdin after a successful atomic O flush
  • run through Bubble Tea terminal handoff so OSC 52 helpers can write to /dev/tty, then restore mouse tracking
  • preserve the flushed output file and report status when the command fails
  • document an example user-created OSC 52 clipboard helper

Verification

  • make test
  • make lint
  • make build
  • reviewer subagent: no remaining actionable findings
@mishamsk
mishamsk requested a review from umputun as a code owner July 18, 2026 21:38
Copilot AI review requested due to automatic review settings July 18, 2026 21:38

Copilot AI 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.

Pull request overview

Adds an optional “post-flush” hook that runs a user-configured shell command after an in-session annotation flush (O), piping the exact annotation snapshot on stdin and executing via Bubble Tea’s terminal handoff so helpers can write to /dev/tty (e.g., OSC 52), then restoring mouse tracking.

Changes:

  • Introduces --post-flush-command (CLI/env/config) and wires it at the composition root into the UI via a consumer-side PostFlushHook interface.
  • Adds app/handoff to construct an exec.Cmd that reads the flush snapshot from stdin while discarding stdout.
  • Extends the UI flush path (app/ui/output.go) to run the optional hook via tea.ExecProcess, with tests and documentation updates.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
site/docs.html Documents --post-flush-command and provides an OSC 52 example helper script.
README.md Adds the new flag to the options table and documents the OSC 52 post-flush workflow.
docs/ARCHITECTURE.md Updates architecture map/data flow and documents the new app/handoff subsystem and UI interface.
CLAUDE.md Updates repo structure overview with the new app/handoff package.
app/ui/output.go Runs optional post-flush hook after a successful atomic O flush via tea.ExecProcess and restores mouse tracking.
app/ui/output_test.go Adds unit tests for hook invocation and completion handling.
app/ui/model.go Adds PostFlushHook interface, injects it via ModelConfig, and handles the completion message in Update.
app/main.go Wires handoff.New(opts.PostFlushCommand) into ui.ModelConfig.PostFlushHook.
app/handoff/handoff.go Implements the hook runner producing sh -c <command> with snapshot on stdin and stdout discarded.
app/handoff/handoff_test.go Tests that stdin snapshot is delivered to the command as expected and validates empty-command behavior.
app/config.go Adds --post-flush-command option with env/config support and trims whitespace.
app/config_test.go Tests flag/env/config precedence and ensures dump-config includes the new key.
.claude/rules/gotchas.md Updates internal documentation for the output flush path to include the optional post-flush hook behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/ui/output.go Outdated

@umputun umputun left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

lgtm, happy to merge. Build/test/lint/race green, exec surface is clean (snapshot is stdin-only, command is user-config, no injection), mouse-restore matches the editor path, and the typed-nil PostFlushHook is handled.

a few nice-to-fix items, none blocking:

  • handleFlushOutput formats the snapshot twice on the hook path: store.WriteFile formats internally, then store.FormatOutput() runs again for the hook stdin (app/ui/output.go:387). Same goroutine and the store isn't mutated between them, so it's correct, just redundant. Could format once and hand the same string to both the write and the hook.
  • the flag description "run command after flushing annotations" doesn't say it fires on the O flush and so needs -o. Worth a word, otherwise someone sets --post-flush-command=pbcopy on its own and wonders why O does nothing.
  • the hook runs synchronously through tea.ExecProcess, so a hung command blocks the TUI until it returns (and SIGTERM can't quit meanwhile). Same as the $EDITOR path, so nothing new, but since this one fires automatically on every O a one-line doc note that it should be a fast, non-interactive command wouldn't hurt.

on whether it should need -o at all: your r-branch flow already writes --output then pipes through osc-copy, so the coupling matches how you use it. Fine as is.

@mishamsk

Copy link
Copy Markdown
Contributor Author

Thanks — all three nits were applied in 5981dbe:

  • the annotation snapshot is formatted once, atomically written, and that exact snapshot is passed to the hook
  • the flag/help text now says the hook runs after a successful O flush and requires -o/--output
  • the docs now note that the hook runs synchronously and should be fast and non-interactive

I also considered allowing the post-flush hook to run standalone without an output file. That does make sense as a follow-up, but I kept the existing coupling here to avoid expanding the scope and blowing up this diff.

@umputun

umputun commented Jul 20, 2026

Copy link
Copy Markdown
Owner

all three look good. Returning the snapshot from WriteFile is a cleaner fix than what I suggested, the store now owns the written bytes end to end and the hook can't drift from the file. Merging (squash).

@umputun
umputun merged commit 1b563f8 into umputun:master Jul 20, 2026
2 checks passed
@mishamsk
mishamsk deleted the feat/post-flush-hook branch July 20, 2026 02:06
umputun added a commit that referenced this pull request Aug 28, 2026
decouple the configured hook from file output so O can send the full
snapshot directly to a command. File-backed flush behavior and hints
stay unchanged.

Related to #336

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

Labels

None yet

3 participants