{"id":51340368,"url":"https://github.com/standardapplied/sail","last_synced_at":"2026-07-13T17:00:55.444Z","repository":{"id":346468858,"uuid":"1152460349","full_name":"standardapplied/sail","owner":"standardapplied","description":"Isolated development environments for AI agents","archived":false,"fork":false,"pushed_at":"2026-07-02T04:16:15.000Z","size":3251,"stargazers_count":11,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-02T04:22:09.605Z","etag":null,"topics":["agent-orchestration","ai-agents","coding-agent","harness"],"latest_commit_sha":null,"homepage":"https://standardapplied.com/products/open-source/#sail","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/standardapplied.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY_AUDIT.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-07T22:49:44.000Z","updated_at":"2026-07-02T04:01:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"af87f1e6-e723-48d8-bf2a-9557a7a11107","html_url":"https://github.com/standardapplied/sail","commit_stats":null,"previous_names":["singlr-ai/sing","standardapplied/sail"],"tags_count":146,"template":false,"template_full_name":null,"purl":"pkg:github/standardapplied/sail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardapplied%2Fsail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardapplied%2Fsail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardapplied%2Fsail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardapplied%2Fsail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/standardapplied","download_url":"https://codeload.github.com/standardapplied/sail/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/standardapplied%2Fsail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35036553,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-orchestration","ai-agents","coding-agent","harness"],"created_at":"2026-07-02T07:00:40.135Z","updated_at":"2026-07-13T17:00:55.438Z","avatar_url":"https://github.com/standardapplied.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sail\n\nSail turns bare-metal servers into isolated, spec-driven dev environments where AI coding\nagents do the work. Each project gets a hard-isolated container. The team's specs and\nproject definitions live in a synced database. Agents are dispatched against those specs\nwith rollback safety and cross-agent review.\n\nSail is not a coding agent. It is the layer around them: the environments they run in, the\nspecs they pick up, the reviews they pass, and the shared state a team works from. It does\nfor coding agents roughly what Kubernetes does for containers, orchestrating the work\nrather than performing it.\n\nBuilt with Java 25, picocli, and GraalVM native-image. One binary, no runtime\ndependencies, sub-millisecond startup.\n\n## Install\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/standardapplied/sail/main/install.sh | bash\n```\n\n`sail upgrade` replaces the binary in place and converges the database. Linux (amd64) runs\na full host. macOS (arm64) runs as a thin client that drives a remote host over SSH.\n\n## The model: one main, many nodes\n\nAn org runs one main box. It holds the team's specs and project definitions in a SQLite\ncontrol plane and is the source of truth. Every engineer also has their own box. A box\npointed at main is a node: it pulls specs, project definitions, and shared files from main,\nand pushes its own work back.\n\nThere is no GitHub in this loop and no separate board. The database is the board, and\n`sail sync` moves it over a locked-down SSH gateway using public-key auth, with three-way\nconflict resolution so no one's work is overwritten. Compute is never scheduled across\nboxes. The star coordinates state, not execution.\n\n## Quick start\n\nStand up the main. One idempotent command provisions the box, installs the control plane,\nand declares it the source of truth:\n\n```bash\nsudo sail init --as-main\n```\n\nAuthorize each engineer with the public key their `sail init --main` printed:\n\n```bash\nsail fde add mady --role member --key \"ssh-ed25519 AAAA... sail-sync@madybox\"\n```\n\nJoin a node:\n\n```bash\nsudo sail init --main \u003cmain-ip\u003e   # provision, install sail-api, generate this box's sync\n                                  # key, and print the fde add line to run on main\nsail sync                         # pull specs, projects, and shared files from main\n```\n\nOn a Mac or other thin client, run `sail client \u003chost\u003e` to point your local CLI at a box.\nIt forwards commands over SSH, and no control plane runs locally.\n\n## Projects\n\nA project is one `sail.yaml`: runtimes, services, repos, and agent config. The database is\nthe source of truth, and the on-disk descriptor is a materialized view. `sail project\ncreate` turns the definition into an isolated Incus container with runtimes installed,\nPodman services running under `--restart=always`, repos cloned, and agent context\ngenerated.\n\n```bash\nsail project init        # author a sail.yaml\nsail project create web  # provision the container\nsail project edit web    # change the definition (saved to the catalog, synced to peers)\nsail project connect web # print SSH config for your editor\n```\n\nThe synced definition is identity-free. Per-engineer fields are placeholders\n(`${GIT_NAME}`, `${GIT_EMAIL}`, `${SSH_PUBLIC_KEY}`) resolved from your own box at provision\ntime. A teammate's project commits as you and trusts only your key. No identity or keys\nride the sync onto another box. Resource limits sync both ways and resize the running\ncontainer in place.\n\n```yaml\n# sail.yaml (name, resources, and image are the only required fields)\nname: web\nresources: { cpu: 4, memory: 12GB, disk: 150GB }\nimage: ubuntu/24.04\nruntimes: { jdk: 25, node: 22 }\ngit: { name: ${GIT_NAME}, email: ${GIT_EMAIL} }     # per-developer, never synced\nrepos:\n  - { url: \"https://github.com/acme/web.git\", path: web }\nservices:\n  postgres: { image: postgres:16, ports: [5432] }\nagent:\n  type: claude-code\n  methodology: { approach: spec-driven, verify: \"mvn clean test\" }\n  guardrails:  { max_duration: 4h, action: snapshot-and-stop }\nssh:\n  authorized_keys: [ ${SSH_PUBLIC_KEY} ]            # per-developer, never synced\n```\n\nRun `sudo sail project demo` to spin up a bundled zero-config demo (an Outline wiki) end to\nend.\n\n## Specs and agents\n\nSpecs are the unit of work. They live in the database with a status, an assignee, and\ndependencies, filterable across the whole team. You manage them with `sail spec`. Agents\ninside a container use an in-container `spec` CLI over a bound socket, so there is one\nsource of truth and no sync glue.\n\n```bash\nsail spec create --project web --title \"Stripe webhook\" --assignee mady --depends-on oauth\nsail spec board --project web    # who is on what, and what is ready\nsail spec dispatch --project web # pick the next ready spec, launch the agent, watch it\n```\n\n`dispatch` honors dependencies and assignee, snapshots the container for rollback, creates\nthe work branch, and launches the agent with full generated context. Its log streams live.\nSail is agent-agnostic across claude-code and codex, so one agent can implement and another\ncan review: configure `agent.review_pipeline` in `sail.yaml` and when the coder stops, a\nreviewer checks the branch, a fix agent addresses its findings, and the loop repeats up to\n`max_iterations` before escalating to a human. `sail agent review \u003cproject\u003e` shows every\nattempt's iterations and findings; `sail agent log \u003cproject\u003e --review` follows the\nnegotiation live. Guardrails combine a `max_duration` and an action, so a runaway agent is\nstopped and rolled back to the pre-launch snapshot. A passing review parks the spec in\n`awaiting_merge` — sail never talks to the forge, so you merge the PR there and close the\nloop with `sail spec update \u003cid\u003e --status done`.\n\nFindings the gate let ship don't die in the review store: `sail spec create --from-review\n\u003cspec-id\u003e` drafts a follow-up spec from the latest review's open findings — one actionable\nsection per finding, priority derived from the highest severity, repos copied from the\noriginal. The draft stays in `draft` until you promote it, and when it reaches `done` the\nfindings it was created from are marked resolved. `sail spec show` and the board flag done\nspecs that still carry open findings (`· N open findings`), so completion-with-residue is\ndistinguishable from clean completion.\n\nSpecs and projects edited on two boxes merge automatically when the changes touch different\nfields. A true same-field clash parks for `sail conflicts` instead of overwriting either\nside.\n\n## Going deeper\n\n- [ARCHITECTURE.md](ARCHITECTURE.md) covers the full design: the sync engine, the security\n  model, the control plane, and the provisioning pipeline.\n- Every command has `--help`. State-mutating commands support `--dry-run`, and all support\n  `--json`.\n\n## Build from source\n\nRequires JDK 25 or newer and Maven 3.9 or newer.\n\n```bash\nmvn clean verify                  # build and run the full test suite with coverage gates\nJAVA_HOME=/path/to/graalvm-jdk-25 mvn clean package -Pnative -DskipTests   # native binary\n```\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstandardapplied%2Fsail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstandardapplied%2Fsail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstandardapplied%2Fsail/lists"}