Thanks for your interest in contributing!
HarnessKit is a Cargo workspace containing four Rust crates and a React + Vite frontend in src/. The desktop app is packaged with Tauri; the CLI embeds the built frontend via rust-embed to serve it in web mode.
- Node.js β₯ 20 (Vitest 4 requires Node β₯ 20; Node 18 is end-of-life)
- Rust 1.85+ (edition 2024) β install via rustup
- Tauri CLI (only for desktop development):
cargo install tauri-cli --version "^2.0.0" - Xcode Command Line Tools (macOS only):
xcode-select --install
This project uses npm, not pnpm or yarn.
git clone https://github.com/RealZST/HarnessKit.git
cd HarnessKit
npm ciUse npm ci rather than npm install: it installs exactly what package-lock.json pins, keeping the @tauri-apps/* packages aligned with their matching Rust crates. Re-run it after every git pull / git rebase to pick up newly added dependencies. If you hit a Tauri version-mismatch error, see Troubleshooting.
Two terminals β Vite dev server + Rust backend:
# Terminal A
npm run dev # http://localhost:1420 (HMR)
# Terminal B
cargo run -p hk-cli -- serve # http://127.0.0.1:7070Open http://localhost:1420 in your browser. Vite proxies /api/* requests to the backend at :7070.
cargo tauri devTauri automatically runs npm run dev as a before-dev command and launches the native window. On Windows, the Visual Studio Build Tools ("Desktop development with C++") that rustup asks for are the only extra prerequisite. cargo tauri build packages NSIS and MSI installers under target/release/bundle/; because createUpdaterArtifacts is on, it also needs TAURI_SIGNING_PRIVATE_KEY in the environment, or pass --config '{"bundle":{"createUpdaterArtifacts":false}}' for a local build without updater artifacts.
./build.shProduces .dmg bundles for Apple Silicon and Intel, plus hk CLI binaries.
The release workflow (release-desktop-windows in release.yml) builds the NSIS installer on a Windows runner and attaches it, with its updater signature, to the GitHub release. To build one locally on Windows, see Desktop App Development.
npm run build # produce dist/ for rust-embed
cargo build --release -p hk-cli # produces target/release/hkOn macOS and Linux, scripts/install-local.sh runs both steps and copies the binary to ~/.local/bin/hk for local testing. That is the same path install.sh uses, so it replaces a release install; rerun install.sh to switch back.
./scripts/install-local.shcrates/
βββ hk-core/ Shared core: scanning, models, DB, agent adapters
βββ hk-desktop/ Tauri desktop app (wraps hk-core + frontend)
βββ hk-cli/ CLI binary (hk); includes `hk serve` for web mode
βββ hk-web/ HTTP layer for web mode (embedded into hk-cli via rust-embed)
src/ React frontend (shared by desktop app and web mode)
βββ pages/ Route pages (Overview, Kits, Agents, Extensions, Marketplace, Audit, Settings)
βββ components/ Shared UI components
βββ stores/ Zustand stores
βββ hooks/ Custom React hooks
βββ lib/ Utils, API client, type definitions
βββ types/ Shared TypeScript type definitions
public/ Static assets
npm test # frontend tests (vitest)
cargo test --workspace # Rust tests
cargo fmt --all # Rust formatting (CI rejects unformatted code)Tests that need an isolated home directory set HARNESSKIT_HOME, which hk_core::home_dir() honors ahead of the real home. It exists for test isolation (on Windows the home directory cannot be redirected through HOME); it is not a supported way to relocate HarnessKit's data.
Tauri's CLI requires each npm @tauri-apps/* package and its matching Rust crate to share the same major and minor version (patch may differ) β the core pair is @tauri-apps/api β the tauri crate, and each @tauri-apps/plugin-<name> β its tauri-plugin-<name> crate. Running npm install instead of npm ci can bump a package within its ^ range while Cargo.lock stays pinned, desyncing the two. A mismatch errors out cargo tauri build (and the mobile build/run commands) and is logged as an error on cargo tauri dev (which still starts); pass --ignore-version-mismatches to build anyway when it is a known false positive.
- Accidental drift β you ran
npm installand the lockfiles diverged: restore the tracked lockfiles and reinstall withgit restore Cargo.lock package-lock.json && npm ci. - Intentional plugin upgrade β bump the npm package in
package.json, then sync only the matching crate withcargo update -p tauri-plugin-<name>(e.g.cargo update -p tauri-plugin-dialog). Use a barecargo updateonly when you intend to refresh every dependency.
Upstream likely added a new frontend dependency (e.g. react-i18next). Run npm ci to install it.
- Create a feature branch from
main(e.g.fix/marketplace-loadingorfeat/new-agent) - Use Conventional Commits in commit messages β
feat:,fix:,chore:,docs:,refactor: - Ensure
npm testandcargo test --workspacepass andcargo fmt --allleaves no changes before opening a PR - Write a clear PR description: what problem it solves and how
- For UI changes, include a screenshot or short video
- Small, focused PRs are easier to review than large ones β prefer splitting when possible