# Architecture

> The current system and its important boundaries. Describe what *is*, not aspirations.

## System at a glance

- **Shape:** dual client surfaces (Chrome MV3 extension + VS Code extension) sharing portable LLM core; no LexAI backend
- **Stack:** TypeScript; Chrome via WXT ^0.20 + React 18; VS Code via `packages/vscode` (esbuild bundle); Node 22
- **Data stores:** Chrome `chrome.storage.local` (encrypted key + prefs); VS Code Secret Storage (API key) + `lexai.*` settings
- **Hosting / deploy target:** Chrome Web Store (Gitea CI); VS Code Marketplace not wired yet (local VSIX / extension host)
- **Build / release:** Chrome `npm run build` → `.output/chrome-mv3/`; VS Code `npm run vscode:build` → `packages/vscode/out/extension.js`

## Component map

```text
shared: src/lib/{providers,actions,types}  (+ crypto/messaging Chrome-only)

Chrome:
  content.ts ──ANALYZE_TEXT──> background.ts ──fetch──> provider API
  options/popup (React) ──storage──> chrome.storage.local

VS Code:
  extension.ts (commands/menus) ──callProvider──> provider API
       │                              ▲
       └── secrets / settings ────────┘
```

| Component | Responsibility | Owns (paths) | Talks to | Notes |
| --- | --- | --- | --- | --- |
| Shared core | Actions, prompts, provider adapters | `src/lib/providers.ts`, `actions.ts`, `types.ts` | Provider HTTPS APIs | No Chrome/VS Code imports |
| Chrome content | Selection, toolbar/modal, replace | `entrypoints/content.ts` | Background via messaging | DOM timing; `data-lexai` |
| Chrome background | Decrypt key, call providers, menus | `entrypoints/background.ts` | `chrome.storage`, providers | CORS + key isolation |
| Chrome Options/Popup | Settings + standalone analyze | `entrypoints/options`, `popup` | Storage + background | React; inline styles |
| VS Code extension | Commands, context menu, replace | `packages/vscode/src/**` | SecretStorage, settings, providers | Bundles `@lib` via esbuild |
| Chrome crypto/messaging | tweetnacl key path; safe chrome wrappers | `src/lib/crypto.ts`, `messaging.ts` | `chrome.*` | Not used by VS Code |

## Boundaries and contracts

- **Trust boundaries:** page DOM (Chrome) and editor buffer (VS Code) are untrusted text; API key never logged; only user’s chosen provider receives text/key
- **Message contract (Chrome):** `ANALYZE_TEXT` (payload + flat), `COPY_AS`, `LIST_MODELS` — see `src/lib/types.ts`
- **VS Code commands:** `lexai.{fix,rephrase,shorten,expand,explain,prompt,setApiKey,clearApiKey,showStatus}`
- **Internal imports:** VS Code may import `@lib/providers|actions|types` only — not `crypto` / `messaging`
- **External dependencies:** OpenAI, Anthropic, Groq, OpenRouter chat + models endpoints

## Data model (essentials)

- **Config:** provider, model, writing style, keyProvider
- **Sensitive:** API key — Chrome encrypted blob + encKey; VS Code Secret Storage
- **Legacy:** Chrome plaintext `apiKey` fallback until migrated

## Cross-cutting concerns

- **Authn/z:** none (BYO key)
- **Observability:** console debug in Chrome replace path (pre-release); VS Code notifications
- **Feature flags:** none
- **Config:** Chrome storage schema; VS Code `contributes.configuration` `lexai.*`

## Open architectural risks

- Chrome and VS Code settings are not synced
- VS Code v1 has no Prompt Builder / Copy As / floating toolbar
- Relocating Chrome into `packages/chrome` deferred — root remains the WXT app
