Install vp using the root README. The checkout requires Node 24;
Bun is optional. From the repository root:
vp i
vp run devOpen the one-time pairing URL printed by the dev runner. The bare origin does not authenticate a new browser.
Use vp run dev for server and web, or vp run dev:desktop for the Electron client.
dev:server and dev:web start those processes separately.
See the mobile README for native builds and Metro.
Flags go directly after the task name, for example vp run dev --home-dir /tmp/t3code-dev.
Add --browser to open a browser automatically.
Linked worktrees default to their own .t3/userdata, even when T3CODE_HOME is set.
The main checkout defaults to ~/.t3/dev/userdata. An explicit --home-dir wins in both cases.
Never run a development server against the live ~/.t3/userdata.
See test data for copying a consistent database snapshot.
Read ports from the [dev-runner] output. Worktrees derive stable preferences from their paths,
but occupied ports can shift them. T3CODE_PORT_OFFSET or T3CODE_DEV_INSTANCE can select a
different preference when needed.
vp run dev --share publishes the web port over the machine's tailnet and prints a pairing URL
for that origin. Give the tester the complete URL, including its token. The dev runner removes
its mapping on exit.
Leave VITE_HTTP_URL and VITE_WS_URL unset. Vite proxies the backend through the browser's
origin so the same build works over localhost and remote connections.
Shared runs enable bundled dev to avoid a network round trip for each import level.
T3CODE_BUNDLED_DEV=0 opts out when debugging bundler differences. Two reload traps matter
when changing this setup:
- The web entry must dynamically import the app so React refresh initializes before application chunks. Static imports can work on first load and fail after a route split.
- Bundled dev rebuilds Tailwind through watched files. Its ordinary Vite hot-update hook expects a server/module graph that Rolldown does not provide.
The workarounds live in the web entry and Tailwind plugin.
Run checks for the files and packages you changed:
vp test run <files>
vp lint <files>
vp run --filter <package> typecheckUse vp run lint:mobile for native mobile changes. CI owns the full suite; see
ci.yml for its current jobs.
The manual Windows lane is available for focused
Windows investigation while that suite is not a required gate.
vp run knip:check checks unused files and dependencies across the repo, then
unused runtime exports in apps/web and every internal package under packages/.
CI enforces both checks.
Exported types and Effect schemas are allowed without consumers. The schema preprocessor
recognizes schema types, including aliases and schema classes; functions that create or decode
schemas remain checked. Completely unused files remain checked too.
Named exports in web UI component modules are kept as complete component sets. Knip ignores
unused exports in apps/web/src/components/ui/*.tsx, while still reporting an entire unused file.
Use vp run knip --workspace apps/web to audit one workspace, including exports,
or vp run knip:production --workspace apps/web to find code kept alive only by tests.
The full export audit still has findings and is not a repo-wide CI gate. Extend the
export check's workspace selectors as more workspaces become clean. Review callers before
deleting code; production mode can also report development scripts and test fixtures.
Runtime-discovered entrypoints and dependency exceptions belong in knip.jsonc.
Local artifact builds are unsigned by default and write to release/:
vp run dist:desktop:dmg
vp run dist:desktop:linux
vp run dist:desktop:winDMGs default to the host architecture. Use --arch to choose another target and --keep-stage
to retain packaging files for inspection. Run vp run dist:desktop:artifact --help for other
options.
Build on Linux because the browser-secret helper links against the host's libsecret. Install Rust, C/C++ build tools, libsecret development headers, pkg-config, and ImageMagick.
Ubuntu and Debian:
sudo apt-get update
sudo apt-get install cargo rustc build-essential libsecret-1-dev pkg-config imagemagickFedora:
sudo dnf install rust cargo gcc gcc-c++ make libsecret-devel pkgconf-pkg-config ImageMagickArch Linux:
sudo pacman -S rust base-devel libsecret pkgconf imagemagickThe C toolchain, pkg-config, and libsecret headers are also needed for Linux desktop development.
Install the Xcode Command Line Tools with xcode-select --install and install Rust.
For a cross-architecture or universal build, add the requested Rust targets:
rustup target add aarch64-apple-darwin x86_64-apple-darwinInstall Rust, Python 3, and Visual Studio Build Tools with Desktop development with C++. Include the Windows SDK and the MSVC build tools and Spectre-mitigated libraries for the target architecture. Add its Rust target:
rustup target add x86_64-pc-windows-msvc
# For an ARM64 installer:
rustup target add aarch64-pc-windows-msvcNSIS is downloaded by electron-builder. WSL support additionally needs a Linux node-pty prebuild; see the release runbook.
Add --signed after configuring the platform credentials in the
release runbook. macOS passkeys need a signed, provisioned app; follow the
Connect setup for local signing and renderer HMR.