Skip to content

Repository files navigation

agit

License: MIT Built with Rust

Lossless version control for every agent session: publishable, resumable. Works with Claude Code, Codex, OpenCode, and Cursor.

On disk, sessions are just JSONL files that get overwritten, compacted, and cleaned up at any moment. agit puts snapshots and versions on top of them, so "that conversation last Wednesday that finally cracked the bug" becomes something you can find, continue, and hand to a teammate.

agit                              choose a session to continue
agit new                          choose a repo and name a fresh conversation
agit import                       choose an existing runtime conversation to adopt
agit log                          choose a session and browse its history
agit push                         choose a saved session to publish
agit share                        choose a session and review link settings
agit run owner/repo@ref           open a saved source, forking when needed

These bare commands open their interfaces in a human terminal. agit resume continues the same session and never forks; agit run can start a new writable session from a tag, historical point or another author's source.

Inside an adopted agent session, agit commit saves completed turns and agit push publishes that session. For scripts, pass the target explicitly, for example agit push owner/repo@branch --json. Directory branch pins do not choose targets for commit, push or share.

On user-facing startup, agit checks for a newer release at most once a day and prints a reminder to stderr; it never upgrades automatically. JSON/quiet/CI and internal hook/MCP paths skip this reminder.

Adopting and recording the first version are one command — the in-between state ("linked, but unversioned") means nothing to anyone. To mark a session without versioning it (e.g. offline), pass --link-only.

Use a full native session ID and an explicit runtime and destination for lineage discovery. The terminal offers verified local bases, independent import, or cancellation. Noninteractive calls return choices without writing; pass --onto <ref> or --independent to select a path. --propose-lineage prints a read-only report without adopting the session. Inspecting lineage in an existing repository requires NUL-framed Git worktree output, normally available in Git 2.36 or newer. An unsupported Git reports git_worktree_format; explicit --onto, --independent, and --link-only imports retain their ordinary checks.

agit clone fetches repository history locally. Use agit run or agit resume to start a runtime. A clone is read-only by default on the Hub: nothing is created in your name and origin points at the source. agit clone --mine creates your copy, repoints origin and remembers the source as upstream.

The full command list is in agit --help.

Install

Users: npm

npx -y create-agit                 # one-shot: installs agit + wires skills/hooks/MCP
# or as a global package:
npm install -g @einsia/agent-git   # pnpm add -g @einsia/agent-git works too
agit --version

Both routes install a prebuilt binary — no Rust toolchain required. npm picks the platform sub-package matching your os/cpu; on platforms with no prebuilt binary (e.g. FreeBSD) running agit prints the source-build recipe. Details and environment variables: npm/README.md.

Windows x64 packages include the native peer RC daemon. On Windows, Linux and macOS, run agit login followed by agit rc start --detach to register the device and allow your own account to control it from Workspaces. Windows owner RPC uses a local named pipe restricted to the current user. RC state requires a private, user-owned directory.

pnpm (v10+) does not run dependency install scripts by default, so the automatic agit setup is skipped there — run agit setup once yourself after installing.

The Linux artifact is musl static-linked, so no minimum glibc — the release pipeline runs every Linux binary inside an Alpine / Amazon Linux / Debian / Ubuntu container matrix before publishing.

Prebuilt binaries include Git and Git LFS, extracted into a private cache on first use. Your shell PATH and global Git configuration stay unchanged. Source builds use system Git; AGIT_USE_SYSTEM_GIT=1 selects it in a prebuilt binary too. See runtime configuration and source prerequisites.

Do not install @einsia/agentgit (no hyphen) — that is the pre-rewrite CLI; its protocol does not match this branch and it will not work.

Contributors / eager users: from source

git clone https://github.com/Einsia/agent-git
cd agent-git
./setup.sh

setup.sh checks the toolchain (rustc, a C compiler), builds, and installs the binary to ~/.local/bin/agit. Common flags:

./setup.sh --debug      # no LTO, much faster while hacking
./setup.sh --test       # run cargo test --lib before installing
./setup.sh --help

To build a binary whose built-in hub is the staging deployment, set the build-time default explicitly. Runtime AGIT_HUB_URL and agit config hub.url ... still take precedence:

AGIT_DEFAULT_HUB_URL=https://staging.agent-git.com cargo build --release --locked

