feat: Tauri desktop app — Harness Manager + Marketplace browser#17
Merged
feat: Tauri desktop app — Harness Manager + Marketplace browser#17
Conversation
- Bootstrap apps/desktop/ with Tauri v2 + React 19 + Vite + Tailwind CSS 4 - Sidebar shell with 4 sections: Harness Manager, Marketplace, Observatory, Comparator - Harness Manager pages: Plugins, Hooks, CLAUDE.md viewer, Settings - Rust commands: list_installed_plugins, list_marketplaces, read_hooks, read_claude_md, list_claude_dir - Light/dark theme system with prefers-color-scheme + localStorage override - New packages/ui/ shared component library (Button, Card, Badge, Input) - Extend @harness-kit/shared types: InstalledPlugin, KnownMarketplace, HooksConfig - Update monorepo: pnpm-workspace.yaml, root scripts, .gitignore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Reduce body font to 13px with -apple-system font stack (macOS native) - Replace generic card borders with row-list pattern (1px separator dividers) - Refine color tokens: warm-neutral palette, semantic rgba borders, near-black dark mode (#1c1c1e) matching macOS system backgrounds - Sidebar: remove emoji, tighten spacing (28px rows), add accent-tint active states, section label hierarchy with sub-items - Add CSS utility classes: .row-list, .row-list-item, .sidebar-item, .sidebar-subitem for consistent macOS-style components - ClaudeMdPage: add file path titlebar, proper monospace code view - ComingSoonPage: minimal placeholder (no emoji/icons) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add RLS policies migration (00002): public read via anon key, writes restricted to service_role, SECURITY DEFINER on increment_install_count - Add @supabase/supabase-js + dompurify to desktop dependencies - Create Supabase client (null-safe, VITE_ env vars, graceful degradation) - Add vite-env.d.ts (was missing, needed for import.meta.env types) - BrowsePage: search, category/type filter pills, sort toggle, plugin list with trust/type badges; fetches components + categories client-side - PluginDetailPage: header, stats bar, tags, DOMPurify-sanitized SKILL.md and README.md rendering, sidebar with install command/author/related plugins - Wire marketplace routes in App.tsx, add Browse child to sidebar nav Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…path - BrowsePage: add useSearchParams to read ?tag= from navigation, fetch component_tags + tags tables, add client-side tag filter with active tag banner and clear button; fix ccRes.error being silently swallowed; use shared ComponentCategory type; select only list-view columns (skip skill_md/readme_md); add aria-pressed to pills - PluginDetailPage: add <br to renderMarkdown paragraph lookahead - RLS migration: pin search_path on SECURITY DEFINER function Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- markdown.ts: extract renderMarkdown into standalone module + 18 unit tests covering headings, inline formatting, blocks, security (XSS/script strip), and multiline documents - BrowsePage.test.tsx: 36 tests covering not-configured state, loading, plugin list display, search/category/type/tag filtering, sort order, plugin count, navigation, and error handling - PluginDetailPage.test.tsx: 34 tests covering not-configured, loading, not-found, plugin details, trust/type badges, tags, markdown sections, sidebar (install command, author, GitHub link, related plugins), navigation, and error state - vite.config.ts: add vitest config (jsdom, setupFiles, coverage) - test-setup.ts: @testing-library/jest-dom matchers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace custom regex renderer with react-markdown + remark-gfm for full GFM support (tables, task lists, code blocks, blockquotes) - Add Preview/Raw tab toggle to each markdown section (Skill Definition and Documentation) so users can see rendered and raw content - Add .markdown-body CSS block to app.css using design system tokens (light/dark mode compatible) - Add resolve.preserveSymlinks: true to vite.config.ts to fix pnpm symlink resolution for ESM-only packages Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ction - BrowsePage: add missing tagRes.error check so tag query failures surface to the user rather than silently producing an empty filter list - read_claude_md Rust command: canonicalize path and verify it stays within the user's home directory, preventing arbitrary file reads Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
146a1ea to
522b63e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces the harness-kit desktop app (Tauri v2 + React 19) with two main sections: Harness Manager (reads real
~/.claude/data — plugins, hooks, settings, CLAUDE.md) and Marketplace Browser (connects to Supabase to browse and view all 10 published plugins). The marketplace detail pages render SKILL.md and README.md with full GFM markdown and a Preview/Raw toggle.This PR does not expose any marketplace UI on the web — the website changes here are docs-site improvements only (plugin page visual polish, MarkdownViewer component for docs accordions).
Changes
apps/desktop/— full Tauri v2 desktop app: React 19, Vite 6, Tailwind 4, react-router-dom v7apps/desktop/src-tauri/— Rust commands:list_installed_plugins,list_marketplaces,read_hooks,read_claude_md,list_claude_dirapps/desktop/src/pages/marketplace/— BrowsePage (search, filter, sort) and PluginDetailPage (full markdown rendering with Preview/Raw tabs)apps/desktop/src/lib/supabase.ts— Supabase client (null-safe: shows "not configured" if env vars absent)apps/desktop/src/lib/markdown.ts— minimal markdown renderer (used in tests; detail page now uses react-markdown)marketplace/supabase/migrations/00002_rls_policies.sql— RLS policies: anon = read-only SELECT, writes via service_role onlypackages/shared/andpackages/ui/— shared types and UI primitiveswebsite/— docs visual polish, MarkdownViewer component, plugin doc page updates, remark-embed rewriteplugins/usage-stats/— new usage-stats plugin (Claude Code activity dashboard)vite.config.ts—resolve.preserveSymlinks: truefor pnpm + ESM package compatibilityTest Plan
pnpm testinapps/desktop/) — BrowsePage (36), PluginDetailPage (34), markdown renderer (18)pnpm tauri devfromapps/desktop/— Browse shows 10 plugins, detail page renders markdown with Preview/Raw toggle.envremoved, app shows graceful "not configured" messageNotes
Supabase setup required to validate locally — see steps below in PR comments. The anon key (read-only) ships in
.envand is intentionally public. Service role key stays server-side only.react-markdownv9 andremark-gfmv4 are ESM-only;resolve.preserveSymlinks: truein vite.config.ts is the required fix for pnpm's symlinked node_modules.The marketplace Supabase project (
xaneywqwezfgjzzsmzsf) is already provisioned and seeded with all 10 plugins including full SKILL.md and README.md content.