# Sol

**Sol is a version control system where a checkout is a window, not a copy.**

Content is SHA-256 addressed. History is a tamper-evident hash-chained op-log.
A working directory is one view onto that store - sometimes materialized on
disk, sometimes served from the store through a mount, sometimes not needed at
all. Everything Sol does that git cannot follows from that.

> The name: `sol` is the sun. Three letters, like `git`.

## 60-second start

Requires **Bun >= 1.3.11** (<https://bun.sh/docs/installation>).

```sh
bun add -g midsummer-sol     # exposes `sol`
sol --version
sol auth login               # one-click browser sign-in; token cached outside any repo
```

Then:

```sh
sol init                     # or: sol clone <owner>/<repo>
# ...edit files...
sol status
sol commit "first cut"          # optional named checkpoint
sol push <owner>/<repo>      # first push configures the remote and creates the repo
```

There is no `sol add`. Automatic capture starts with the checkout and records every
save into the local op-log. `sol commit` names what is already recorded rather than
collecting it, and takes no file list. `sol push` is the explicit durability barrier:
it returns only after the remote confirms all captured operations.

Set `SOL_ACTOR=you` to attribute changes. Remote durability and convergence happen only through explicit
`sol push` and `sol pull` commands.

Bun is a CLI requirement only. Embedding Sol as a library uses the Node SDK
surface, which runs on **Node >= 20.19.5** with no Bun anywhere in the path.

## The three things git cannot do

### 1. Commit your `.env` safely

```sh
$ sol seal .env
sealed .env to @you — canonical op_92feef112483 (pending push)

$ sol read .env
DATABASE_URL=postgres://localhost/demo
```

To anyone outside the audience, the same read is `<<sealed — you are not a
recipient>>`. The content encryption key is wrapped per recipient to their
X25519 public key; the private key is *derived* from a recovery code and never
stored or sent. The host holds ciphertext and a list of account ids and cannot
decrypt - not by policy, but because it has nothing to decrypt with.

`sol hide "secrets/**" --role write` binds the audience to a **role** instead of
a name list, so it stays correct as the team changes. `sol provenance <path>`
proves, offline, whether a path's plaintext has ever left the machine.

See [docs/cli/seal.md](docs/cli/seal.md), [hide.md](docs/cli/hide.md),
[provenance.md](docs/cli/provenance.md).

### 2. Views in seconds, with zero duplicated files

```sh
$ sol view agent-a
created view 'agent-a'
  workspace /repo/.sol/mnt/agent-a (lazy)
  branch view/agent-a  @ op_9236292fd182  (you: zander)
  2 file(s) ready; sharing 6 object(s) with the parent
  integrate from the parent with `sol merge agent-a`
```

A view is a second working tree with its own branch and index, over **the same
object store**. A git worktree per agent means a full checkout per agent -
`node_modules` and every blob copied N times, and every agent contending on
`.git/index.lock`. Ten Sol views share one store, commit concurrently, and
converge losslessly with `sol merge <view>`. On a large repo the checkout is
served from the store and *nothing is written at all*.

See [docs/cli/view.md](docs/cli/view.md) and [views.md](docs/cli/views.md).

### 3. Agents author without a filesystem

```sh
sol mcp             # workspace tools: read/write/edit/commit/push/diff/seal/...
sol mcp --secret    # agent-safe env + secret tools: names and refs, never values
```

An agent can author into a Sol repo with no checkout to materialize, no working
directory to clean up, and no path traversal to sandbox. The secret server is a
cryptographic boundary rather than a permission flag: an agent holding no key
cannot read a value even if it calls the tool.

See [docs/cli/mcp.md](docs/cli/mcp.md), [secret.md](docs/cli/secret.md).

## Everyday commands

```sh
sol status                  # immediate sealed/last-observed as-of state
sol view NAME               # isolated working tree over the shared object store
sol view wait NAME          # wait until the View's shared toolchain is ready
sol view remove NAME        # retire a settled view (add --abandon to discard explicitly)
sol commit "milestone"      # optional name for already-captured work
sol pull                    # converge with the configured remote
sol push                    # remote-durability barrier for captured work
sol diff                    # bounded as-of working changes, never a full scan
sol log                     # named history         (sol log --all for every branch)
sol show                    # one operation's metadata and touched paths
sol blame src/app.ts        # per-line attribution
sol ls / sol read FILE      # tracked paths / one file's committed content
sol doctor                  # full local health check
```

Nearly every read command takes `--json`.

`sol watch status` is available for operator diagnosis of automatic capture;
it is not a required step in the everyday workflow.

`sol push` and `sol pull` both **converge**. Neither is fast-forward-only: the
three-way merge runs locally for `pull` and on the server for `push`, so a
concurrent pusher's changes land even when you were behind. A clean merge
advances atomically; a real conflict never silently chooses a side.

## Releases

CLI/SDK and backend releases are deliberately independent:

```sh
bun run release:cli -- --version <version> --branch <branch>       # add --publish to publish
bun --cwd ../../infra/sol-backend run release:backend              # guarded Worker promotion
```

The CLI release never deploys the Worker, and the backend release never publishes
the npm package. The distributed benchmark gate is available as
`bun run bench:distributed` and is already blocking inside the CLI publish gate.

## Documentation

- **[docs/guide.md](docs/guide.md)** - the walkthrough: solo loop, agents,
  teams, privacy, mounts, the machine store.
- **[docs/cli/](docs/cli/)** - one man page per command.
- **[docs/cli/unimplemented.md](docs/cli/unimplemented.md)** - canonical
  replacements for retired compatibility verbs.
- **[HIDING.md](HIDING.md)** - the visibility and sealing model in depth.
- **[FORMAT.md](FORMAT.md)** - the on-disk and on-wire format.

## Self-hosting

The default backend is `https://sol.midsummer.new`. Point elsewhere with
`SOL_REMOTE`, or per repo:

```sh
sol remote https://sol.example.com my-repo
```

`SOL_TOKEN` is used directly and always wins over the cached login - that is the
CI path.

## License

No license yet - deliberately deferred, not decided. The published package
carries no `license` field and no `LICENSE` file. Add both when that decision
actually gets made.
