Skip to content

feat: write /rewrite and /refine results back into the source app#197

Merged
quiet-node merged 11 commits into
mainfrom
feat/cross-app-replace
Jun 7, 2026
Merged

feat: write /rewrite and /refine results back into the source app#197
quiet-node merged 11 commits into
mainfrom
feat/cross-app-replace

Conversation

@quiet-node
Copy link
Copy Markdown
Owner

Overview

Sends /rewrite and /refine results straight back into the app you were working in, replacing the text you had selected. After a rewrite finishes you can drop it into the source app with one click (or automatically), without copying and pasting by hand.

Highlights

  • Replace button on every /rewrite and /refine result. It pastes the rewrite into the source app while the Thuki overlay stays open, so you can replace repeatedly, and confirms with a brief checkmark.
  • Behavior settings tab with two independent toggles, both off by default:
    • Auto-replace writes the result back the moment the model finishes, no click needed.
    • Auto-close dismisses the overlay after a successful replace (manual or automatic).
  • Sticky Replace on follow-up turns: refining a result in the same chat ("make it longer") keeps the Replace button.
  • Section help tooltips: a ? next to a settings-section heading explains what the whole group does, distinct from the per-row helpers.

How it works

Backend (replace.rs). An NSWorkspace activation observer records the PID of the last non-Thuki app to activate; because Thuki's overlay is a non-activating panel, summoning it never overwrites that target. replace_selection saves the clipboard, writes the rewrite to it (tagged transient so clipboard-history managers skip it), activates the target app, posts a synthetic Cmd+V directly to the target process with CGEventPostToPid, then restores the clipboard. Posting to the process rather than the system key window is what lets the paste land in the source app while Thuki's panel stays key and visible. Paste is used over an Accessibility selected-text write because Cmd+V reliably replaces the selection where an AX write collapses to the caret once focus leaves.

Configuration. A new [behavior] section (auto_replace, auto_close) flows through defaultsschemaloader, is exposed via get_config, and is edited from the Behavior tab. write_field_to_disk now materializes an allowed-but-not-yet-persisted section before patching, so toggling a brand-new field on a config file seeded before the section existed works instead of failing with UnknownSection.

Frontend. The new commands go through the existing unified dispatch in App.tsx: the replaceable trigger is carried on the assistant message via useOllama, ChatBubble renders the Replace button for those results, and both the manual and automatic paths send the same rendered text (turn-boundary tokens stripped) back to the source app.

Security

The write path is gated three ways: it no-ops when Accessibility is not granted, when there is no observed target app, and when secure input is active (a focused password field or iTerm Secure Keyboard Entry), so a rewrite can never be pasted into a credential field. Section and field names are validated against the existing allowlist before any TOML is written, so the new on-disk-section creation can only ever materialize a real schema section.

Testing

  • bun run test:all:coverage — 1517 frontend tests and 896 backend tests pass; the 100% line-coverage gate holds on both sides.
  • bun run validate-build — ESLint, cargo clippy -D warnings, tsc, Prettier, and the full release build/bundle all pass with no warnings.

macOS-only feature; requires the Accessibility permission Thuki already uses for its hotkey.

quiet-node added 11 commits June 3, 2026 22:00
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
…nhance user feedback

Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
@quiet-node quiet-node merged commit 03a8fce into main Jun 7, 2026
3 checks passed
@quiet-node quiet-node deleted the feat/cross-app-replace branch June 7, 2026 00:28
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.

1 participant