Internal GitLab pipelines package commit-addressed dev and staging builds with this setting embedded. Their agit --version output includes the channel and source commit, and agit upgrade is disabled for them so an acceptance-test binary cannot silently turn into the public release. Only an existing GitHub agit-v* tag produces the prod channel. The tag push runs the Release workflow automatically; operators may also select the same reviewed tag through the workflow's manual production input to retry a failed release without creating a different artifact identity.

Requires rustc >= 1.88 and a C compiler (rusqlite uses the bundled feature, so sqlite's C sources are compiled during the build). The reason for the toolchain floor is in docs/01_setup.md.

Both paths install the same binary. npm is for "users who don't want to touch Rust"; setup.sh is for "people changing the code" and "people running unreleased versions".

Docs

Goal Where
Build, run the backend, sign in, debug docs/01_setup.md
How sessions are stored locally docs/02_session_store.md
The terminal interface for humans docs/07_tui.md
Login / token mechanics docs/commands/auth.md
Local low-entropy secret filtering docs/05_global_secret_filter.md
Reversible repository secret placeholders docs/06_repository_secret_dictionary.md
Probed storage formats of each runtime docs/mechanism-probing/
npm package behavior and env vars npm/README.md
Release artifact naming contract .github/RELEASE_ARTIFACTS.md
What changed in each release CHANGELOG.md

The server (AgentGit) is a separate repository, deployed on its own.

Release

Cargo.toml is the single source of the version; every npm manifest must agree with it (node scripts/check-version.js — run in CI and before npm pack). To move the version, change every spot in one shot:

node scripts/bump-version.mjs 0.1.0    # Cargo.toml + Cargo.lock + all npm manifests

Release notes live in CHANGELOG.md, and they come first: write the version's ## [x.y.z] section, then bump. bump-version.mjs refuses to touch a file for a version that has no section, and check-version.js refuses one in CI and before npm pack. The section becomes the GitHub Release body (scripts/release-notes.mjs extracts it in release.yml, with repository-relative links pinned to the release tag) and ships inside the @einsia/agent-git package.

After the source release commit passes CI and is synchronized to GitHub main, verify the mirrored files and create the tag in that GitHub checkout. The mirror rewrites commit IDs, so the source repository's SHA is not the release SHA. Pushing the tag to GitHub runs the whole chain — binaries first, npm right after:

# Run from the verified Einsia/agent-git GitHub mirror checkout.
git tag agit-v0.1.0
git push git@github.com:Einsia/agent-git.git refs/tags/agit-v0.1.0

Distribution to users runs through the npm registry: each target ships as a platform sub-package (@einsia/agent-git-linux-x64 and friends, gated by os/cpu — npm installs only the matching one), and the main @einsia/agent-git pulls them in via optionalDependencies. The GitHub Release holds the canonical tarballs plus SHA256SUMS (contract).

Publishing to npm is the npm publish workflow. It runs automatically once the Release workflow finishes green (and can be dispatched manually — Actions → npm publish — for retries, next dist-tag trials, or a dry_run). It publishes the whole family in dependency order — platform packages → @einsia/agent-gitcreate-agit — with a real global install of the main tarball as a preflight in between, authenticating via npm trusted publishing (OIDC, no stored token). The equivalent local fallback:

gh release download agit-v0.1.0 -p 'agit-*.tar.gz' -D /tmp/agit-dist
node npm/publish.mjs /tmp/agit-dist        # platform packages → main → create-agit

npm/create-agit/ is the one-shot installer behind npx -y create-agit — it depends on the main package and turns the npx cache copy into a durable ~/.local/bin/agit, then wires skills/hooks/MCP via agit setup. There is deliberately no unscoped alias package: agit on npm belongs to an unrelated project, and npm's typosquat rule blocks agent-git for being one punctuation mark away from a third party's agentgit.

The version oracle (GET /api/cli/version on the hub) and agit upgrade both read the npm registry; integrity verification uses the registry's SRI (sha512). Self-hosted hubs that pin an internal fork set AGIT_BACKEND_CLI_REPO and the whole chain reverts to the GitHub path.

@einsia/agent-git is a fresh package name with no existing users, so the first release goes straight to latest — no need to hide in next first. (The old @einsia/agentgit stays put; it points at the pre-rewrite CLI.)

About

Code is cheap, show me the talk: version control for agent sessions

Resources

Stars

121 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages