This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Xcho is a Chrome extension that generates AI-powered reply suggestions for X (Twitter). It uses Google Gemini API to create personalized, authentic-sounding comments based on selected tweets.
npm install # Install dependencies
npm run dev # Development mode with hot reload
npm run build # Production build (outputs to dist/)After building, load the extension in Chrome:
- Navigate to
chrome://extensions/ - Enable "Developer mode"
- Click "Load unpacked" and select the
distfolder
npm test # Run all tests once
npm run test:watch # Watch mode during development- Framework: Vitest with jsdom environment
- Setup:
tests/setup.tsprovides global Chrome API mocks - Mocks:
tests/mocks/chrome.ts(storage mock factory),tests/mocks/gemini.ts(Gemini SDK mock) - Tests:
tests/utils/contains tests for gemini.ts, storage.ts, persona.ts
- docs/architecture.md: Message flow, state management, caching strategy
- docs/prompt-engineering.md: Prompt structure and design decisions
- docs/development.md: Development workflow, testing, debugging
The extension uses three interconnected components that communicate via Chrome's messaging API:
-
Content Script (src/content/index.ts)
- Injected into x.com/twitter.com pages
- Detects tweet clicks and extracts tweet data using DOM selectors (
[data-testid="tweetText"],[data-testid="User-Name"]) - Handles both timeline view (article elements) and detail page (direct extraction)
- Uses MutationObserver to detect SPA navigation (URL changes)
-
Background Service Worker (src/background/index.ts)
- Manages side panel lifecycle
- Caches tweet data per tab (Map<tabId, TweetData>) to handle timing issues between content script and side panel
- Cleans up cache when tabs close
-
Side Panel UI (src/sidepanel/App.tsx)
- React-based UI for comment generation
- Requests cached tweet data from background on mount (handles race conditions)
- Settings modal for API key and persona configuration
User clicks tweet → Content Script extracts data → sends TWEET_CLICKED message
→ Background caches data + opens side panel → Side panel requests GET_CURRENT_TWEET
→ Background returns cached data → UI displays tweet + generation options
- Per-tab tweet cache: Background stores latest tweet per tab in
chrome.storage.session(keyed by tabId, cleaned on tab close) - Per-tweet results cache: Side panel caches generated comments per tweet in
chrome.storage.session(LRU eviction at 10 entries, keyed by first 200 chars of tweet text) - Translation cache: In-memory Map via React
useRef(keyed by first 100 chars of tweet text, lives for session duration) - Session state: Side panel state persisted to
chrome.storage.sessionfor survival across panel close/reopen
- src/utils/gemini.ts: LLM integration with structured prompting (role/goal/context/constraints pattern), token tracking, and cost calculation
- src/utils/persona.ts: Writing style analysis from uploaded documents, extracts formality/directness/humor traits
- src/utils/storage.ts: Typed wrapper around chrome.storage.local
All shared types are in src/types/index.ts including TweetData, PersonaData, MessagePayload, and token/cost tracking interfaces.
See DEBUGGING.md for step-by-step debugging guide. Key debugging points:
- Content script: Check X.com page console for emoji-prefixed logs
- Background worker: Click "service worker" link in chrome://extensions/
- Side panel: Right-click inside panel → Inspect
- Gemini API key stored in chrome.storage.local
- Default model:
gemini-3-flash-preview(configurable via UI, defined in gemini.ts) - Model pricing defined in MODEL_PRICING constant for cost tracking