PromptSight AIPrompt governance for VS Code — every token is checked before it is spent. PromptSight sits between you and the LLM. Before a prompt is sent it tries to avoid the call entirely (local prompt cache), reduce it (lossless compression, exact-repeat summaries, secret redaction), and govern it (token/cost thresholds, session budgets, team policy, personal-data masking) — then stops so you decide. Nothing is sent until you choose.
Features
Everything runs locally and in-process — no Python, no subprocesses, no network calls, and nothing leaves your machine without your explicit decision. Installation
From the Marketplace (recommended):
Or from the command line:
Building from source (contributors):
Then reload VS Code ( How to UseIn Copilot Chat —
|
| Button | What it does |
|---|---|
| 💾 Use cached solution | Reuses the best cached answer — 0 tokens spent |
| ✅ Allow — send original | Sends your prompt unchanged |
| ♻ Reframe | Sends the safely optimized, compact-encoded, secret-redacted version, or unchanged text if no safe edits exist; the send line shows the condensed input tokens next to the original count |
| ⇄ Switch model — send via suggested | Routes the request through the model PromptSight recommends (cheaper for simple tasks, stronger for complex ones) |
| ⇄♻ Reframe + Switch model | Sends the optimized prompt and routes it through the suggested model — stacks both savings |
| ▶ Continue | Appears when a reply stopped at the reply cap — sends your prompt and the partial reply back to the same model, which picks up where it stopped (both count as input again) |
| (ignore) | Nothing is sent |
Allow and Reframe remain available even when there are no automatic savings; Reframe keeps the send optimized label and shows token savings only when positive, sending unchanged text without claiming savings if the optimizer found nothing to change. Switch model and Reframe + Switch model always appear too — if the current model already fits the task, clicking either just replies that no switch is needed rather than opening a manual model picker. Use cached solution appears only when a confident cache match exists.
When you send, the first line splits the estimate into Input tokens and Output tokens; after Reframe the input shows the condensed count, for example:
PromptSight: ALLOW · Input tokens: ~160 (condensed from ~560) and Output tokens: ~480 (reply capped at 8,000) · saved ~600 tokens · sending optimized prompt…
The reply then ends with the actual usage, split the same way: estimated ~640 → actual 1,210 tokens (input 160 + output 1,050).
Slash command shortcuts:
| Command | What happens |
|---|---|
@promptsight <prompt> |
Pre-flight report only — you decide after |
@promptsight /send <prompt> |
Pre-flight, then sends original prompt |
@promptsight /optimize <prompt> |
Pre-flight, then sends optimized prompt |
@promptsight /switchmodel <prompt> |
Pre-flight, then sends via the suggested model (e.g. drops a premium model to gpt-4.1-mini for a simple task) |
@promptsight /optimizeswitch <prompt> |
Pre-flight, then sends the optimized prompt via the suggested model — combines Reframe and Switch model |
@promptsight /continue <prompt> |
Continues a reply that stopped at the reply cap (the ▶ Continue button does this for you) |
| Attach a file or selection (📎) to your message | PromptSight includes its content in the prompt and overall token estimate without a separate attachment table — no /readfile or copy/paste needed |
@promptsight /cached <prompt> |
Reuses the best cached solution — costs 0 tokens |
@promptsight /helpful <prompt> |
Rates the last cached answer 👍 — raises its confidence |
@promptsight /unhelpful <prompt> |
Rates the last cached answer 👎 — lowers its confidence |
@promptsight /feedback up\|down [feature:<name>] <comment> |
Records feedback about PromptSight itself (stored locally) |
@promptsight /feedback summary |
Shows collected feedback: satisfaction %, per-feature counts, recent comments |
@promptsight /dashboard [days] |
Shows token-savings, cache, and usage metrics for the last N days (default 30) |
@promptsight /clearcache |
Clears the local prompt cache, or /clearcache expired to prune only stale entries |
After /cached, 👍/👎 rating buttons appear automatically — the cache learns which answers are worth reusing.
Model switching in practice: if you ask a simple question while a premium model (e.g. Claude Opus) is selected, the pre-flight report says "You can likely downgrade to a small / fast model such as 'gpt-4.1-mini' to cut cost" and shows the ⇄ Switch model button. Clicking it sends this request through the suggested model. The suggested model must be enabled in the chat model picker ("Manage Models…") — if it isn't, PromptSight tells you and sends nothing.
In Agent Mode — #promptsight
- Switch Copilot Chat to Agent mode
- Add
#promptsightto your message:#promptsight Refactor all files in this repo to use async/await - A gate dialog appears with Allow, Reframe, and Deny options:
- Allow — agent proceeds with your original request
- Reframe — agent uses the optimized prompt instead
- Deny — agent stops; adjust your prompt and retry
The reply cap and the estimated-vs-actual usage apply to @promptsight only: in agent mode the agent's own replies don't pass through PromptSight, so they can't be capped or measured. Likewise the agent already has your message, so personal-data masking only protects the Reframe text PromptSight hands back to it.
After updating to VS Code 1.141
VS Code 1.141 can open new chats as Copilot (agent host) sessions, which run on models that only the agent host can use (ids such as agent-host-copilotcli:auto). Earlier releases quietly ran a @promptsight request in such a chat on the default Copilot model instead. Since 1.141 (microsoft/vscode#339307), VS Code rejects the request before it reaches PromptSight:
The selected model 'agent-host-copilotcli:auto' is not available. Select a different model and try again.
Picking another model in that chat doesn't help, and no extension can intercept this error. PromptSight therefore fixes it on its own, so nobody has to click anything:
- When VS Code starts, PromptSight turns off
chat.defaultToCopilotHarnessandchat.editor.preferCopilotHarnessin your user settings if either is on, and shows a short notice with an Undo button. New chats then open as regular Copilot chats, where you can type@promptsight. - This happens once per install, and only when VS Code's own default turned these settings on. If you turned either on yourself, chose Don't Show Again on the notification in version 1.1.4, turn one back on later, or click Undo, PromptSight leaves your choice alone.
- Chats that are already open keep their type, so use a new chat afterwards. The setting applies to every new chat, not only PromptSight's.
- To apply the fix again later, run PromptSight: Fix @promptsight for New Chats from the Command Palette. It also opens a new chat with
@promptsighttyped in.
#promptsight isn't affected: tools don't depend on the chat's model, so the Allow / Deny / Reframe gate keeps working in Copilot (agent host) chats.
Settings
Open VS Code Settings (Ctrl+,) and search for promptsight:
| Setting | Default | Description |
|---|---|---|
promptsight.defaultModel |
gpt-4.1-mini |
Rates used when the chat's model has no price (e.g. Copilot's Auto); the report says so. The agent-mode gate estimates with this model |
promptsight.warnThreshold |
8000 |
Token count that triggers a ⚠ WARN; when you set it, it overrides the policy file's warn_total_tokens |
promptsight.blockThreshold |
12000 |
Token count that triggers a 🔴 BLOCK; when you set it, it overrides the policy file's block_total_tokens |
promptsight.policyPath |
(bundled) | Path to a custom policy.json (a workspace .promptsight/policy.json is auto-detected) |
promptsight.pricingPath |
(bundled) | Path to a custom pricing.json |
promptsight.cacheEnabled |
true |
Stores prompt keywords and model replies in a plaintext local cache for 0-token reuse (personal data and secrets are masked first); disable if you work with sensitive content |
promptsight.maskPii |
true |
Masks personal data before every @promptsight send and puts the real values back in the reply you see |
promptsight.piiNames |
[] |
Extra names to always mask (customers, patients…) — for names the built-in rules can't recognise |
promptsight.cacheTtlDays |
30 |
Retention window (days) for cached prompt/solution pairs; older entries are treated as stale and pruned automatically (0 disables expiry) |
promptsight.maxOutputTokens |
8000 |
Reply cap: the most tokens one reply may use; a reply that reaches it stops and offers ▶ Continue (0 removes the cap). Doesn't apply to agent mode |
promptsight.sessionBudgetTokens |
150000 |
Session token budget, charged with the tokens each send actually used; a send that could go over it requires confirmation (0 disables) |
Team policy via git
Create .promptsight/policy.json in your repository root and commit it — every teammate with PromptSight gets the same governance rules automatically (a teammate who sets promptsight.warnThreshold or promptsight.blockThreshold themselves keeps that threshold):
{
"warn_total_tokens": 8000,
"block_total_tokens": 12000,
"hard_block": true,
"allowed_models": ["gpt-4.1", "gpt-4.1-mini", "gpt-4o-mini"],
"max_duplicate_ratio": 0.2
}
Troubleshooting
| Problem | Fix |
|---|---|
@promptsight does not appear in chat |
Reload window: Ctrl+Shift+P → Developer: Reload Window |
@promptsight fails with The selected model 'agent-host-copilotcli:…' is not available |
VS Code 1.141 blocks @promptsight in Copilot (agent host) chats. PromptSight fixes this once at startup; if it was undone or turned back on, run PromptSight: Fix @promptsight for New Chats, then use a new chat. See After updating to VS Code 1.141 |
| Extension not visible in Extensions panel | Reinstall from the Marketplace and reload |
code command not found |
Run Shell Command: Install 'code' command in PATH from Command Palette |
| Estimated cost says at … rates or n/a | The model picked in the chat has no price in pricing.json — typically Copilot's Auto, which only picks a model at send time. PromptSight then uses your promptsight.defaultModel rates and says so; it shows n/a only when that model has no price either. Pick a specific model, or add its rates via promptsight.pricingPath |
| A name wasn't masked | Add it to promptsight.piiNames — names in free text that match none of the built-in rules can slip through |
Uninstall
code --uninstall-extension HemantSagar-MS.promptsight-preflight
Then reload VS Code: Ctrl+Shift+P → Developer: Reload Window.
Running the Tests
npm test
The suite covers the analyzer units, personal-data masking, a 16-scenario validation corpus of technical and non-technical prompt types (code, logs, Terraform, SQL, JSON, transcripts, emails, marketing copy, PII/secrets…), model-selection impact (cost scaling, downgrade/upgrade routing), the feedback store, a mocked-vscode smoke test of the chat participant (switch-model routing, the reply cap, and ▶ Continue included), and the automatic fix for @promptsight in Copilot (agent host) chats.
Compare token/cost impact of different models across the whole corpus:
npm run eval:models # or: node scripts/model-impact.js
node scripts/model-impact.js --models gpt-4.1-mini,claude-opus-4
The report shows per-scenario cost by model and where routing advice recommends a cheaper (cost) or stronger (output quality) model.
Repository Layout
PromptSight_AI/
├── package.json Extension manifest (chat participant + agent tool)
├── extension.js Chat participant, agent gate, cache UX, session budget, model switch, feedback
├── lib/ VS Code-facing helpers used by extension.js
│ ├── config.js Settings and repo-committed policy lookup
│ ├── attachments.js Chat attachments (files, selections, inline text) → prompt text
│ ├── dashboard.js /dashboard, /clearcache, and the dashboard webview
│ ├── feedback.js /feedback ratings and summary
│ ├── format.js Shared text, Markdown, and HTML formatting
│ └── chatDefault.js One-time automatic fix for @promptsight in Copilot (agent host) chats
├── build-vsix.ps1 Packages the extension into a .vsix
├── scripts/
│ └── model-impact.js Model-selection impact report over the validation corpus
├── src/ In-process analyzer (one small bundled dependency, no network calls)
│ ├── analyzer.js Pre-flight orchestrator (tokens → cost → policy → optimization)
│ ├── tokenizer.js Token counting (real BPE for OpenAI models) + calibrated output estimation
│ ├── classifier.js Input type / complexity / duplication detection
│ ├── costEstimator.js Per-model pricing → cost
│ ├── policyValidator.js ALLOW / WARN / BLOCK decision
│ ├── optimizer.js Safe cleanup, model routing, secret detection/redaction
│ ├── piiMasker.js Personal-data detection and reversible masking
│ ├── promptCache.js Local JSON prompt-solution cache (0-token reuse, LRU-capped)
│ ├── feedbackStore.js Local feedback store (ratings + summary)
│ ├── metricsStore.js Local usage/telemetry store (savings, cache reuse, dashboard)
│ └── compactEncoder.js JSON → compact tabular lossless compression
├── analyzer/
│ └── config/
│ ├── policy.json Threshold and rule configuration
│ ├── pricing.json Per-model token pricing
│ ├── model_rules.json Model routing rules
│ └── tokenizer_encodings.json Model name → BPE encoding table
└── test/
├── analyzer.test.js Analyzer unit tests
├── validation.test.js Recommendation validation over the prompt corpus
├── modelImpact.test.js Model-selection impact on tokens/cost/routing
├── feedbackStore.test.js Feedback store tests
├── metricsStore.test.js Usage-metrics store tests
├── promptCache.test.js Prompt cache tests
├── piiMasker.test.js Personal-data detection and masking tests
├── tokenizer.test.js BPE/heuristic token counting + output calibration tests
├── extensionSmoke.test.js Chat participant smoke test (mocked vscode)
├── chatDefault.test.js Automatic chat fix tests
└── fixtures/
└── promptCorpus.js 16 technical + non-technical validation scenarios
Notes
- Token counts use real BPE tokenization (via the bundled
js-tiktoken) for OpenAI-family models — the exact count they're billed on. Every other vendor (Claude, Gemini, Grok, MAI) falls back to a heuristic estimate (≈¾ word per token). Very long unbroken runs of text (CJK paragraphs, separator lines, minified blobs) are counted from a sample. Output-token, cost, and CO₂e figures are estimates, blended with your own local usage history once enough samples accumulate, for pre-flight awareness only. Cost uses the rates of the model picked in the chat; when it has none (e.g. Copilot's Auto), thepromptsight.defaultModelrates are used and the report says so. - Input tokens are counted on exactly what
@promptsightsends — your prompt plus attachments, with personal data masked — using the tokenizer of the model that answers (for Copilot's Auto, the model PromptSight sends through). So the pre-flight prompt size, the send line, and the usage line after the reply show the same input count; only the output was estimated. The actual usage is PromptSight's count of the text sent and the reply received; a provider may add a few tokens of its own message framing. - The analyzer runs fully in-process — no Python, no subprocesses, no network calls at runtime. The one bundled dependency (
js-tiktoken, a pure-JS BPE tokenizer with pre-computed rank-table data files) never phones home; it only ever reads from localnode_modules. - The optimizer only performs deterministic, zero-token edits: exact-repeat summaries, lossless compact re-encoding of JSON, and secret masking. No LLM is used to optimize prompts.
- Repetition summaries are limited to exact adjacent entries in clearly recognized logs or timestamped transcripts, with repetition counts retained. Different values and connections are never treated as duplicates. Source code, SQL, Terraform, configuration, mixed or uncertain content, and repetitions in separate contexts are left unchanged by this step. Preserving meaning takes priority over token savings.
- Secret detection is best-effort; high-severity matches are masked in the optimized prompt and always redacted in the report.
- Personal-data detection is local and best-effort. Formats, checksums (Luhn for cards, Verhoeff for Aadhaar, mod-97 for IBAN) and labelled fields are reliable; a name that matches none of the rules and isn't in
promptsight.piiNamescan still get through. Private and reserved IP addresses and CIDR blocks identify no one, so they are left as they are. - The prompt cache is enabled by default and is a local JSON file (per-machine, under VS Code global storage, capped at 500 entries). It stores only the derived keyword list (not the raw prompt/file text), a content hash per attached file (used to stop cross-project matches on same-named files, never the file content itself), and the model's response with personal data masked and high-severity secrets redacted. Nothing is uploaded anywhere; disable
promptsight.cacheEnabledif you work with sensitive content. - Feedback (
/feedback) is also a local JSON file (capped at 1000 entries) — nothing is uploaded anywhere. - Model switching routes the request through the suggested model via the VS Code language-model API; the chat window's model picker UI itself cannot be changed by extensions and keeps showing your manual selection.
- GitHub Copilot Chat is required to use the
@promptsightparticipant and#promptsighttool.