Documentation
What Oak is
Oak is a purpose-built VCS designed for agent-driven development. It's the thing your coding agent (Claude Code, Codex, Cursor, etc.) can use to store code and assets.
Oak doesn't run agents. Bring your own. What Oak gives you is the storage and collaboration layer underneath: branch-per-session workflows and lazy mounts for large repos.
Today's release ships macOS on Apple Silicon and Linux. Windows builds will come eventually.
Organizations
An organization is the owner of repositories. Every account gets a personal organization (named after your username); you can also create shared organizations for teams and companies.
The organization is also the deduplication boundary for storage. Blobs and chunks are shared across every repo within the same organization, so a binary asset committed to two repos in the same org is stored once. Storage and bandwidth quotas are accounted at the organization level.
Repository URLs are <organization>/<repo> โ for example oakspace/oak.
Branches and descriptions
The unit of work in Oak is a branch, not a commit. oak init and oak clone auto-create a personal feature branch off main โ you never work directly on main locally. This matches how agents work: one branch per session, merged when the session is done.
Commits on feature branches have no commit message. Instead, the branch description is the source of truth for what a change introduces. Create a branch with oak switch -c <name> and set its description with oak desc "...".
Merging a feature branch into main produces a single squash commit whose message is the branch description. The squash commit retains a pointer to the original branch tip, so the pre-squash history stays reachable for tooling. Direct pushes to main are refused.
Lazy mounts
oak mount lets a working tree live on top of a remote repository without a full local clone. Files materialize lazily through macFUSE as you touch them, so you can work against a multi-gigabyte monorepo with seconds-to-first-edit instead of waiting for a full pull.
Edits go into a virtual branch backed by a local mount cache. The overlay (modified, deleted, and renamed paths) is the active commit โ the logical commit you're amending as you edit. oak commit finalizes that active commit onto the virtual branch; oak push sends it upstream.
Inside a mounted directory, top-level commands (oak status, oak commit, oak log, oak diff) automatically route to the mount-aware code path, so mounted and locally-cloned repos feel identical at the command level.
Mount requires the CLI built with --features mount plus macFUSE installed (brew install macfuse).
Git import and export
oak clone <gitrepo> is the import path from git into Oak. When the argument looks like a git remote URL, Oak shells out to git clone, initializes an Oak repository in the destination directory, then replays the cloned git history into Oak on main. By default the destination directory is derived from the git repo name; pass a destination path as the second argument to choose it yourself.
The CLI's oak export <dest> command is the local counterpart: replay your Oak history into a fresh git repo on disk. This is the documented escape hatch โ your data is never trapped in Oak's format.
oak clone <gitrepo> replays git history into Oak, while oak export replays Oak history back into git. Push code with oak push.
Data portability
The trust story is the export path above: any Oak repo can be replayed into a fully-functional git repo at any time with oak export.
If you want to leave, you can โ with full history intact.
Overview
The oak CLI is the primary way to drive Oak from your terminal โ create, commit, branch, pull, mount, and export repositories.
Pass --help to any command to see its flags. A global --verbose flag (before the subcommand) prints phase timings.
Installation
Install the latest release with one command:
curl -fsSL https://oakvcs.com/install | sh
The binary installs to ~/.local/bin/oak. To upgrade in place:
oak upgrade
Getting Started
Start a new local repository, commit, and push to the server:
# Create and enter a new repo
oak init my-game && cd my-game
# Add files, then snapshot the working directory
oak status
oak commit
# Log in and push โ the remote repo is created on first push
oak login
oak push
Or clone an existing repo from the server:
oak clone owner/repo
cd repo
Core VCS
oak init [PATH]
Initialize a new local repository, auto-creating a personal feature branch parented onto main.
PATH
directory to initialize (default: current directory)
oak status
Show the status of the working directory โ modified, added, and deleted files.
oak diff
Show changes between the working directory and HEAD.
oak commit [--no-verify]
Create a new commit on the current branch, snapshotting the entire working directory. Commits carry no message โ the branch description (set with oak desc) becomes the squash-merge commit message when the branch lands on main.
--no-verify
skip pre-commit and post-commit hooks
oak log [-n LIMIT] [--verbose]
Show commit history.
-n, --limit LIMIT
maximum number of commits to display
--verbose
include changed files in each entry
oak hash
Print the current HEAD commit hash.
oak switch [NAME] [-c] [-d]
Switch to a branch, create one, or detach HEAD at a commit. With no NAME, prompts you to pick a branch interactively.
NAME
branch name or commit hash (omit for interactive picker)
-c, --create
create a new branch with this name and switch to it
-d, --detach
treat NAME as a commit hash and detach HEAD there
oak checkout REFERENCE
Detach HEAD at a specific commit, given by full hash or a unique prefix (โฅ 4 hex chars).
oak desc DESC
Set the current branch's description โ the source of truth for what the branch introduces, and the message used when it squash-merges to main.
oak close [NAME]
Close a branch (defaults to the current branch).
oak restore [PATHS...] [-s COMMIT] [-f]
Restore files to their HEAD state, or to a source commit. Restores everything when no path is given.
-s, --source COMMIT
restore from this commit instead of HEAD
-f, --force
skip confirmation prompt
oak reset [PATH] [-f]
Reset the working directory (or a specific path) to HEAD, discarding uncommitted changes.
-f, --force
skip confirmation prompt
oak merge [--continue | --abort]
Merge the current branch into its parent. Use --continue to resume after resolving conflicts, or --abort to cancel.
oak tree
Show a visual tree of branches based on their parent links.
Remote operations
oak login [-r URL]
Log in to an Oak server. Credentials are stored in the OS keychain.
-r, --remote URL
server URL (default: https://oakvcs.com)
oak clone [OWNER/NAME] [DEST]
Clone a repository from the server (alias: get). With no argument, opens an interactive picker. A git remote URL is accepted instead and imported into Oak.
OWNER/NAME
repo spec; a bare name resolves to your personal org. Omit to pick interactively
DEST
destination directory (default: the repo name, git-style)
-r, --remote URL
server URL
oak push [-r URL] [-f]
Push commits on the current branch to the remote. The remote repository is created automatically on the first push.
-r, --remote URL
server URL
-f, --force
overwrite remote history even when diverged
oak pull [-r URL] [-f] [--continue | --abort]
Bring the local clone up to date: fetch new commits on the current branch, then merge in changes from the parent branch. --continue / --abort drive parent-merge conflict resolution.
-r, --remote URL
server URL
-f, --force
discard local commits not on remote and sync with remote HEAD
oak fetch [-r URL]
Refresh the local copy of main from the remote without touching the working tree or running a merge.
-r, --remote URL
server URL
Mount
oak mount SPEC [BRANCH]
Shorthand: set up an agent space at ./
SPEC
repository spec in owner/repo form
BRANCH
branch to mount (default: repo head, preferring main then master)
-r, --remote URL
server URL
oak mount start SPEC DEST [-b BRANCH]
Mount a repository at an explicit destination path. Runs in the foreground until interrupted.
-b, --branch BRANCH
branch to mount (default: repo head)
oak mount list
List active mounts.
oak mount status [DEST] [--quiet]
Show status for one mount, or summarize all mounts under the current directory when DEST is omitted.
--quiet
print nothing when every mount under cwd is clean (useful from hooks)
oak mount push DEST
Push the virtual branch (and its dependencies) to the remote.
oak mount forget DEST
Forget a mount's local state (only safe when nothing is mounted there).
oak mount end DEST [-f]
Unmount, forget local state, and remove the mount directory in one step.
-f, --force
discard uncommitted overlay changes instead of refusing
Tools
oak archive [-o PATH]
Create a zip archive of the current directory.
-o, --output PATH
output file path (default: oak export DEST [-b BRANCH] [--git-branch NAME] [-f]
Replay this Oak repository's history into a fresh git repo at DEST โ the documented escape hatch. Preserves original author and timestamp.
-b, --branch BRANCH
Oak branch to export (default: current branch)
--git-branch NAME
name for the resulting git branch (default: same as the Oak branch)
-f, --force
write into DEST even if it already contains files
oak open
Open the current repository in the web browser.
oak query
Open a SQLite shell to the local repository database (read-write). Arbitrary writes can corrupt the repository.
oak upgrade [-f] [-r URL]
Upgrade the Oak CLI to the latest release.
-f, --force
skip confirmation
-r, --remote URL
server URL
This page is for people who want to know how Oak actually works under the hood โ object model, chunking algorithm, and how it compares to the VCSes that influenced it. Oak is written in Rust; the CLI ships as a single static binary.
Manifests and commits, like Mercurial
Oak's object model is closer to Mercurial's design than Git's. There are no tree objects โ each commit points at a flat manifest that records the full directory snapshot as a list of (path, blob_hash, mode) tuples. No recursive tree traversal needed to reconstruct a working tree.
The commit chain is simple: each commit stores its parent commit hash, the manifest hash, an optional message, and a timestamp. Merges carry an additional merge_parent_hash that points at the pre-squash branch tip so the full history stays reachable even after squash-merge to main.
Everything is content-addressed via BLAKE3. A blob's identity is its hash; storing the same file twice costs one chunk write. Diffs are computed by diffing two manifests โ walk the path lists, compare hashes, done.
Branch descriptions (not commit messages) are the narrative layer. Local commits don't carry messages; only the squash commit that lands on main gets one, derived from the branch description. This keeps the history clean without requiring rebase discipline.
FastCDC for content-defined chunking
Large files are split into variable-length chunks using FastCDC, a content-defined chunking algorithm. Cut points are determined by the content of the file itself โ not fixed offsets โ so inserting a line near the top of a 100 MB file only invalidates a handful of chunks around the insertion point, not everything after it.
Git stores each version of a large file as a separate blob and relies on pack-file delta compression after the fact. Oak's chunking happens at write time, so deduplication is immediate and works across files that share content โ two binary assets with a common header share those chunks in storage.
Oak's defaults produce chunks roughly in the 256 KB โ 4 MB range (FastCDC's normalization keeps the distribution tight around the target). Each chunk is hashed independently with BLAKE3, and the manifest records the ordered chunk list per blob. Push and pull transfer only the chunks the remote is missing.
How Oak differs from Fossil
Fossil SCM is the closest prior art to Oak in philosophy: both use a single local database file instead of a loose-object store, and both treat the repository as a first-class artifact you can back up with cp. Oak local repos use the same SQLite-backed approach.
Where they diverge:
- Large-file handling. Fossil stores file content inline in SQLite, which caps out on large binaries. Oak uses content-defined chunking (FastCDC) and spills large chunks to external storage keyed by BLAKE3 hash โ large binary assets are a first-class citizen, not a workaround.
- Object model. Fossil's artifact format is a custom text encoding. Oak uses flat manifests (path โ blob hash), closer to Mercurial's design. Simpler to reason about; no need to parse a specialized artifact grammar to understand repo state.
- Branching. Fossil uses a timeline model where branching is a tag on a commit. Oak has explicit named branches with a parent-branch relationship โ branches are first-class, not timeline annotations.
- Scope. Fossil bundles a wiki, bug tracker, and forum into the repository. Oak is VCS-only โ use the tools you already have for issue tracking and documentation.
- Agent workflows. Oak is designed for branch-per-agent patterns:
oak clone, commit on a personal branch,oak push, open a PR. Fossil's model predates this use case.
Fossil's biggest win is its self-contained philosophy โ Oak borrows that. The rest is a different set of trade-offs aimed at a different problem.
Built with HTMX, running in Oregon
The web UI is server-rendered HTML powered by HTMX. Most interactions are partial-page swaps: a button click sends a request, the server returns a fragment, HTMX swaps it into the DOM. No client-side framework, no build step, no JavaScript bundle.
If you read this far you are a certified VCS nerd. Send me an email at [email protected] or reach out on Discord if you're interested in working on Oak!