A standalone desktop Git client built on the
bones engine. The repository contains a snapshot of
@an-dr/commits-core in packages/core and a reusable webview
shell in packages/webview-shell, while the Bones host
and its adapter live under apps/commits. The adapter is
compiled to a WebAssembly component and runs the same Git Graph webview used by
the extension in a wry panel.
Everything here is MIT-licensed, including the vendored engine; see
THIRD_PARTY_NOTICES.md for the upstream lineage and
the dependency licenses that carry their own terms.
Phases 0 and 1 provide the walking skeleton: the native app, TypeScript guest
toolchain, shared binary codec, HostPort, VS Code page API shim, and a typed
echo round trip. Real Git behavior starts in Phase 2.
- Rust 1.94 or later
- Node.js 22.12 or later and npm
- CMake and Ninja
- A working C/C++ toolchain
- WebView2 on Windows
Nothing here is bundled, and a machine that has never built native Rust is
missing most of it. On a fresh Windows box the two that actually stop the build
are Rust and the MSVC toolchain, and neither failure names itself clearly:
without Rust, npm run build:host reports an unknown cargo; without MSVC,
cargo reports a missing link.exe. Install both up front:
# Rust, per user, no administrator rights needed
winget install --id Rustlang.Rustup -e
# MSVC compiler, linker and the Windows SDK, needed by the
# x86_64-pc-windows-msvc target and the vendored engine's CMake build.
# Requires administrator rights and downloads several gigabytes.
winget install --id Microsoft.VisualStudio.2022.BuildTools -e --override `
"--quiet --wait --norestart --nocache --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"Verify before building, because a partial toolchain fails deep into a long compile rather than at the start. Each of these must print a path:
(Get-Command cargo).Source
(Get-Command cmake).Source
(Get-Command ninja).Source
& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" `
-latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPathNode must be 22.12 or later: vitest pulls in vite and rolldown, which
refuse anything earlier. npm install only warns about this, then npm test
fails, so it is easy to mistake for a broken checkout.
WebView2 ships with current Windows 11. Confirm it, since the app opens an empty window without it:
(Get-ItemProperty "HKLM:\SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}").pvInitialize the nested bones dependencies after cloning:
git submodule update --init --recursive
npm installA clone that predates the bones 1.0 pin also carries a nested agents
submodule that the 1.0 tree no longer has. Git cannot drop it on its own — it
reports unable to rmdir agents: Directory not empty and leaves an untracked
directory that reads as part of the checkout. Clear it once, from the
repository root:
Remove-Item -Recurse -Force vendor\bones\agents -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force .git\modules\vendor\bones\modules\agents -ErrorAction SilentlyContinue
git -C vendor\bones config --remove-section submodule.agentsThe last line prints no such section on a clone that never had it, which is
the harmless case — nothing to clear.
On Windows ARM64, npm run build bootstraps a repository-local wizer
10.0.0 because the upstream npm package has no prebuilt ARM64 executable.
That first build is slow; later builds reuse .tools/wizer/bin/wizer.exe.
npm run build
npm run verifyEach part builds on its own, so an unchanged part is never rebuilt. The host is the slow one because it compiles the vendored engine; the page is the fast loop.
| Target | Rebuilds | Run it after changing |
|---|---|---|
npm run build:web |
page bundle and markup | apps/commits/web, packages/webview-shell |
npm run build:wasm |
the WebAssembly components | apps/commits/bones-adapter, packages/core |
npm run build:host |
the native executables | apps/commits/host, crates/, vendor/bones |
npm run dist:web, dist:wasm and dist:host refresh the matching part of
dist/app in place. npm run clean is the only thing that removes output.
Assemble a runnable release directory:
npm run dist
.\dist\app\commits.execommits takes one optional argument: the repository to open.
commits C:\path\to\repository
commits .A relative path resolves against the shell's working directory, so commits .
opens the folder you are standing in. The path must be a git repository; a
missing folder, a file, or a folder without a .git leaves the app on the
chooser saying which of those it was, rather than failing to start.
Started with no argument, it opens the chooser rather than reattaching to whatever was last in use. The chooser lists recent repositories, and its input is pre-labelled with the last one — pressing Enter on the empty box reopens it, so the common case is still one keystroke. The same list is under Recent in the menu, for switching without leaving the graph.
A window that opens black, with no menu bar, means the commits component
failed to attach. The engine treats that as non-fatal -- it logs the error and
keeps ticking -- so nothing ever opens the panel. The app now reports this in a
dialog and writes commits.log beside the executable; the previous run is kept
as commits.prev.log, because relaunching is the first thing anyone tries.
Get-Content .\dist\app\commits.logThe line to look for is:
[ERROR] engine: failed to load ...\extensions\commits.wasm: error while executing at wasm backtrace: ... init
This is a timing failure, not a broken build. instantiate plus init must
finish inside a wall-clock budget, and commits.wasm is roughly 12 MB carrying
an embedded JavaScript engine. Because the budget is wall clock, it is spent by
any delay at all, not only by work: a busy machine, a first run where the file
is not in the page cache and a virus scanner is still reading a newly written
12 MB binary, or a launch straight after npm run dist.
The engine's default budget of one second was too tight for this component --
under heavy CPU load it failed every launch, while the same bytes loaded every
time on an idle machine. The app therefore asks for thirty seconds through
Engine::extension_load_timeout in
apps/commits/host/src/main.rs; the same load
that used to fail four times out of four now succeeds four times out of four.
If you still see this, the machine is slower than that allowance rather than misconfigured: raise the value there. Relaunching on a quiet machine also works.
The repository splits by who can use the code: packages/ holds
what the VS Code extension consumes, apps/ holds this application, and
each directory's README states what belongs in it.
Architecture and current verification evidence are indexed in
docs/index.md.