diff --git a/.claude/skills/add-content-type/SKILL.md b/.claude/skills/add-content-type/SKILL.md
new file mode 100644
index 00000000..4963e586
--- /dev/null
+++ b/.claude/skills/add-content-type/SKILL.md
@@ -0,0 +1,43 @@
+---
+name: add-content-type
+description: Scaffold a complete new content type (tag, extraction, grid, detail, prompt)
+allowed-tools: Bash(*), Read, Edit, Write, Glob, Grep, Agent
+---
+
+Add a complete new content type to AIUI. The user will provide the content type name (e.g., "event", "product", "video").
+
+Follow ALL steps — this is the full pipeline for a content type:
+
+1. **Tag format**: Add a new `[[{type}_ext:Field1|Field2|...]]` regex to `packages/app/src/composables/contentExtraction.ts` alongside the existing ones (FILM_EXT_RE, SONG_EXT_RE, etc.)
+
+2. **Type definition**: Add the TypeScript interface to `packages/core/src/types/content.ts` if it doesn't exist
+
+3. **Extraction function**: Add `extractAll{Type}s(text, userQuery)` to `contentExtraction.ts` following the pattern of `extractAllFilms` or `extractAllBooks`
+
+4. **Strip tags function**: Add `strip{Type}Tags()` and include it in `stripContentTags()`
+
+5. **Query classifier**: Add `is{Type}Query()` and optionally `is{Type}LikeResponse()` to `contentFiltering.ts`
+
+6. **ContentTab type**: Add the new tab name to the `ContentTab` union in `contentFiltering.ts`
+
+7. **Tab filtering**: Update `filterTabsByContext()` and `preferredFirstTab()` in `contentFiltering.ts`
+
+8. **Grid component**: Create `packages/app/src/components/content/{Type}Grid.vue` following the glass-morphism pattern of existing grids (BookGrid.vue is a good template)
+
+9. **Detail component**: Create `packages/app/src/components/content/{Type}Detail.vue` following the pattern of BookDetail.vue
+
+10. **Wire into ContentPanel.vue**: Add import, grid render block, detail render block, and panel state refs
+
+11. **Wire into ContentGridView.vue**: Add import, props, and grid render block
+
+12. **Wire into ChatPage.vue**: Pass the new panel data as props to ContentGridView
+
+13. **Wire into useContentPanel.ts**: Add panel ref, selected ref, open/close functions, extraction call in `updatePanelFromText()`
+
+14. **System prompt**: Add tag format instructions to the `SYSTEM_PROMPT` in `useAI.ts`
+
+15. **Tab label**: Add to `TAB_LABELS` in `ContentPanel.vue`
+
+16. **Verify**: Run `pnpm typecheck` and fix any errors
+
+Report what was created and the tag format to use.
diff --git a/.claude/skills/add-tool/SKILL.md b/.claude/skills/add-tool/SKILL.md
new file mode 100644
index 00000000..7e97db99
--- /dev/null
+++ b/.claude/skills/add-tool/SKILL.md
@@ -0,0 +1,32 @@
+---
+name: add-tool
+description: Add a new AI tool (function call) to the Claude proxy for the AI to use
+allowed-tools: Bash(*), Read, Edit, Write, Glob, Grep
+---
+
+Add a new tool that the AI model can call via Claude's tool_use API. The user will describe what the tool should do (e.g., "search local files", "get app status", "browse media").
+
+## Steps
+
+1. **Read the proxy**: Read `packages/app/server/claude-proxy.ts` to understand the existing tool_use loop and `SEARCH_WEB_TOOL` definition.
+
+2. **Define the tool**: Add a new tool definition following the Claude tool_use format:
+ ```ts
+ const NEW_TOOL = {
+ name: 'tool_name',
+ description: 'What this tool does...',
+ input_schema: {
+ type: 'object',
+ properties: { ... },
+ required: [...]
+ }
+ }
+ ```
+
+3. **Add handler**: In the tool_use loop (where `search_web` calls are handled), add a handler for the new tool name.
+
+4. **Implement backend**: If the tool needs a new API endpoint (e.g., `/api/media/scan`), create a Vite plugin or add a route to the proxy.
+
+5. **Update system prompt**: Add instructions in `useAI.ts` SYSTEM_PROMPT telling the AI when and how to use the new tool.
+
+6. **Verify**: Run `pnpm typecheck` and test the proxy starts without errors.
diff --git a/.claude/skills/audit-prompts/SKILL.md b/.claude/skills/audit-prompts/SKILL.md
new file mode 100644
index 00000000..d33b93b8
--- /dev/null
+++ b/.claude/skills/audit-prompts/SKILL.md
@@ -0,0 +1,37 @@
+---
+name: audit-prompts
+description: Deep audit of AI system prompts — find gaps, test extraction coverage, verify tag formats
+allowed-tools: Bash(*), Read, Glob, Grep, Agent
+---
+
+Perform a comprehensive audit of AIUI's AI prompt system. Do NOT make changes — report findings only.
+
+## Steps
+
+1. **Read the full system prompt**: Read `packages/app/src/composables/useAI.ts` and reconstruct the complete system prompt including all dynamic sections (persona, Wavlake, memory, web search, Archy context, code context).
+
+2. **Catalog all tag formats**: List every `[[type:...]]` and `[[type_ext:...]]` format defined in the prompt. Cross-reference with regexes in `contentExtraction.ts`.
+
+3. **Check for gaps**: For each content type in `ContentTab` (contentFiltering.ts), verify:
+ - Is there a tag format in the system prompt?
+ - Is there a matching extraction regex?
+ - Is there a query classifier?
+ - Is there a grid + detail component?
+ - Is the tab wired in ContentPanel.vue and ContentGridView.vue?
+
+4. **Test extraction coverage**: Read the seed prompts in `src/__tests__/fixtures/seedPrompts.ts`. For each seed, verify:
+ - Does the extraction function find the expected number of items?
+ - Are there edge cases that would break extraction?
+
+5. **Analyze prompt quality**: Check for:
+ - Conflicting instructions
+ - Missing edge case handling (e.g., "what if the AI can't find a match?")
+ - Overly vague instructions
+ - Missing content types that should have tag formats
+
+6. **Check proxy tools**: Read `server/claude-proxy.ts` and verify tool definitions match what the prompt claims.
+
+7. **Report**: Create a structured summary with:
+ - Content type coverage matrix (tag/extraction/grid/detail/prompt)
+ - Identified gaps and inconsistencies
+ - Priority recommendations
diff --git a/.claude/skills/check/SKILL.md b/.claude/skills/check/SKILL.md
new file mode 100644
index 00000000..2df6a024
--- /dev/null
+++ b/.claude/skills/check/SKILL.md
@@ -0,0 +1,17 @@
+---
+name: check
+description: Run all quality checks (typecheck, lint, test) and auto-fix errors
+allowed-tools: Bash(*), Read, Edit, Glob, Grep, Agent
+---
+
+Run all quality checks for the AIUI project and fix any issues found. Execute in order:
+
+1. **TypeScript**: Run `pnpm typecheck`. If errors found, read the failing files and fix the type errors.
+2. **Lint**: Run `pnpm lint`. If fixable errors, run `pnpm lint --fix` first, then fix remaining manually.
+3. **Tests**: Run `pnpm --filter @aiui/app test -- --run`. For each failure:
+ - Read the test file and the source file it tests
+ - Determine if the test is wrong (outdated assertion) or the source has a bug
+ - Fix whichever is incorrect
+4. Report a summary: pass/fail counts, what was fixed.
+
+Important: Do NOT change test expectations just to make them pass — understand WHY they fail first.
diff --git a/.claude/skills/deploy/SKILL.md b/.claude/skills/deploy/SKILL.md
new file mode 100644
index 00000000..39e61cb7
--- /dev/null
+++ b/.claude/skills/deploy/SKILL.md
@@ -0,0 +1,32 @@
+---
+name: deploy
+description: Build and prepare AIUI for deployment to Archy node
+allowed-tools: Bash(*), Read, Edit, Glob, Grep
+---
+
+Build AIUI for production deployment. Steps:
+
+1. **Pre-flight checks**:
+ - `pnpm typecheck` — must pass
+ - `pnpm lint` — must pass
+ - `pnpm --filter @aiui/app test -- --run` — report failures but continue
+
+2. **Build**:
+ - `pnpm build`
+ - Verify `packages/app/dist/` exists and contains `index.html`
+
+3. **Bundle analysis**:
+ - Report total dist size and gzip estimate
+ - List the 5 largest chunks
+ - Check against 250KB gzipped budget (warn if over)
+
+4. **Verify nginx config**:
+ - Read `packages/app/server/nginx-archy.conf`
+ - Verify SPA routing (`try_files $uri $uri/ /aiui/index.html`)
+ - Verify proxy paths for Claude API
+
+5. **Container build** (if Dockerfile exists):
+ - `podman build -t aiui:latest packages/app/`
+ - Report image size
+
+6. **Report**: Build status, bundle size, any warnings.
diff --git a/.claude/skills/fix-tab/SKILL.md b/.claude/skills/fix-tab/SKILL.md
new file mode 100644
index 00000000..c1e4e5cd
--- /dev/null
+++ b/.claude/skills/fix-tab/SKILL.md
@@ -0,0 +1,33 @@
+---
+name: fix-tab
+description: Diagnose and fix a broken content panel tab (extraction, routing, rendering)
+allowed-tools: Bash(*), Read, Edit, Glob, Grep, Agent
+---
+
+Diagnose and fix a broken content panel tab. The user will specify which tab (e.g., "app", "code", "image", "nostr").
+
+## Diagnostic pipeline — check each layer:
+
+1. **System prompt**: Does `useAI.ts` SYSTEM_PROMPT tell the AI to use the tag format for this content type? If not, add instructions.
+
+2. **Tag regex**: Does `contentExtraction.ts` have a regex for this content type's tags? If not, add one.
+
+3. **Extraction function**: Does `extractAll{Type}s()` or `extract{Type}s()` exist and work correctly? Test with sample input.
+
+4. **Query classifier**: Do `is{Type}Query()` and/or `is{Type}LikeResponse()` exist in `contentFiltering.ts`?
+
+5. **Tab filtering**: Is the tab included in `filterTabsByContext()` and `preferredFirstTab()`? Check the boolean flag is wired.
+
+6. **useContentPanel.ts**: Is the extraction called in `updatePanelFromText()`? Is the panel ref populated? Is the tab added to `availableTabs`?
+
+7. **ContentPanel.vue**: Is there a grid render block for `activeTab === '{tab}'`? Are imports present? Is the tab in TAB_LABELS?
+
+8. **ContentGridView.vue**: Same checks for the wide desktop view.
+
+9. **ChatPage.vue**: Are the panel data props passed to ContentGridView?
+
+10. **Grid component**: Does the grid component exist and render correctly?
+
+11. **Detail component**: Does the detail component exist?
+
+Fix each broken layer. Run `pnpm typecheck` after all fixes.
diff --git a/.claude/skills/mock-archy/SKILL.md b/.claude/skills/mock-archy/SKILL.md
new file mode 100644
index 00000000..878ac1ad
--- /dev/null
+++ b/.claude/skills/mock-archy/SKILL.md
@@ -0,0 +1,32 @@
+---
+name: mock-archy
+description: Enable/configure mock Archy data for standalone dev testing
+allowed-tools: Bash(*), Read, Edit, Glob, Grep
+---
+
+Set up or modify mock Archy data for testing the Archipelago integration without a real Archy host.
+
+## How it works
+
+Mock data is in `packages/app/src/mocks/archy.ts`. When enabled, `useArchy.ts` loads this data instead of waiting for the Archy bridge.
+
+## Enable mock mode
+
+Two ways:
+1. Add `VITE_MOCK_ARCHY=true` to `.env.local`
+2. Add `?mockArchy` to the URL: `http://localhost:5173/?mockArchy`
+
+## Customization
+
+The user may ask to:
+- Add/remove mock apps from the installed list
+- Change wallet balance or channel count
+- Add/modify files in the mock file list
+- Change system info or network status
+- Test specific scenarios (e.g., "node is syncing", "wallet offline", "no files")
+
+Edit `packages/app/src/mocks/archy.ts` accordingly.
+
+## Verify
+
+After changes, check that `buildArchyContext()` in `useArchy.ts` produces the expected system prompt section by reading the function and tracing the mock data through it.
diff --git a/.claude/skills/new-detail/SKILL.md b/.claude/skills/new-detail/SKILL.md
new file mode 100644
index 00000000..9209e265
--- /dev/null
+++ b/.claude/skills/new-detail/SKILL.md
@@ -0,0 +1,27 @@
+---
+name: new-detail
+description: Generate a detail view component following AIUI glass-morphism patterns
+allowed-tools: Read, Write, Edit, Glob, Grep
+---
+
+Create a new detail view component at `packages/app/src/components/content/{Name}Detail.vue`.
+
+## Requirements
+
+1. **Read a reference**: Read `BookDetail.vue` or `PlaceDetail.vue` as a template.
+
+2. **Follow conventions**:
+ - `
diff --git a/packages/app/src/components/content/ContentPanel.vue b/packages/app/src/components/content/ContentPanel.vue
index ce984770..8424c7ac 100644
--- a/packages/app/src/components/content/ContentPanel.vue
+++ b/packages/app/src/components/content/ContentPanel.vue
@@ -58,53 +58,63 @@
diff --git a/packages/app/src/components/content/FileTreeNode.vue b/packages/app/src/components/content/FileTreeNode.vue
index 5b5f1986..555ff374 100644
--- a/packages/app/src/components/content/FileTreeNode.vue
+++ b/packages/app/src/components/content/FileTreeNode.vue
@@ -1,13 +1,11 @@
-