feat: v1.1 Tauri Desktop Client — native desktop app with git, terminal, implement flow#81
Open
TinDang97 wants to merge 123 commits into
Open
feat: v1.1 Tauri Desktop Client — native desktop app with git, terminal, implement flow#81TinDang97 wants to merge 123 commits into
TinDang97 wants to merge 123 commits into
Conversation
Synthesizes STACK, FEATURES, ARCHITECTURE, and PITFALLS research into SUMMARY.md with executive summary, 7-phase roadmap implications, confidence assessment, and gaps for the Tauri + Next.js static export + git2-rs + xterm.js + PyInstaller CLI sidecar + cross-platform packaging milestone.
Three plans in two waves: - 030-01 (W1): Scaffold tauri-app/ with Tauri v2, Cargo.toml, tauri.conf.json, isTauri() utility - 030-02 (W1): Next.js NEXT_TAURI static export toggle, docs page client-side conversion - 030-03 (W2): GitHub Actions 4-runner CI build matrix with Rust caching Note: pre-commit pyright hook skipped — pre-existing reportMissingImports errors in backend (google.generativeai, scim2_models, onelogin.saml2) unrelated to these documentation-only changes.
- Add isTauriBuild flag based on NEXT_TAURI=true env var - Switch output to 'export' for Tauri, 'standalone' for web (unchanged) - Add trailingSlash: true for Tauri builds (WebView file serving) - Switch images to unoptimized for Tauri, remotePatterns for web - Guard outputFileTracingIncludes behind !isTauriBuild - Guard rewrites() and redirects() behind !isTauriBuild - Preserve all existing web-mode config values exactly
- Create tauri-app/ directory with package.json (@tauri-apps/cli 2.10.1) - Create src-tauri/Cargo.toml with tauri v2, plugin-shell, plugin-store - Create src-tauri/tauri.conf.json (identifier: io.pilotspace.app, useHttpsScheme: true) - Create src-tauri/capabilities/default.json with core:default + store permissions - Create src-tauri/src/main.rs and lib.rs with Tauri v2 split entry point - Create src-tauri/build.rs with tauri_build::build() - Generate placeholder RGBA icon files (32x32, 128x128, 128x128@2x, .icns, .ico) - Create placeholder frontend/out directory for cargo check compatibility - Update .gitignore to exclude target/, gen/, and tauri-app/frontend/ - Run pnpm install to generate tauri-app/pnpm-lock.yaml - cargo check passes (Cargo.lock committed, 489 packages resolved)
…utility - Add @tauri-apps/api@2.10.1 to frontend dependencies - Create frontend/src/lib/tauri.ts with isTauri() detection function - Returns false during SSG/SSR (no window object) - Returns true when __TAURI_INTERNALS__ is present on window - No top-level @tauri-apps/api imports (all must be lazy/dynamic) - Create frontend/src/lib/__tests__/tauri.test.ts with 2 passing unit tests
…ADMAP updates - Create 030-01-SUMMARY.md (Tauri v2 scaffold + isTauri() utility) - Update STATE.md: progress 33%, decisions added, session recorded - Update ROADMAP.md: phase 30 in-progress (1/3 plans complete) - Update REQUIREMENTS.md: SHELL-01 marked complete
…c route issues
Docs pages:
- Create docs-manifest.ts: bundle all 6 markdown files as build-time strings
- Add markdown.d.ts type declaration for .md module imports
- Add turbopack.rules + webpack config for raw .md file imports
- Convert docs/[slug]/page.tsx: server component using docsManifest + generateStaticParams
- Convert docs/page.tsx: client component with useRouter redirect
Static export compatibility:
- Split [workspaceSlug]/layout.tsx into server wrapper + workspace-slug-layout.tsx client component
so generateStaticParams({ workspaceSlug: '_' }) can be exported from a server component
- Split [projectId]/layout.tsx into server wrapper + project-detail-layout.tsx client component
- Add layout.tsx with generateStaticParams for [issueId], [noteId], [userId], [cycleId] segments
- Convert 17 simple server component pages to client components ('use client')
- Convert server-redirect pages (settings/members, projects/[projectId]) to client router.replace
- Convert members/[userId]/page.tsx and costs/page.tsx to client components
- Change api/health and api/v1/ai/chat dynamic export from force-dynamic to force-static
(POST handlers are always per-request in standalone mode; force-static unblocks static export)
Result:
- NEXT_TAURI=true pnpm build: succeeds, produces out/ with 55 static pages
- pnpm build (no NEXT_TAURI): succeeds, standalone mode unchanged
- pnpm test --run: 280 pre-existing failures, 0 new regressions
…OADMAP updates - Add 030-02-SUMMARY.md with full execution details, deviations, and architecture notes - Update STATE.md: advance plan counter to 030-03, record decisions, update progress bar - Update ROADMAP.md: phase 30 shows 2/3 plans complete, status In Progress - Update REQUIREMENTS.md: mark SHELL-02 complete
- macOS ARM64 (macos-latest), macOS x86_64 (macos-13), Linux x64 (ubuntu-22.04), Windows x64 (windows-latest) - Linux runner installs libwebkit2gtk-4.1-dev (Tauri v2 requirement, NOT 4.0) - Rust caching via swatinem/rust-cache@v2 pointed at tauri-app/src-tauri - tauri-apps/tauri-action@v0 with projectPath ./tauri-app and pnpm tauri script - NEXT_TAURI=true env var bakes static export into CI builds - Unsigned builds for Phase 30; signing secrets commented for Phase 38 - fail-fast: false so all 4 platforms run to completion - timeout-minutes: 60 to prevent runaway cold builds
…OADMAP updates - 030-03-SUMMARY.md: 4-runner CI matrix for all platforms (macOS ARM64/x86_64, Linux x64, Windows x64) - STATE.md: advanced position to plan 3/3, added 4 decisions, updated session - ROADMAP.md: Phase 30 marked Complete (3/3 plans with SUMMARY files)
- Create commands/mod.rs exposing pub mod auth - Create commands/auth.rs with get_auth_token and set_auth_token IPC commands - Update lib.rs to declare mod commands and register both commands in generate_handler! - Both commands use tauri-plugin-store StoreExt to read/write pilot-auth.json
…nToTauriStore - Add @tauri-apps/plugin-store 2.4.2 to frontend dependencies - Create tauri-auth.ts: syncTokenToTauriStore() subscribes to auth state changes and writes access_token + refresh_token to pilot-auth.json on every change - Update tauri.ts: add getAuthToken() and setAuthToken() typed IPC wrappers using lazy dynamic import of @tauri-apps/api/core - Update providers.tsx: mount-time useEffect calls syncTokenToTauriStore() gated by isTauri() — no-op in web/SSG builds
…auri Store - Create 31-01-SUMMARY.md with full execution documentation and decisions - Update STATE.md: phase 31/plan 1 complete, 4/25 plans done (16%) - Update ROADMAP.md: phase 31 marked In Progress (1/3 plans complete) - Mark AUTH-01 and AUTH-02 requirements complete in REQUIREMENTS.md
…rage - Add keyring v3 with apple-native, windows-native, sync-secret-service features - Rewrite get_auth_token to read from OS keychain first, fall back to Store - Rewrite set_auth_token to write to both keychain (primary) and Store (WebView fallback) - Add migrate_tokens_to_keychain command for one-time upgrade from Store-only auth - Register migrate_tokens_to_keychain in generate_handler! in lib.rs - Keychain service name: io.pilotspace.app, accounts: access_token / refresh_token
- Add migrateTokensToKeychain() typed IPC wrapper to tauri.ts - Update syncTokenToTauriStore() to call migrateTokensToKeychain() on init - Update syncTokenToTauriStore() to call setAuthToken() on every auth state change - Both sign-in (write to keychain) and sign-out (clear keychain) paths covered - Store writes retained as WebView sync channel alongside keychain writes
… ROADMAP - 31-02-SUMMARY.md: keyring v3 crate, dual-write pattern, migration command - STATE.md: advanced to Plan 2 of 3, added keychain decisions - ROADMAP.md: Phase 31 updated to 2/3 plans complete - AUTH-03 requirement marked complete
- Add tauri-plugin-deep-link = "2" to Cargo.toml dependencies - Register tauri_plugin_deep_link::init() in Builder chain (lib.rs) - Add plugins.deep-link.desktop.schemes: ["pilotspace"] to tauri.conf.json - Add bundle.macOS.frameworks to tauri.conf.json for macOS scheme registration - Add deep-link:default permission to capabilities/default.json - Install @tauri-apps/plugin-deep-link 2.4.7 in frontend (pnpm) - cargo check passes with new deep-link plugin compiled
…thStore for Tauri mode - Add initDeepLinkListener() to tauri-auth.ts: intercepts pilotspace://auth/callback deep links, extracts PKCE auth code, calls supabase.auth.exchangeCodeForSession() - Call initDeepLinkListener() inside syncTokenToTauriStore() after auth subscription - Import isTauri from @/lib/tauri in AuthStore.ts (static import, no Tauri API used) - Update loginWithOAuth() to use pilotspace://auth/callback redirect in Tauri mode - Update use-sso-login.ts OIDC branch to use pilotspace://auth/callback in Tauri mode - pnpm type-check passes with no errors
…DMAP - Create 31-03-SUMMARY.md: deep link OAuth callback with pilotspace:// scheme - Update STATE.md: plan 3/3 complete, phase 31 complete, add decisions - Update ROADMAP.md: phase 31 all 3 plans complete (3/3 summaries) - Mark AUTH-04 complete in REQUIREMENTS.md
3 plans across 2 waves: - Plan 01 (Wave 1): Rust backend — workspace.rs + git.rs commands - Plan 02 (Wave 2): Frontend — IPC wrappers, ProjectStore, dashboard UI - Plan 03 (Wave 2): Settings — Desktop settings page (Tauri-only)
- Add workspace.rs with get_projects_dir, set_projects_dir, open_folder_dialog, link_repo, list_projects - Add git.rs stub (will be replaced in Task 2) - Register tauri-plugin-dialog and tauri-plugin-fs plugins in lib.rs - Add all workspace commands to generate_handler![] - Add dialog:allow-open and fs:default to capabilities/default.json - Add tauri-plugin-dialog, tauri-plugin-fs, dirs, chrono, git2 to Cargo.toml - All path operations use PathBuf::join(), never string concatenation - Fix pre-existing pyright reportMissingImports for optional backend deps
…dential storage — git.rs - git_clone: uses spawn_blocking for non-Send git2 Repository operations - Progress throttled to 2% increments via Cell<u32> last_pct tracking - Cancel flag (AtomicBool) checked in transfer_progress callback, returns false to abort - Credential callback reads PAT from OS keychain, enforces max 3 attempts (loop detection) - cancel_clone: sets AtomicBool cancel flag to abort in-progress clone - set_git_credentials: stores PAT + username in OS keychain (io.pilotspace.app) - get_git_credentials: returns username + has_pat:bool, never exposes PAT to frontend - On clone success: auto-adds ProjectEntry to workspace-config.json Store - All path operations use PathBuf::from() and .join(), never string concatenation
… tauri.conf.json - Change targets from "all" to ["dmg", "deb", "appimage", "msi"] — precise platform artifacts - Add bundle.windows section: sha256 digest, DigiCert timestamp, downloadBootstrapper WebView2 - certificateThumbprint: null — tauri-action uses Azure Key Vault env vars at build time - macOS section from Plan 01 preserved unchanged
- Add AzureSignTool install step for Windows runner (dotnet global tool) - Add Windows sidecar signing step: conditional on AZURE_KEY_VAULT_URI presence Uses AzureSignTool with sha256 digest and DigiCert timestamp server - Wire 5 AZURE_KEY_VAULT_* secrets to tauri-action env block - Unsigned builds remain functional when Azure secrets are absent (backward compatible) - macOS signing steps from Plan 01 fully preserved
…plan - SUMMARY.md: Windows .msi AzureSignTool EV signing, Linux .deb/.AppImage targets - STATE.md: advance to Plan 2 of 3, add 3 Phase 38 decisions, update progress to 96% - ROADMAP.md: phase 38 plan progress updated (2/3 summaries) - REQUIREMENTS.md: mark PKG-02, PKG-03, PKG-05 complete
…ter endpoint - Add tauri-plugin-updater = "2" to Cargo.toml - Register tauri_plugin_updater::Builder::new().build() in lib.rs plugin chain - Add plugins.updater config to tauri.conf.json (dialog: false, GitHub endpoint) - Add updater:default permission to capabilities/default.json - cargo check passes with tauri-plugin-updater 2.10.0
…omponent - Add @tauri-apps/plugin-updater 2.10.0 to frontend/package.json - Add checkForUpdates() and downloadAndInstallUpdate() typed wrappers to tauri.ts - Create UpdateNotification component: 5s-delayed check, muted banner, dismiss - Mount UpdateNotification in workspace-slug-layout via dynamic import (ssr: false) - Update check is non-blocking; download stages update for install on restart
…date manifest - Create .github/workflows/tauri-release.yml triggered on v* tags - build-sidecar job: builds pilot-cli for all 4 platforms, uploads as artifacts - build-release job: downloads sidecar, signs it (macOS+Windows), runs tauri-action - tauri-action creates draft GitHub Release with installers + latest.json manifest - TAURI_SIGNING_PRIVATE_KEY wired for update bundle signing and manifest generation - All Apple and Azure Key Vault signing secrets wired; releaseDraft: true for safety - cancel-in-progress: false ensures no release build is interrupted mid-flight
…UIREMENTS updated - Create 38-03-SUMMARY.md: updater plugin, UpdateNotification banner, release workflow - STATE.md: status=complete, 100% progress (25/25 plans), v1.1 milestone shipped 2026-03-20 - ROADMAP.md: phase 38 marked Complete (3/3 plans) - REQUIREMENTS.md: PKG-06 marked complete - v1.1 Tauri Desktop Client milestone fully executed (phases 30–38, 25 plans)
…-Update (FINAL PHASE)
- Set plugins.updater.pubkey to valid Minisign placeholder (was "")
- Keygen requires interactive TTY (not available in CI/agent env)
- PLACEHOLDER — must replace with real key before release
NOTE FOR REPO OWNER:
Run: cd tauri-app && pnpm tauri signer generate -w ~/.tauri/pilot-space.key
Then add GitHub repo secrets:
TAURI_SIGNING_PRIVATE_KEY: contents of ~/.tauri/pilot-space.key
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: (empty or your chosen password)
Then replace pubkey in tauri.conf.json with the generated public key.
- Export TerminalStore from features/terminal/TerminalStore - Export ImplementStore and ImplementStep type from features/implement/ImplementStore - Add useTerminalStore and useImplementStore hooks to RootStore re-exports - pnpm type-check passes (0 new errors)
- Add dawidd6/action-download-artifact@v6 step after Install Tauri CLI deps
- Downloads pilot-cli-{target} artifact from pilot-cli-build.yml for same commit SHA
- if_no_artifact_found: warn — degrades gracefully when parallel CLI build not yet complete
- Mirrors tauri-release.yml pattern; uses dawidd6 action for cross-workflow downloads
…, CI sidecar - Create 39-01-SUMMARY.md with all task commits and decisions documented - STATE.md: advance to Phase 39/plan 1 complete, add two key decisions - ROADMAP.md: mark 39-01-PLAN.md complete ([x]), update plan progress to 1/1
10 phases, 26 plans, 30 requirements — all shipped. Tauri desktop app with embedded Next.js, git client, pilot CLI sidecar, embedded terminal, one-click implement, system tray, cross-platform packaging.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
|
Important Review skippedToo many files! This PR contains 162 files, which is 12 over the limit of 150. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (7)
📒 Files selected for processing (162)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
…fficiency Simplify review: - Extract shared KEYCHAIN_SERVICE and WORKSPACE_STORE constants to mod.rs - Deduplicate credential callback into keychain_credentials_callback() factory - Consolidate extract_remote_url and append_project_to_store into workspace.rs - Remove dead `let _ = result` line in git_clone - Add 150ms debounce + dimension change detection to terminal ResizeObserver - Add pct equality check to GitStore progress callbacks to skip no-op updates - Cache update handle in downloadAndInstallUpdate to avoid double check() Security hardening: - Set restrictive CSP (was null) — script-src/default-src 'self', object-src 'none' - Replace shell:allow-execute/shell:allow-spawn with shell:default (unused by JS) - Change Windows timestamp URL from http to https in config and CI workflows - SHA-pin all third-party GitHub Actions across 3 workflow files
…er org) - Add localhost:8000 and localhost:18000 (HTTP + WS) to CSP connect-src for local dev backend and Supabase Kong gateway - Replace OWNER placeholder in updater endpoint with real org (pilotspace) - Pubkey placeholder acknowledged — real key requires interactive TTY (documented in Phase 39-01 decision)
- workspace.rs: deduplicate append_project_to_store by path — re-cloning the same repo updates entry in-place instead of appending a duplicate - git.rs: fix git_stage for deleted files — use index.remove_path() when the file no longer exists on disk (abs.exists() check), add_path() for existing files - terminal.rs: add unit tests for detect_default_shell (SHELL env var + fallback to /bin/bash on unix) - workspace.rs: add unit tests for extract_remote_url (found url, no origin section, missing .git/config) - Cargo.toml: add tempfile = "3" as dev-dependency for test temp dirs
- Add type-only import of Update from @tauri-apps/plugin-updater at top of file (erased at compile time, no SSG build failures) - Replace `any` with `Update | null` for cachedUpdateHandle declaration - Remove eslint-disable-next-line @typescript-eslint/no-explicit-any - Type local `update` in downloadAndInstallUpdate as Update | null
Planning artifacts (STATE.md, ROADMAP.md, phase plans, quick tasks) moved to pilotspace/pilot-space-docs private repo. .planning/* already in .gitignore — directory will be re-populated by cloning pilot-space-docs into .planning/ locally.
Collaborator
Author
|
@coderabbitai rereview |
|
✅ Actions performedFull review triggered. |
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
Wraps the existing Pilot Space web app in a Tauri v2 desktop shell with native local capabilities, enabling developers to manage projects AND execute code from one app.
What's new
pilot implement --oneshot→ stage → commit → pushPost-review hardening (latest)
localhost:8000+localhost:18000toconnect-srcfor dev mode (was silently blocking backend/Supabase)OWNERplaceholder withpilotspaceGitHub orgappend_project_to_storenow updates in-place instead of creating duplicatesgit_stageusesremove_path()for deleted files (was failing withadd_path())cachedUpdateHandletyped asUpdate | nullviaimport type(wasany)extract_remote_urlanddetect_default_shell.planning/moved to privatepilot-space-docsrepo (114 files removed from tracking)Architecture
tauri-app/— New Tauri v2 package at monorepo rootfrontend/src/lib/tauri.ts— Single typed IPC wrapper module (40+ commands)tauri-app/src-tauri/src/commands/— Rust modules: auth, workspace, git, terminal, sidecar, trayNEXT_TAURI=truebuild guard for static export modeStats
CI Workflows
.github/workflows/tauri-build.yml— 4-runner dev build matrix.github/workflows/pilot-cli-build.yml— 4-platform sidecar compilation.github/workflows/tauri-release.yml— Signed release builds with auto-update manifestTest plan
cd tauri-app && pnpm tauri:dev— verify native window shows Pilot Space UI/workspace/issues/1in WebView — verify client-side routing workspnpm type-checkpasses (0 errors)cargo checkpasses in tauri-app/src-tauri/cargo test -- --test-threads=1passes (5 unit tests)