The dim prompt suggestion that Tab accepts starts with a capital letter and ends with a full stop, unless it is a slash command or already ends a sentence

A Claude Code mod. After a turn, Claude Code proposes your next prompt as dim text in the empty prompt box, and Tab accepts it. The suggestion often comes in lowercase and without a full stop, so if you write your prompts as sentences, every accepted suggestion needs fixing before you send it. This mod rewrites the suggestion before it is shown: it starts with a capital letter and ends with a full stop.
| Suggested | Shown |
|---|---|
| run the tests | Run the tests. |
| why did it fail? | Why did it fail? |
| čekaj da završi | Čekaj da završi. |
` npm test again ` | ` npm test again. ` |
| /commit | /commit |
., ?, !, … or :.One prompt.suggest hook in plugin/hooks/register.ts rewrites the text and passes it on with next({ ...e, text }). It calls nothing on $: no files, processes, network or model calls.
It handles every suggestion, both Claude Code's own and any that another plugin proposes through $.prompt.suggest.
In the Code tab of Claude Desktop the suggestion shows unchanged: there the engine sends it to the host without raising prompt.suggest, so the mod never sees it. The mod starts working there by itself once the engine routes that suggestion through prompt.suggest. The versions measured, a minimal repro and the bug report (anthropics/claude-code#99876) are in docs/claude-desktop.md.
claude plugin marketplace add <path-to-this-repo>
claude plugin install cc-mod-suggestion-sentence-case@cc-mod-suggestion-sentence-case --scope user
On Claude Code builds before 2.1.287, function hooks of installed plugins may need "CLAUDE_CODE_ENABLE_FUNCTION_HOOKS": "1" in the env block of ~/.claude/settings.json.
Check and test: claude plugin validate ./plugin and claude plugin test ./plugin.
hooks/register.ts 23 lines1import type { Register } from 'claude-code'
2
3// The prompt suggestion (the dim text in an empty prompt box that Tab accepts) as a sentence:
4// a capital first letter and a full stop at the end.
5const ENDS_SENTENCE = /[.?!…:]$/
6
7const toSentence = (text: string): string => {
8 const trimmed = text.trim()
9 // A slash command stays as it is.
10 if (trimmed === '' || trimmed.startsWith('/')) return text
11 const first = trimmed[0]
12 // Only a letter is capitalized; code, a quote or a digit at the start stays as it is.
13 const isLetter = first.toLowerCase() !== first.toUpperCase()
14 const capped = isLetter ? first.toUpperCase() + trimmed.slice(1) : trimmed
15 return ENDS_SENTENCE.test(capped) ? capped : `${capped}.`
16}
17
18// Every suggestion, not only Claude's own (origin kind 'suggestion'): a suggestion another
19// plugin proposes should read the same way, and a test can only raise one without an origin.
20export const register: Register = on => {
21 on('prompt.suggest', ($, e, next) => next({ ...e, text: toSentence(e.text) }))
22}
23