Why is this here?
Highlight a line. Get the real reason it exists — past formatting commits, renames, and file moves — then the pull request and ticket that asked for it.

Select code → trail from commit → PR → ticket → a short cited answer.
What you get
- Answer — 2–4 sentences with confidence and clickable citations. If history never recorded why, it says so instead of guessing.
- Trail — commit → pull request → Jira issue → epic, with authors and dates. Click any node to open the source.
- Evidence — commit message, PR discussion (comments on your lines first), and issue text.
Also: CodeLens (why is this here? on functions), hover provenance (no model), and Copy as markdown for Slack.
Quick start
- Install the extension in VS Code or Cursor.
- Open a git repo, select a line or block.
- Right-click → Why is this here? (or
Cmd+Alt+W / Ctrl+Alt+W).
- Sign in to GitHub when prompted (or continue with local git only).
- Optional: Connect Jira and Model Settings for tickets and the synthesized answer.
Local git archaeology always works. GitHub unlocks PRs and private repos. Jira unlocks tickets. A model turns evidence into the short answer — without inventing sources.
Connect (optional)
| Connect |
Why |
| GitHub |
Pull requests, review comments, private repos. VS Code/Cursor GitHub session on github.com; PAT for Enterprise. |
| Jira |
Sign in with Atlassian (Jira Cloud OAuth) or an API token (Server / Data Center). |
| Model |
Model Settings stores API keys for OpenAI, Anthropic, Gemini, local Ollama, or a custom endpoint. Synthesis tries the editor’s free built-in model first (VS Code + Copilot; Cursor has none), then each stored key in order until one answers. |
There is no Why-is-this-here backend. Keys and OAuth tokens stay in your editor’s Secret Storage (OS keychain). See PRIVACY.md.
Jira Cloud OAuth note
Sign-in opens your browser and finishes on a loopback URL (http://127.0.0.1:8787/...) on your machine. That is the same for Marketplace installs and sideloaded VSIX — Atlassian requires a fixed callback URL for the OAuth app. Nothing is sent to a Why-is-this-here server.
Commands
| Command |
What it does |
| Why is this here? |
Investigate the selection |
| Why Is This Here: Explain Range |
Same, for a range from another extension or keybinding |
| Why Is This Here: Copy Last Answer as Markdown |
Answer, trail, and citations to the clipboard |
| Why Is This Here: Sign in to GitHub / Sign out of GitHub |
GitHub session or PAT |
| Why Is This Here: Connect Jira |
Atlassian OAuth or API token |
| Why Is This Here: Set Jira API Token |
Token only, if site/email already set |
| Why Is This Here: Clear Jira API Token |
Clears OAuth session and API token |
| Why Is This Here: Test Jira Connection |
Live check of stored credentials |
| Why Is This Here: Model Settings |
Add/update API keys for the cascade; turn AI off |
| Why Is This Here: Set Model API Key / Clear Model API Key |
Quick key helpers |
| Why Is This Here: Show Model Status |
Which models are in the try-order |
| Why Is This Here: Show Cache Stats / Clear Cache |
Local disk cache |
| Why Is This Here: Run Synthesis Gate |
Maintainer QA (hidden from everyday use) |
Caching
Cached under the extension’s global storage on your machine:
| What |
Expires |
| Commit → PR |
never |
| PR body / comments |
24h |
| Issues |
24h |
| Synthesised answer |
never (keyed by evidence hash) |
| Not-found results |
6h |
Failed lookups are never cached. Clear anytime with Clear Cache.
Settings
All settings are prefixed whyIsThisHere.. Tokens are never stored in settings.
| Setting |
Default |
Purpose |
ui.useWebview |
true |
Panel, or markdown in the output channel |
codeLens.enabled |
true |
Lens above functions and classes |
codeLens.maxPerFile |
100 |
Cap in huge files |
hover.enabled |
true |
One-line provenance on hover |
hover.debounceMs |
300 |
Rest time before hover work |
hover.lookUpPullRequest |
true |
Resolve PR on hover; off = fully offline hovers |
llm.provider |
auto |
auto (cascade), off, or legacy vscode / http |
llm.models.openai |
gpt-4o-mini |
OpenAI model id when that key is stored |
llm.models.anthropic |
claude-sonnet-4-6 |
Anthropic model id when that key is stored |
llm.models.google |
gemini-2.5-flash |
Gemini model id when that key is stored |
llm.models.local |
llama3.1 |
Local model id when local is enabled |
llm.models.custom |
— |
Model id for the custom endpoint |
llm.local.enabled |
false |
Include local Ollama-style server in the cascade |
llm.custom.endpoint |
— |
Custom OpenAI-compatible base URL |
llm.endpoint |
— |
Legacy single endpoint (migrated into cascade) |
llm.model |
— |
Legacy single model id |
llm.vendor |
copilot |
Pin a vscode.lm vendor |
llm.family |
— |
Pin a vscode.lm family |
llm.maxEvidenceTokens |
8000 |
Evidence budget for the model |
jira.baseUrl |
— |
e.g. https://acme.atlassian.net |
jira.email |
— |
Account for API-token auth |
jira.epicLinkField |
— |
Epic link field on Jira Server |
jira.keyDenylist |
[] |
Patterns that look like keys but aren’t |
jira.maxLookups |
5 |
Candidate keys verified per run |
jira.maxIssues |
3 |
Issues kept after verification |
jira.maxLinkedFollows |
3 |
Linked issues, one level deep |
cache.enabled |
true |
Disk cache |
cache.networkTtlHours |
24 |
Freshness for PRs and issues |
cosmeticFileThreshold |
20 |
Wide whitespace-only commits count as cosmetic |
maxRecursionDepth |
10 |
Walk-back depth through cosmetic commits |
bulkImportFileThreshold |
500 |
Above this, prefer pickaxe |
Trust & privacy
- Every claim carries a commit SHA or URL.
- The model may only cite labels from the evidence bundle.
- Credentials: Secret Storage only. Privacy policy.
- Publisher: whyisthishere (Subhanshu Dwivedi) on the Visual Studio Marketplace.
License
Proprietary commercial software — see LICENSE. All rights reserved.