midsummer-sol
v0.3.59
Published
Sol — agent-native version control (a new git). CLI, MCP server, and no-filesystem SDK.
Maintainers
Readme
Sol
Sol is an agent-native version control system — a new git. It keeps the
shape you already know (commit, branch, switch, merge, diff,
clone/push/pull) and adds what git structurally can't: every edit is
captured automatically, history is content-addressed and tamper-evident, and an
agent can author straight into version control with no working files at all.
The name:
solis the sun. Three letters, likegit.
Install
The sol, sol-mcp, and sol-secret-mcp commands require Bun >= 1.3.11.
Install or upgrade Bun first (see https://bun.sh/docs/installation), then verify
the runtime before installing Sol:
bun --version # must be 1.3.11 or newernpm i -g midsummer-sol # exposes the `sol` commandThe npm installer checks that compatible Bun is available; the installed CLI and MCP commands execute with Bun, not Node. The package's programmatic SDK export is separate: it is built for Node and supports Node >= 20.19.5.
Check it:
sol --versionAuthenticate
Sign in once and Sol caches a token outside any repo so every machine command just works:
sol auth login # opens a one-click link to finish sign-in in your browser
sol auth status # who you're signed in as
sol auth logoutPrefer a token in your environment (CI, scripts)? Set SOL_TOKEN and Sol uses
it directly — it always wins over the cached login:
export SOL_TOKEN=<your-token>Everyday commands
sol init # create ./.sol in the current directory
# ...edit files...
sol commit "first cut" # snapshot the working tree + record a commit
sol status # current branch + uncommitted changes
sol log # commit history (sol log --all for every op)
sol diff # working-tree changes (sol diff main feature between refs)
sol watch # OR: auto-capture every change, hands-freeBranch and merge:
sol branch feature
sol switch feature
sol commit "work on feature"
sol switch main
sol merge feature # 3-way merge; conflicts land in your working tree to resolve
sol tag v1Recover and inspect:
sol restore --from 3 app.py # a file (or the whole tree) from any ref
sol show 5 # a commit's message + its diff
sol blame src/app.ts # who/which commit last touched each lineA ref is a branch/tag name, a commit hash-prefix, an op sequence number, or
HEAD. Set SOL_ACTOR=you to attribute your changes.
Remotes
Sol is hosted. After sol auth login, clone and push to the hosted Sol with no
extra setup — the default remote is https://sol.midsummer.new:
sol clone <owner>/<repo> # clone into ./<repo>
# ...work, commit...
sol push # publish your commits — never rejected for being behind
sol pull # sync from the remote — 3-way converges on divergence,
# same conflict markers as `sol merge` if it can'tsol push and sol pull both converge rather than requiring you to be
ahead first — neither is fast-forward-only. The 3-way merge computation
itself always happens the same way (the same converge() sol merge uses);
what differs is only where that computation runs: for pull it runs
locally; for push the server runs it (so a concurrent pusher's changes
still land even if you were behind) and returns the result over the wire.
Either way, the result reaches your local working tree the same way —
if it's a clean merge your branch just advances; if there's a real conflict,
you get the same <<<<<<< markers to resolve as sol merge leaves, whether
that conflict surfaced via push or pull.
Point at a different host when you need to (a self-hosted or staging Sol). Either
set SOL_REMOTE, or configure a remote per repo:
export SOL_REMOTE=https://sol.example.com # override the default for all commands
# or, per repo:
sol remote https://sol.example.com my-repo
sol pushRunning code: sol run
Everything above is about the version-controlled tree — writing code never needs a sandbox, since it lands straight in Sol. A sandbox is only needed when code has to actually execute (tests, a build):
sol run -- npm test # hydrate the current tree into a disposable temp dir,
# run the command there, capture what it produced back as a commit
sol run --isolate -- <cmd> # same, with no network + writes confined to the sandbox
sol run --keep <path> -- <cmd> # also keep <path> even if the run would otherwise ignore itsol run hydrates the current tree into a fresh temp directory, runs the
command there (stdio inherited, so you see output live), and — only on a
zero exit code — captures whatever files it wrote/deleted back as a real
commit (run: <command>) and syncs your working tree to match. A failing
run captures nothing: "a failed run must not pollute history" — you get the
command's exit code surfaced instead, no commit, no history change. This is
independent of sol watch: sol run's temp directory is never the directory
sol watch monitors, so the two mechanisms never overlap or double-capture —
watch only ever sees edits made directly in your real working tree.
The operations-layer Sandbox primitive (not yet a CLI verb)
Separately from sol run above, packages/sol/src/bin/orchestrator.ts
defines a lower-level Sandbox { hydrate, exec, snapshot, fork, destroy }
interface with two adapters: LocalSandbox (a disposable scratch dir) and
CloudSandbox (a real, separate Cloudflare Container instance per box,
addressed over HTTP). This is not what sol run uses — today it backs
only the content-addressed operations cache (op-run-cloud.ts/
op-run-local.ts, the "N agents, one cached result" layer) and is exercised
via direct script/programmatic use, not a first-class sol command yet.
Sandbox.fork(): Promise<Sandbox> (added 2026-07-06) is a copy-on-write
branch of a sandbox's current state under a new, independent identity —
LocalSandbox forks via a cheap filesystem copy; CloudSandbox forks via the
underlying Cloudflare Container's own backup/restore primitive, so the two
resulting boxes are genuinely separate Container instances, live-verified
under concurrent load. Neither observes the other's writes after the fork
point. This is filesystem-level only — a fork replays its start command
against the restored disk, it does not resume a live process
mid-instruction.
Naming note: this
fork()is unrelated to a repo fork (sol fork <parent> <new-repo>— "your own copy of a repo to propose from," carrying all branches/history; seedocs/sol-vocabulary.mdfor the full lexicon). Same word, two different concepts at two different layers — flagged as a naming collision worth resolving, not silently glossed over.
Beyond the everyday lifecycle
This README covers the git-shaped core. Sol has several other substantial,
tested command families, each with its own sol help <verb> page:
- Privacy/sealing —
sol seal,hide,sealed,open,keys: a host-blind hiding ladder from "encrypt this file's content" up to "hide that a path exists at all." SeeHIDING.md. - Secrets manager —
sol secret,env: declare/set/reveal/inject environment secrets with per-audience access control, independent of file content sealing. - Multi-agent workspaces —
sol agent,view/views: clone-free working trees that share one object store on disk, so multiple agents (or a human and an agent) can work the same repo in parallel without N full clones —sol view teammate-bcreates the managed working directory at.sol/views/teammate-bover the same repo, no re-clone. An explicit path such assol view teammate-b ../teammate-b-workdirremains supported. - Merge requests —
sol mr open/list/show/review/comment/check/merge: a real reviewable proposal object (commits + diff + checks), not a raw diff. - Integrity & recovery —
sol doctor,fsck,recover,gc: op-log chain verification, deep reachability checks, and history recovery tools.
For the on-disk/on-wire format these all sit on top of, see
FORMAT.md.
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.
