https://github.com/singlr-ai/sing
Isolated development environments for AI agents
https://github.com/singlr-ai/sing
ai-agents coding-agent development-environment
Last synced: 13 days ago
JSON representation
Isolated development environments for AI agents
- Host: GitHub
- URL: https://github.com/singlr-ai/sing
- Owner: singlr-ai
- License: mit
- Created: 2026-02-07T22:49:44.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-06-13T00:58:40.000Z (15 days ago)
- Last Synced: 2026-06-13T02:24:37.944Z (15 days ago)
- Topics: ai-agents, coding-agent, development-environment
- Language: Java
- Homepage: https://sing.singlr.ai
- Size: 1.72 MB
- Stars: 8
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Security: SECURITY_AUDIT.md
Awesome Lists containing this project
README
# sail
A single native binary that provisions bare-metal servers and manages isolated dev environments for AI-assisted engineering. One binary, zero dependencies, fully declarative.
Built with Java 25 + picocli + GraalVM native-image. <1ms startup.
## Why
You have a bare-metal server. You work on multiple projects simultaneously, each needing its own JDK, Postgres, Meilisearch, Redpanda, and AI coding agents — fully isolated so a runaway agent in one project can't affect another.
`sail` provisions the server, creates project environments as Incus system containers, manages their lifecycle, and orchestrates AI agents inside them with spec-driven workflows, guardrails, and rollback safety. Each project gets a complete Ubuntu 24.04 userspace with its own filesystem, network stack, and rootless Podman runtime.
## Day 0: Server + Project Setup
```bash
# Install sail (single binary, no dependencies)
curl -fsSL https://raw.githubusercontent.com/singlr-ai/sing/main/install.sh | bash
# Initialize server (one-time, needs sudo)
sudo sail host init
```
`host init` installs Incus, creates a storage pool (dir by default, ZFS with `--storage zfs --disk /dev/sdX`), configures networking, and caches the base Ubuntu 24.04 image.
```bash
# Pull project descriptor from shared repo (team projects)
export GITHUB_TOKEN=ghp_...
sail project pull acme-health
# Or generate a new sail.yaml interactively
sail project init
# Create the environment
sail project create acme-health
```
`project pull` stores the project bundle under `~/.sail/projects//` by default.
`project create` provisions an Incus container with everything declared in `sail.yaml` — installs runtimes, starts Podman services, clones repos, configures git identity, generates agent context files, and sets up the harness.
```bash
# Print SSH config for your editor
sail project connect acme-health
```
Add the output to `~/.ssh/config`, then connect in Zed: `Cmd+Shift+P` → "Connect to SSH Host" → `acme-health`.
## Day 2: The Two Modes
Engineers work in two modes. `sail` supports both from the same project.
### Interactive Mode (Daytime)
Open Zed, connect via SSH remote dev, start the agent from Zed's Agent Panel. You're in the loop — brainstorming, exploring code, writing specs, reviewing output. `sail` is invisible here; the generated context files (CLAUDE.md, SECURITY.md, `.context/`) guide the agent.
```bash
sail project restart acme-health # start container, show connection info
```
Developer processes (`java -jar`, `npm run dev`) run interactively in Zed terminal tabs. Infrastructure services (Postgres, Meilisearch, etc.) are managed by Podman with `--restart=always` and survive container reboots automatically.
### Autonomous Mode (Overnight)
Write specs during the day. Walk away. The agent works through them overnight.
```bash
sail spec dispatch acme-health # pick next ready spec, launch agent
```
`dispatch` scans `specs/*/spec.yaml` from the container, finds the next pending spec (respecting dependencies and assignee), reads the detailed `spec.md`, and launches the agent with full context. Guardrails enforce time limits. Auto-snapshot provides rollback safety.
## Spec-Driven Workflow
Specs are the unit of work. Each spec lives in its own directory inside `specs/`, checked into a shared repo so the team can see and assign work.
### Structure
```
specs/
├── oauth-flow/
│ ├── spec.yaml # Metadata: id, title, status, assignee, depends_on
│ ├── spec.md # What to build and why (brainstormed with agent in Zed)
│ └── plan.md # How to build it (optional, for complex specs)
├── payment-integration/
│ ├── spec.yaml
│ ├── spec.md
│ └── plan.md
└── fix-footer-typo/
├── spec.yaml
└── spec.md # Simple spec, no plan needed
```
### spec.yaml
```yaml
id: payment-integration
title: "Stripe payment webhook"
status: pending
assignee: bob
depends_on:
- oauth-flow
repo: webapp
agent: codex
model: gpt-5.5
reasoning_effort: high
branch: feat/payment-integration
```
`repo`/`repos` routes work to the right repository in multi-repo projects. `agent` routes a spec
to a specific installed agent (`claude-code` or `codex`); if omitted, dispatch uses
`agent.type` from `sail.yaml`. `model` and `reasoning_effort` tune agents that support those
controls; unsupported combinations fail fast.
### Lifecycle
```
pending → in_progress → review → done → archive
```
**pending**: Ready for an agent to pick up. **in_progress**: Agent is working. **review**: Work complete, security review and code review hooks run automatically. **done**: All reviews pass. **archive**: Cleaned up (`sail task archive`).
### The Full Loop
```
Morning (Zed, interactive):
Engineer + agent brainstorm → write specs/oauth-flow/spec.md
Optionally plan → write specs/oauth-flow/plan.md
Push specs to shared repo
Evening:
sail spec dispatch acme-health
Overnight:
Agent reads spec.md, works, commits, pushes branch
Reviews run automatically at spec completion
Guardrails enforce time limits
Next morning:
sail agent status # all projects at a glance
sail agent report acme-health # detailed: commits, spec progress, review results
Review PRs, merge or address findings
```
### Team Coordination
Specs live in a shared private repo (e.g., `your-org/projects/acme-health/specs/`). Multiple engineers, each with their own container:
- Alice specs out OAuth, assigns to herself
- Bob specs out payments, depends on Alice's OAuth work
- `sail spec dispatch` respects `assignee` — each engineer's agent only picks up their specs (or unassigned ones)
- Dependencies prevent premature work — payments won't start until OAuth is done
No project board needed. The spec directory *is* the board. Git history is the audit trail.
### Fleet Migration
After upgrading `sail`, bring existing project containers up to the current spec layout and agent
instructions with one command:
```bash
sail project migrate --all --pull-specs
```
For a single project:
```bash
sail project migrate acme-health --pull-specs
```
The migration starts stopped projects, regenerates agent context files, converts legacy
`specs/index.yaml` entries into `specs//spec.yaml`, removes the legacy index after a safe
conversion, and reports spec Git sync state. Use `--json` for automation or `--keep-index` if you
want to retain the old index file during manual review.
## Context Generation
`sail agent run` (or `sail agent context regen`) generates a complete agent environment from `sail.yaml`. Context files are agent-agnostic — Claude Code gets `CLAUDE.md`, Codex gets `AGENTS.md`. Same content, different format.
| Generated | Purpose |
|-----------|---------|
| `CLAUDE.md` / `AGENTS.md` | Tech stack, conventions, runtimes, services, autonomous work protocol |
| `SECURITY.md` | Zero-trust principles, OWASP Top 10, input validation, secrets management |
| `.context/` repository | Persistent knowledge across sessions (system overview, patterns, failure log) |
| Methodology skills | `/spec` (write spec first), `/verify` (run tests and block on failures) |
| Post-task hooks | Auto-trigger security audit and code review at spec completion |
The autonomous work protocol in the context file tells the agent how to read specs, update status, and hand off — this works identically across Claude Code and Codex.
### `.context/` — Institutional Memory
```
.context/
system/ # always loaded — project overview, key decisions
patterns/ # discovered architectural patterns and conventions
failures/ # what went wrong and how it was fixed
```
Agents read `system/README.md` at session start and update these files as they learn. Committed alongside code so knowledge persists across sessions and engineers.
## Methodology
```yaml
agent:
methodology:
approach: spec-driven # spec-driven | tdd | free-form
verify: "mvn clean test"
lint: "mvn spotless:check"
```
- **`spec-driven`**: Agent writes a spec before coding. Generated as a `/spec` skill.
- **`tdd`**: Agent writes failing tests first, then implements until green.
- **`free-form`**: No methodology constraints.
- **`verify`** / **`lint`**: Commands injected as skills the agent runs after implementation.
## Guardrails
```yaml
agent:
guardrails:
max_duration: 4h
action: snapshot-and-stop
```
When the time limit triggers, the agent is stopped and rolled back to the pre-launch snapshot. The watcher starts automatically with `sail spec dispatch` and `sail agent run --background`.
Actions: `snapshot-and-stop` (rollback), `stop` (keep changes), `notify` (webhook, agent continues).
## Agent Commands
```bash
# Dispatch
sail spec dispatch acme-health # next ready spec, background launch
sail spec dispatch acme-health --spec auth # specific spec by ID
# Run (context regen + launch)
sail agent run acme-health # interactive mode (Zed)
sail agent run acme-health --task "..." # headless with explicit task
sail agent run acme-health --background # background, picks next spec
# Monitor
sail agent status # all projects at a glance
sail agent status acme-health # single project detail
sail agent log acme-health -f # stream output live
sail agent report acme-health # morning-after summary
# Control
sail agent stop acme-health # SIGTERM → SIGKILL after 3s
sail agent watch acme-health # enforce guardrails (auto-started by dispatch)
# Quality
sail agent audit acme-health # cross-agent security audit
sail agent review acme-health # cross-agent code review
sail agent sweep acme-health # codebase cleanup pass
```
## Multi-Agent Support
`sail` is agent-agnostic. Configure the primary agent and optionally install others for cross-agent review:
```yaml
agent:
type: claude-code
install:
- claude-code
- codex
security_audit:
enabled: true
# auditor: codex # defaults to a different agent than primary
code_review:
enabled: true
```
Claude or Codex can execute a spec. Set `agent: codex` in `spec.yaml` to override the
project default for that unit of work. For Codex, `model` and `reasoning_effort` map to
`codex exec --model ... --config model_reasoning_effort=...`. The hooks fire at spec completion,
not session stop — so reviews always see complete, coherent work.
## Example `sail.yaml`
```yaml
name: acme-health
description: "Acme Health Platform"
resources:
cpu: 4
memory: 12GB
disk: 150GB
image: ubuntu/24.04
runtimes:
jdk: 25
node: 22
maven: "3.9.9"
git:
name: "Acme Engineering"
email: "eng@acme.com"
auth: token
repos:
- url: "https://github.com/acme/backend.git"
path: "backend"
branch: "main"
- url: "https://github.com/acme/webapp.git"
path: "webapp"
services:
postgres:
image: postgres:16
ports: [5432]
environment:
POSTGRES_DB: acme
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
volumes:
- pgdata:/var/lib/postgresql/data
meilisearch:
image: getmeili/meilisearch:latest
ports: [7700]
environment:
MEILI_ENV: development
agent:
type: claude-code
auto_branch: true
auto_snapshot: true
specs_dir: specs
methodology:
approach: spec-driven
verify: "mvn clean test"
lint: "mvn spotless:check"
guardrails:
max_duration: 4h
action: snapshot-and-stop
ssh:
user: dev
authorized_keys:
- "ssh-ed25519 AAAA... you@laptop"
```
## Project Lifecycle
```bash
sail project create acme-health # provision container from sail.yaml
sail project start acme-health # start stopped container
sail project stop acme-health # stop container (preserves state)
sail project restart acme-health # start + show connection info
sail project containers # list all projects with status
sail project snapshot create acme-health # create snapshot
sail project snapshot restore acme-health snap-01 # rollback to snapshot
# Modify running projects
sail project add service acme-health
sail project add repo acme-health
sudo sail project resources set acme-health --memory 16GB
sail project destroy acme-health # delete container and state
```
## Building from Source
Requires JDK 25+ and Maven 3.9+.
```bash
mvn clean test # run tests (588 tests)
mvn clean package # build JAR
# Native image (requires GraalVM JDK 25)
JAVA_HOME=/usr/lib/jvm/graalvm-jdk-25 mvn clean package -Pnative -DskipTests
```
Every command supports `--help`. State-modifying commands support `--dry-run`. All commands support `--json` for machine-parseable output.
## License
[MIT](LICENSE)