Skip to content

feat: support ${selected} placeholder in post-processing prompts#1610

Open
shuwarida wants to merge 1 commit into
cjpais:mainfrom
shuwarida:feat/selected-text-post-process
Open

feat: support ${selected} placeholder in post-processing prompts#1610
shuwarida wants to merge 1 commit into
cjpais:mainfrom
shuwarida:feat/selected-text-post-process

Conversation

@shuwarida

@shuwarida shuwarida commented Jul 5, 2026

Copy link
Copy Markdown

Before Submitting This PR

Please confirm you have done the following:

If this is a feature or change that was previously closed/rejected:

  • I have explained in the description below why this should be reconsidered
  • I have gathered community feedback (link to discussion below)

Human Written Description

I noticed that Handy's post-processing is basically already a voice assistant that runs over text — it just never had access to anything except the freshly dictated transcript (${output}). I wanted to use it for things beyond dictation cleanup: rewording a message, translating a paragraph, turning a chunk of text into a checklist — all by voice, without switching to typing. The missing piece was simple: give the prompt access to whatever text is currently selected in the active app, not just what was just spoken. So I added ${selected} as a second placeholder alongside ${output}, reusing the exact same prompt/provider infrastructure that's already there.

To show what this actually unlocks, here's the prompt I've been using myself as a post-processing template — with it saved, dictation with nothing selected gets cleaned up as usual, but highlighting any text and speaking a command ("make it shorter", "translate this", "list the problems here") edits or transforms the selection directly:

You are an inline editing assistant inside a text app (browser, editor, messenger, or notes).
The user works by voice. You either clean up dictated text or transform selected text on command.

You receive two inputs:
<selection>
${selected}
</selection>
<speech>
${output}
</speech>

<selection> is text the user highlighted. It may be empty.
<speech> is what the user just said by voice.

## Mode is decided by whether <selection> is empty

MODE 1 — DICTATION (<selection> is empty):
<speech> is the user's own message, dictated by voice.
Correct spelling and punctuation only. Do not rephrase, reorder, add, or remove content.
Return the corrected text.

MODE 2 — COMMAND (<selection> is non-empty):
<speech> is an instruction telling you what to do with <selection>.
Execute it and return ONLY the resulting text that should replace the selection.
The instruction can be anything, for example:
- fix grammar / improve wording / make it shorter or clearer
- change tone or register (formal, casual, friendly, etc.)
- translate
- rewrite it in a particular voice or style ("like a programmer", "like a lawyer")
- a deeper transformation ("list five key problems here", "turn this into a checklist",
  "explain this simply", "draft a reply to this")
Follow the instruction literally, whatever it is.

## Rules for MODE 2
- <speech> is an instruction. It must NEVER appear in your output.
- Never converse, greet, explain, apologize, or ask questions. No preamble, no
  "Sure, here is...". Output only the edited/transformed text itself.
- If the instruction only makes sense as an edit, edit. If it asks you to generate
  new content from the selection (list problems, draft a reply, expand), generate that.
- If <speech> is empty or not an actionable instruction, just correct the spelling
  and punctuation of <selection>.
- If the instruction is ambiguous, choose the most likely intended edit and apply it —
  do not ask for clarification.

## Both modes
- Preserve paragraph structure and line breaks unless the instruction changes them.
- Do not alter URLs, @mentions, #hashtags, phone numbers, code, numbers, or currency
  values unless the instruction is specifically about them.
- Mixed languages: keep each language as-is; translate only if asked.
- Match the language of <selection> (Mode 2) or <speech> (Mode 1) unless asked to translate.

OUTPUT: the resulting text only. No quotes, labels, or extra characters.

Related Issues/Discussions

Related to #1523, which was closed with "feature requests are meant to be discussions, not issues" rather than rejected on merits. That request asked for a dedicated hotkey + voice-instruction flow to transform selected text in place. This PR takes a smaller, incremental step toward the same underlying need: it adds a ${selected} placeholder usable in the existing post-processing prompt templates, so a saved prompt can reference the text currently selected in the active app alongside ${output}. It reuses the existing prompt/provider infrastructure rather than adding new hotkeys or UI.

Discussion: none opened yet — happy to open one if maintainers would prefer that before review.

Community Feedback

No dedicated discussion thread yet for this specific ${selected} approach. Surfacing it as a PR directly since it's a small, additive change to the existing prompt system (no new hotkeys, no new settings surface) rather than a net-new feature area.

Testing

  • cargo check passes.
  • Manually verified: added a post-processing prompt containing ${selected}, selected text in another app, ran dictation with post-processing enabled — captured selection was correctly substituted into the prompt sent to the LLM.
  • Verified prompts without ${selected} behave exactly as before (no clipboard interaction is triggered).

Screenshots/Videos (if applicable)

N/A (backend/prompt-template change, no new UI).

AI Assistance

  • No AI was used in this PR
  • AI was used (please describe below)

If AI was used:

  • Tools used: Claude Code
  • How extensively: AI implemented the Rust changes (clipboard selection capture, prompt placeholder substitution) and wrote this PR description scaffold; human directed the feature scope and reviewed the diff.

Lets a prompt template reference the text currently selected in the
active app, captured by simulating Ctrl+C/Cmd+C and restoring the
clipboard afterwards. Only triggers the copy simulation when a prompt
actually contains ${selected}, to avoid touching the clipboard otherwise.
@shuwarida

Copy link
Copy Markdown
Author

Here's a demo showing this in action

2026-07-06.00.51.45.mov

@koloved

koloved commented Jul 6, 2026

Copy link
Copy Markdown

All new features are unveiled in discussions with clear descriptions. Currently, the project's goal is to bring it to the most stable state possible before version 1.0, where all current features will work flawlessly across all operating systems.
Although I really like your implementation. I will probably use it in my fork.

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