Sharpie is a macOS menu-bar app that turns a rough intent into the prompt or task brief the user should have written. It is being reimagined as a fast AI rewrite layer for serious work: one keystroke captures the user's current thought, adds the smallest useful context pack, and produces a single sharp output through the user's own AI tools.
Read PRD.md before making product or architecture changes. That document is the product source of truth. This file is the build-agent source of truth.
Sharpie should feel like a reflex.
The user should be able to highlight bad text, press Command-/, and get the version of that thought that would have taken 15 minutes of careful thinking to write. The product is not a chat app, not a prompt library, and not a dashboard. It is a thin native layer above the user's existing AI tools.
- Primary interaction: selected text plus hotkey, with the window as fallback when selection capture is unavailable.
- Interface direction: Perplexity-like restraint, Spotlight-like speed, Raycast-like utility, and native macOS calm.
- Output: exactly one rewritten prompt or task brief per invocation.
- No clarifying questions. If context is missing, encode an investigation step or assumption into the output.
- Context Pack: attach only the small set of local facts that help the rewrite, such as frontmost app, selected text, clipboard text, current repo, git branch, changed files, and project rules.
- Almost-instant rewrite: speed comes from cached context, compact prompt assembly, backend readiness, fastest-healthy routing, streaming when possible, and optional BYOK Fast Lane.
- Privacy: by default, Sharpie itself makes no outbound network calls. Network activity happens inside the user's chosen CLI backend unless the user explicitly enables BYOK Fast Lane.
- Local-first: no accounts, no sync, no analytics, no update checker, no crash reporter.
- CLI-first AI: use the AI CLIs the user already has installed and authenticated by default; support optional BYOK Fast Lane only behind explicit settings.
- Do not add required direct API integrations for Anthropic, OpenAI, OpenRouter, Gemini, or other providers.
- Do not add first-run API-key flows or make API keys required.
- Do not store optional BYOK secrets outside macOS Keychain or explicit environment-variable configuration.
- Do not add telemetry, analytics, crash reporting, update checks, or phone-home behavior.
- Do not add chat, accounts, cloud sync, team collaboration, or a prompt marketplace.
- Do not add visible user-facing intent mode pickers unless the PRD is explicitly changed first.
- Do not ask clarifying questions in the product flow.
- Do not turn Sharpie into a project indexer. Context Packs must be small, explainable, and local.
- Do not block the hotkey path on backend startup, auth checks, git scans, or filesystem scans.
- Do not block the hotkey path on project indexing.
- Do not write generated indexes into
.sharpie/by default. - Do not add embeddings, vector search, whole-repo AI summaries, or whole-file context dumping in V1.
- Do not use deterministic local templates as the primary rewrite engine.
The strongest version of Sharpie has four layers:
- Command Bloom: a beautiful, compact native Mac surface that appears immediately.
- Fast AI Rewrite: selected text, clipboard text, or typed text is sent to the fastest healthy user-owned AI backend with a compact prompt.
- Context Pack: Sharpie adds a few cached local facts that make the prompt specific to the user's current work.
- Project Memory: each onboarded project can define lightweight human memory in
.sharpie/, while generated repo-map cache lives under Application Support.
Implement these in that order. The first useful version does not need the full Project Capsule system.
Sharpie should feel fast without pretending templates are the product.
Core decisions:
- Add a
PromptAssemblerfor Build, Debug, Review, Plan, and Pitch prompt contracts. - Add an
IntentRouterthat runs locally and cheaply for prompt shaping only. - Add a
BackendRouterthat chooses CLI, BYOK Fast Lane, or failover. - Add a
ContextSnapshotStorethat is refreshed in the background and read synchronously on invocation. - Add a
BackendReadinessCacheso CLI detection and basic health checks happen outside the hotkey path. - Add a
BackendLatencyStoreso Auto mode can prefer the fastest healthy backend. - Keep backend invocation bounded by a hard timeout. If it misses budget, fail over or show a useful error with the original input preserved.
- Add project indexing only as a background input to context quality. It must never become part of the invocation critical path.
Latency budgets:
- hotkey to visible UI: under 100ms
- selected text capture or fallback decision: under 250ms
- Context Pack build from cache: under 50ms
- prompt assembly and budgeting: under 80ms
- dispatch to selected backend: under 500ms
- CLI rewrite, p50: under 3s
- BYOK Fast Lane rewrite, p50: under 2s
- backend hard timeout: 8s
The user gets one final output. Internal candidates are fine; multiple visible rewrites are not.
- Stack: Swift 6.0+, SwiftUI, AppKit where needed, macOS 14+.
- Package manager: SwiftPM executable target. Do not introduce an Xcode project unless there is a strong reason.
- Hotkey: keep the Carbon
RegisterEventHotKeyapproach unless a concrete bug forces a change. - Backend shape: keep an
AIToolBackend-style protocol with subprocess conformers. - Subprocesses: use
Foundation.Process,Pipe, temp working directories, stderr capture, and timeouts. - Rewrite pipeline: route requests through
InvocationCoordinator,ContextPackBuilder,ContextCompiler,PromptAssembler,BackendRouter,RewriteRunner, andResultCommitter. - Context collection: isolate it behind services. The rewrite view model should not know how clipboard, git, accessibility, or project files are collected.
- Permission-sensitive features: degrade gracefully. If selected-text replacement or app inspection requires permissions the user has not granted, fall back to clipboard/window flow.
- Performance rule: anything that can be cached before hotkey press should be cached before hotkey press.
Project onboarding is optional. Sharpie must work immediately with no selected projects.
When the user onboards a project, Sharpie may create human-readable files:
project/
.sharpie/
context.md
preferences.md
recent-decisions.md
ignore
Rules:
.sharpie/is human-authored project memory..sharpie/files must be inspectable, editable, and safe to commit if the user chooses.context.mdstores stable project truth.preferences.mdstores output and workflow preferences.recent-decisions.mdstores decisions and tradeoffs not to reopen.ignorestores gitignore-style rules for Sharpie context and indexing.- Do not store generated indexes, databases, repo maps, AI summaries, or cache files in
.sharpie/by default.
Generated project cache belongs under:
~/Library/Application Support/Sharpie/Projects/<project-hash>/
Typical generated files, added progressively as needed:
manifest.jsonsymbols.dbfiles.dbgraph.jsonlast-indexed.json
Generated cache is rebuildable, local-only, and clearable. Treat it as sensitive because file paths, symbol names, and project structure can reveal private information.
Use project indexing to improve context quality, not to create a heavy knowledge-base product.
Implementation direction:
ProjectRegistrytracks user-selected projects.ProjectCapsuleManagerreads and writes.sharpie/files.ProjectIndexStoreowns Application Support cache.FileChangeMonitoruses macOS FSEvents for onboarded projects.- File changes are marked dirty and debounced by roughly 2 to 5 seconds.
SymbolIndexerincrementally reparses changed files only.RepoMapBuildercreates deterministic, compressed repo maps.ContextCompilerselects only relevant snippets for the current invocation.ContextBudgeterenforces hard context budgets.
Code intelligence direction:
- Use an aider-style repo map as the main inspiration.
- Prefer concise maps of important files, classes, functions, signatures, imports, and dependencies.
- Consider Tree-sitter for fast local multi-language parsing and incremental symbol extraction.
- Consider SourceKit or IndexStoreDB later for deeper Swift-specific intelligence.
- Consider SCIP later as a language-agnostic interchange format.
- Avoid embeddings, full semantic search, and whole-repo AI summaries in V1.
Context budgets:
- V1 target: 500 to 1,200 tokens.
- V2 max: 2,000 tokens.
- Never dump whole files by default.
Hot path rule: use the latest cached index even if stale. If stale, continue and include changed-file hints internally. Background indexing must never block UI, prompt assembly, or backend invocation.
Detect installed CLIs on $PATH and prefer them in this order unless user settings say otherwise:
- Claude Code:
claude - Codex CLI:
codex - Gemini CLI:
gemini
Backends are the rewrite engine. Local code may shape the request, but it must not generate the final answer with canned templates.
Backends should run from a fresh temporary directory unless a feature intentionally needs project context. When project context is needed, pass it explicitly as text. Do not let the backend silently discover unrelated local agent files.
Do not run which, version probes, auth checks, or backend detection on the hotkey path. Use cached backend state and refresh it in the background or when settings opens.
Optional BYOK Fast Lane:
- May be added as an advanced opt-in path.
- Must never be required at first run.
- May make direct provider API calls only for the provider the user explicitly configured.
- Secrets must be stored only with explicit consent, preferably in macOS Keychain, with an environment-variable option for users who do not want stored keys.
The system prompt, prompt assembly, and context selection logic are product code.
- Canonical prompt file:
Sources/Sharpie/Resources/sharpen.md. - Repo-visible prompt path:
prompts/sharpen.md, if present, should point to or mirror the canonical file. - The bundled resource must be a real file. SwiftPM resource symlinks have caused regressions.
SystemPromptLoader.builtinFallbackmust mirror the canonical behavior.- Prompts must lead with role and output contract.
- Rewrite-only is mandatory. Never restore a clarification path.
- Local prompt contracts must prepare the AI backend to produce serious task briefs, not generic paraphrases.
- Do not generate final rewritten prompts from deterministic templates as the primary path.
- Prompt assembly changes need eval examples just like system prompt changes.
Context is useful only when it is small enough to trust.
Allowed context candidates:
- selected text
- clipboard text
- frontmost app name
- active file or window title, when safely available
- current repo path, when safely detectable
- git branch and changed-file names
- nearby project instruction files such as
AGENTS.md,CLAUDE.md,README.md - optional
.sharpie/context.md,.sharpie/preferences.md,.sharpie/recent-decisions.md - optional
.sharpie/ignore - budgeted repo-map excerpts from onboarded projects
Do not collect:
- whole-repo indexes
- hidden secrets
- browser cookies
- unrelated filesystem contents
- background screenshots
- telemetry or usage analytics
- generated indexes directly in prompts
- whole files by default
Hot path rule: build Context Packs from cached snapshots only. If a context source is stale or unavailable, omit it rather than blocking.
Prefer summarizing context into a short, visible Context Receipt that the user can inspect. Hidden context should be minimized and always budgeted.
- The fastest path wins.
- The menu-bar window is a fallback and editing surface, not the whole product.
- The primary surface is Command Bloom: a compact, beautiful floating panel.
- Always show a Context Receipt when context affects the result.
- Output should look like a task brief, not a chat bubble.
- Default hotkey:
Command-/. Escdismisses.Command-Zrestores original input after a rewrite.Returnsubmits, then dismisses after completion.Shift-Returninserts a newline.- Auto-copy successful output.
- If replacement into the frontmost app is unsafe or unavailable, copy to clipboard and show a clear status.
- Errors should preserve the user's original input.
- Motion should be fast and subtle. No bounce, no dramatic reveal, no decorative AI effects.
Scale tests to risk.
- Prompt changes need eval cases for lazy developer inputs, ambiguous inputs, product ideation, debugging, review, and handoff prompts.
- Prompt assembly changes need eval cases for every routed intent family.
- Backend changes need subprocess success, timeout, stderr, empty stdout, and missing CLI coverage.
- BYOK changes need secret-storage, env-var, provider-error, timeout, and no-key-first-run coverage.
- Context Pack changes need tests that prove sensitive or unrelated content is not included.
- Project memory changes need tests that
.sharpie/stays human-readable and generated cache stays in Application Support. - Indexing changes need tests for ignore rules, dirty-file updates, stale-cache fallback, and clear-cache behavior.
- Performance-sensitive changes need tests or instrumentation showing the hotkey path does not perform slow discovery.
- UI changes should be manually verified on macOS with hotkey, focus, copy, dismiss, selected-text replacement, reduced motion, and failure paths.
Run the relevant SwiftPM tests before handing work back when feasible:
swift testIf a full build is relevant:
make appDecide on your own:
- implementation details
- file and type names
- UI copy
- error wording
- test structure
- visual spacing and typography
- branch names and commit messages
- cache TTLs that satisfy the latency budget without collecting extra data
- repo-map ranking heuristics that are deterministic and explainable
- prompt contracts for obvious intent families
Decide and document:
- tradeoffs between CLI routing, BYOK routing, failover, and timeout behavior
- permission fallback behavior
- which context sources ship in a milestone
- why a feature belongs in or out of the Context Pack
- any change that makes the hotkey path slower in exchange for quality
- any new generated cache format or schema migration
Stop and ask Vikky only when:
- the change contradicts the PRD
- the change costs money
- the change publishes or pushes something external before v1.0
- the change requires adding telemetry, required direct API integrations, required API keys, accounts, sync, hidden indexing, embeddings/vector search, whole-repo AI summaries, deterministic local templates as the primary rewrite engine, or a visible intent mode system
The principle: build the reimagined Sharpie with taste and restraint. Make it powerful by making the user's next action obvious, and make it feel instant by keeping the hotkey path brutally small.