The backend is a pure JSON API with no web interface — GET / is a 404. Check
its state with curl or agit doctor.
Several paths, the same binary either way:
| Who | How | Notes |
|---|---|---|
| Users (one-shot) | npx -y create-agit |
one-shot install to ~/.local/bin/agit, then setup |
| Users (global) | npm install -g @einsia/agent-git |
prebuilt binary, no Rust toolchain needed |
| People changing the code | ./setup.sh |
builds from source, installs to ~/.local/bin/agit |
pnpm (since v10) does not run a dependency's install
scripts by default, so the automatic agit setup is skipped — run it once by
hand after installing. What the npm package itself does is in
../npm/README.md.
Do not install @einsia/agentgit (no hyphen) — that is a different CLI from
before the rewrite, and its protocol does not match this branch.
Prebuilt distribution binaries include Git and Git LFS. The CLI extracts its private
runtime under $AGIT_HOME/git-runtime (by default ~/.agit/git-runtime) on first
use, without downloading additional files. Your shell PATH and global Git profile
are unchanged. User and repository Git configuration still apply; AgentGit's own
repository settings continue to control its internal commits and LFS filters.
Source builds use system Git by default and require Git >= 2.28; lineage
inspection needs Git >= 2.36 and LFS operations need Git LFS >= 3.7.1.
AGIT_USE_SYSTEM_GIT=1 also selects system Git in a distribution build, including
when a custom credential helper or extension requires your local Git installation.
Run agit doctor to see the selected Git and LFS versions. See
the bundled runtime guide for packaging and cache details.
On Linux the npm path downloads *-unknown-linux-musl, not gnu. The reason is a
real incident: a gnu artifact turns the build machine's glibc version into a
runtime floor, and the user gets libc.so.6: version 'GLIBC_2.38' not found
straight after installing. GitHub's ubuntu-latest is now 24.04 (glibc 2.39), and
the gnu artifact built there starts on none of Debian 12, Ubuntu 22.04,
Debian 11, Amazon Linux 2.
The musl artifact is static-pie with no glibc floor: every environment above
plus Alpine runs it. Before building the Release, the release pipeline puts
every Linux artifact into an alpine / amazonlinux / debian / ubuntu container
matrix and actually runs it there (the smoke-test step of release.yml).
The embedded Linux Git runtime carries its own musl loader and shared libraries.
It invokes that loader explicitly and uses the host's /bin/sh, so Git does not
introduce a host glibc requirement into the static CLI distribution.
setup.sh checks the toolchain before building; when something is missing it
tells you which command to type instead of an error from deep inside cargo. For
manual control, read on.
Needs cargo >= 1.88 and a C compiler.
The two floors come from different places and are not the same number: edition
2024 itself only needs 1.85, but in the committed Cargo.lock, darling 0.23
and instability 0.3.12 (a ratatui dependency) declare rust-version = 1.88,
so the real floor is 1.88. (1.78 is wrong — edition 2024 does not compile on it
at all.) The C compiler is what rusqlite's bundled feature needs: it
compiles sqlite's C source into the binary, so the target machine does not need
sqlite installed.
rustup installs into ~/.cargo/bin; when that is not on PATH, source ~/.cargo/env first.
(pushd AgentGit-backend && cargo build --release && popd) # agentgit-backend + agentgit-admin
(pushd agent-git && cargo build --release && popd) # agitRun the tests: cargo test (69 in the backend), cargo test --lib (166 in the
CLI). Without --lib the CLI suite times out on this NFS machine.
Zero configuration:
./AgentGit-backend/target/release/agentgit-backend
# INFO AgentGit backend started addr=127.0.0.1:8177 root=~/.agentgit-backendThe sqlite database and the bare git repos both live in ~/.agentgit-backend
(0700), and the tables are created at startup. AGIT_BACKEND_ROOT /
AGIT_BACKEND_PORT change the location and the port.
curl -s http://127.0.0.1:8177/api/health
# {"status":"ok","version":"0.1.0"}Binding a non-loopback address is refused unless --insecure is passed
explicitly — this backend holds every session transcript the team has, and
without TLS both tokens and transcripts cross the network in the clear. In
production, put a reverse proxy in front to terminate TLS.
Self-service registration is open by default: /signup in the web interface
creates an account, or call the API directly:
curl -s -X POST http://127.0.0.1:8177/api/auth/register \
-H 'content-type: application/json' \
-d '{"username":"alice","password":"your-long-password"}'
# returns a token pair; registering signs you inOn an instance with self-service registration off
(AGIT_BACKEND_OPEN_REGISTRATION=false), an administrator creates the accounts.
The password is read from the terminal, never from argv:
./AgentGit-backend/target/release/agentgit-admin user-add alice
# set a password:
# repeat it:
# created account alice
./AgentGit-backend/target/release/agentgit-admin user-listThe only password rule is length ≥10.
With no tty (docker exec -i, a pipe) it prints stty: Inappropriate ioctl for device. That is noise; the account is still created correctly. In a script,
pipe the password in twice:
printf 'your-long-password\nyour-long-password\n' \
| ./target/release/agentgit-admin user-add alice 2>/dev/nullThe CLI connects to the public hub https://agent-git.com by default, so agit login works as soon as it is installed.
This document covers a self-hosted instance, so point every example below at the one you started yourself first:
export AGIT_HUB_URL=http://127.0.0.1:8177For an acceptance binary that defaults to staging without depending on a runtime environment variable:
AGIT_DEFAULT_HUB_URL=https://staging.agent-git.com cargo build --release --lockedCredentials are stored per address, so the public hub and a self-hosted instance each stay signed in; switching the environment variable switches identity.
agit login # authorize through the browser or choose device code
agit doctor --check-backend
# [✓] sign-in alice @ http://127.0.0.1:8177
# [✓] backend ok @ http://127.0.0.1:8177 (version 0.1.0)
agit logout # revokes the server session + deletes local credentials, not the storeSigning in returns a token pair, stored under $AGIT_HOME/credentials/ (default
~/.agit/credentials/). The CLI chooses the filename and binds its contents to
the selected Hub authority. Unix files are private to their owner; Windows
files use the current user's private access control list. The credential scope,
refresh behavior, and compatibility rules are in
commands/auth.md.
CI uses a PAT supplied through stdin. Save the PAT as a secret file in the CI runner, then let the CLI validate and store the session:
export AGIT_HOME=/tmp/agit-ci AGIT_HUB_URL=http://127.0.0.1:8177
agit login --with-token < token.txt
agit whoami --checkDo not construct credential filenames or hand-write token JSON. Records without a valid Hub address cannot establish which destination may receive their tokens.
| Symptom | Cause |
|---|---|
cannot connect to the backend ... |
the backend is not running, or AGIT_HUB_URL has the wrong port |
the backend refused authentication (401) |
the refresh token expired too (thirty days); log in again |
wrong account or password |
wrong password, or no such account — the wording deliberately does not distinguish, to block account enumeration |
GET / returns 404 |
expected; there is no web interface |
stty: Inappropriate ioctl |
noise; the account is still created |
agentgit-admin doctor # account / agent / session counts + repo disk use
agentgit-admin audit -n 20 # audit recordsAn unauthenticated /api/agents returns 200 and an empty list rather than 401:
an anonymous caller can see public agents. A private agent the caller cannot
reach returns 404 rather than 403; otherwise agent names could be enumerated.