# knotless Git that lives in your atproto account. It works on any stock PDS, with nothing to install. People push with plain git through a remote helper, and agents do the same over MCP. A knotless repository is a handful of records in your own atproto repo. There is no git server and no knot. The repository moves with your account and is in your CAR backups, and anyone can clone it from your PDS directly. Forks, pulls, issues and reviews are records too, each in its author's account. One optional server, `knotless-serve`, adds a read cache, an index of pulls and issues, a gateway for collaborators, and web pages. It is cheap to run. ```sh curl -fsSL https://knotless.dev/install.sh | sh # knotless, git-remote-knotless, knotless-mcp, and the runner, labeller and reviewer knotless login alice.bsky.social # OAuth, in your browser git push knotless://alice.bsky.social/my-project main git clone knotless://alice.bsky.social/my-project ``` [knotless.dev](https://knotless.dev) runs `knotless-serve`, and hosts knotless's own repository: [chadtmiller.com/knotless](https://knotless.dev/chadtmiller.com/knotless). ## What it does - `git push`, `fetch` and `clone` over `knotless://` URLs. `knotless-serve` also serves reads over git smart HTTP, partial and shallow clones included. - Commits, branches, reviews and merges from the CLI or MCP, with no clone. - Forks, pulls, reviews, issues, protected branches and a merge queue. Collaborators push through a gateway the owner chooses. - Private repositories in permissioned spaces, where the pulls, issues and comments are as private as the code. - An MCP server for agents: over stdio on your machine, or over HTTP from `knotless-serve`. - CI: `knotless-run` runs workflows in containers on pushes and pulls, and writes checks that gate merges. - Read-only web pages for code, history, diffs, pulls, issues and checks, with syntax highlighting and Mermaid diagrams, on a phone or a desktop. - atproto's moderation: hides, blocks, reports, and takedowns published as labels. ## How it works ```mermaid flowchart LR you[git, knotless CLI,
or an agent over MCP] -->|XRPC| pds[(Your PDS:
dev.knotless.* records
and pack blobs)] others[Collaborators] -->|service token| gw[Gateway] gw -->|writes as you| pds pds --> feed[Jetstream] feed --> serve[knotless-serve:
cache, index, web pages] feed --> run[knotless-run:
workflows] run -->|checks| ci[(Runner's PDS)] readers[Anyone] -->|clone, browse| serve readers -->|clone| pds ``` Four record types in the owner's account hold a repository: | Record | Key | Holds | | --- | --- | --- | | `dev.knotless.repo` | name | the repository's `key` (a TID), description, default branch, collaborators, gateway and branch rules | | `dev.knotless.ref` | `.` | one ref's target, and a generation counter | | `dev.knotless.claim` | `..` | the lock on one generation of a ref | | `dev.knotless.pack` | `.` | an immutable, self-contained git pack, inline when small and in blobs when not | A push creates the claim for the ref generation it read, in the same `applyWrites` as the ref update. The PDS accepts only the first create of a key, so each ref has its own compare-and-swap, and agents pushing to separate branches never contend. The keys share the repository's prefix, so one `listRecords` reads a repository's refs, or its newest packs. Once a repository holds more than 32 packs, they are folded into one, so a clone stays a few reads however long the history is. The [design pages](docs/design/README.md) cover the rest: the limits of a stock PDS, the failure cases, the trust model and the prior art. ## Performance A warm push is two round trips to the PDS, and a fetch of a small push is one. Against the reference PDS on the same machine, with 50 ms of round-trip time added: | | p50 | | --- | --- | | `git push`, one small commit | 223 ms | | `git fetch`, one new commit | 177 ms | | `knotless repo commit`, no checkout | 366 ms | | `git clone`, compacted | 158 ms | | 16 agents pushing 16 branches at once | 443 ms total | [Performance](docs/reference/performance.md) has every measurement and how it was taken. ## Documentation - [Getting started](docs/guide/getting-started.md): install, log in, push, commit without a checkout. - [Collaborating](docs/guide/collaborating.md): sharing, forks, pulls, reviews, merging, moderation. - [Private repositories](docs/guide/private.md). - [Agents](docs/guide/agents.md): connect Claude Code, Claude Desktop, Cursor or claude.ai. - [Running knotless-serve](docs/guide/server.md): the cache, appview, gateway and web pages. - [Workflows](docs/guide/workflows.md): CI with `knotless-run`. - [Command reference](docs/reference/cli.md): every command, flag and environment variable. The [docs index](docs/README.md) lists every page. ## Components - [`knotless`](crates/knotless): the CLI and `git-remote-knotless`. They talk to PDSes directly. - [`knotless-mcp`](crates/knotless-mcp): the MCP server. - [`knotless-serve`](crates/knotless-serve): the optional read cache, appview, gateway, moderation service and web pages, in one binary that fits a small VPS. - [`knotless-run`](crates/knotless-run): the workflow runner. - [`knotless-triage`](crates/knotless-triage): the triage bot, which labels issues with a classifier's choices. - [`web`](web): the SvelteKit pages that `knotless-serve` hands requests to. ## Development ```sh just setup # npm install in harness/ and web/, llvm-tools for coverage just test # every test, against the npm reference PDS just fmt # rustfmt and oxfmt just lint # rustfmt, oxfmt, clippy and svelte-check ``` Tests cover every line and function, and CI fails below that. [Development](docs/development.md) covers the test harness, screenshots and agent scenarios. [AGENTS.md](AGENTS.md) says how changes are made and landed. ## Status knotless runs [knotless.dev](https://knotless.dev), which hosts knotless's own development. Not done yet: verifying refs against signed repository commits ([Known gaps](docs/design/security.md#known-gaps)). ## License MIT or Apache-2.0, at your option: [LICENSE-MIT](LICENSE-MIT), [LICENSE-APACHE](LICENSE-APACHE).