{"id":47662472,"url":"https://github.com/singlr-ai/sing","last_synced_at":"2026-06-15T03:05:04.508Z","repository":{"id":346468858,"uuid":"1152460349","full_name":"singlr-ai/sing","owner":"singlr-ai","description":"Isolated development environments for AI agents","archived":false,"fork":false,"pushed_at":"2026-06-13T00:58:40.000Z","size":1807,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-13T02:24:37.944Z","etag":null,"topics":["ai-agents","coding-agent","development-environment"],"latest_commit_sha":null,"homepage":"https://sing.singlr.ai","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/singlr-ai.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-06-13T00:58:42.000Z","dependencies_parsed_at":null,"dependency_job_id":"af87f1e6-e723-48d8-bf2a-9557a7a11107","html_url":"https://github.com/singlr-ai/sing","commit_stats":null,"previous_names":["singlr-ai/sing"],"tags_count":87,"template":false,"template_full_name":null,"purl":"pkg:github/singlr-ai/sing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singlr-ai%2Fsing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singlr-ai%2Fsing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singlr-ai%2Fsing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singlr-ai%2Fsing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/singlr-ai","download_url":"https://codeload.github.com/singlr-ai/sing/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/singlr-ai%2Fsing/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34345590,"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-06-15T02:00:07.085Z","response_time":63,"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":["ai-agents","coding-agent","development-environment"],"created_at":"2026-04-02T11:40:21.763Z","updated_at":"2026-06-15T03:05:04.465Z","avatar_url":"https://github.com/singlr-ai.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sail\n\nA single native binary that provisions bare-metal servers and manages isolated dev environments for AI-assisted engineering. One binary, zero dependencies, fully declarative.\n\nBuilt with Java 25 + picocli + GraalVM native-image. \u003c1ms startup.\n\n## Why\n\nYou 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.\n\n`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.\n\n## Day 0: Server + Project Setup\n\n```bash\n# Install sail (single binary, no dependencies)\ncurl -fsSL https://raw.githubusercontent.com/singlr-ai/sing/main/install.sh | bash\n\n# Initialize server (one-time, needs sudo)\nsudo sail host init\n```\n\n`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.\n\n```bash\n# Pull project descriptor from shared repo (team projects)\nexport GITHUB_TOKEN=ghp_...\nsail project pull acme-health\n\n# Or generate a new sail.yaml interactively\nsail project init\n\n# Create the environment\nsail project create acme-health\n```\n\n`project pull` stores the project bundle under `~/.sail/projects/\u003cname\u003e/` by default.\n\n`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.\n\n```bash\n# Print SSH config for your editor\nsail project connect acme-health\n```\n\nAdd the output to `~/.ssh/config`, then connect in Zed: `Cmd+Shift+P` → \"Connect to SSH Host\" → `acme-health`.\n\n## Day 2: The Two Modes\n\nEngineers work in two modes. `sail` supports both from the same project.\n\n### Interactive Mode (Daytime)\n\nOpen 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.\n\n```bash\nsail project restart acme-health     # start container, show connection info\n```\n\nDeveloper 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.\n\n### Autonomous Mode (Overnight)\n\nWrite specs during the day. Walk away. The agent works through them overnight.\n\n```bash\nsail spec dispatch acme-health   # pick next ready spec, launch agent\n```\n\n`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.\n\n## Spec-Driven Workflow\n\nSpecs 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.\n\n### Structure\n\n```\nspecs/\n├── oauth-flow/\n│   ├── spec.yaml             # Metadata: id, title, status, assignee, depends_on\n│   ├── spec.md               # What to build and why (brainstormed with agent in Zed)\n│   └── plan.md               # How to build it (optional, for complex specs)\n├── payment-integration/\n│   ├── spec.yaml\n│   ├── spec.md\n│   └── plan.md\n└── fix-footer-typo/\n    ├── spec.yaml\n    └── spec.md               # Simple spec, no plan needed\n```\n\n### spec.yaml\n\n```yaml\nid: payment-integration\ntitle: \"Stripe payment webhook\"\nstatus: pending\nassignee: bob\ndepends_on:\n  - oauth-flow\nrepo: webapp\nagent: codex\nmodel: gpt-5.5\nreasoning_effort: high\nbranch: feat/payment-integration\n```\n\n`repo`/`repos` routes work to the right repository in multi-repo projects. `agent` routes a spec\nto a specific installed agent (`claude-code` or `codex`); if omitted, dispatch uses\n`agent.type` from `sail.yaml`. `model` and `reasoning_effort` tune agents that support those\ncontrols; unsupported combinations fail fast.\n\n### Lifecycle\n\n```\npending → in_progress → review → done → archive\n```\n\n**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`).\n\n### The Full Loop\n\n```\nMorning (Zed, interactive):\n  Engineer + agent brainstorm → write specs/oauth-flow/spec.md\n  Optionally plan → write specs/oauth-flow/plan.md\n  Push specs to shared repo\n\nEvening:\n  sail spec dispatch acme-health\n\nOvernight:\n  Agent reads spec.md, works, commits, pushes branch\n  Reviews run automatically at spec completion\n  Guardrails enforce time limits\n\nNext morning:\n  sail agent status              # all projects at a glance\n  sail agent report acme-health  # detailed: commits, spec progress, review results\n  Review PRs, merge or address findings\n```\n\n### Team Coordination\n\nSpecs live in a shared private repo (e.g., `your-org/projects/acme-health/specs/`). Multiple engineers, each with their own container:\n\n- Alice specs out OAuth, assigns to herself\n- Bob specs out payments, depends on Alice's OAuth work\n- `sail spec dispatch` respects `assignee` — each engineer's agent only picks up their specs (or unassigned ones)\n- Dependencies prevent premature work — payments won't start until OAuth is done\n\nNo project board needed. The spec directory *is* the board. Git history is the audit trail.\n\n### Fleet Migration\n\nAfter upgrading `sail`, bring existing project containers up to the current spec layout and agent\ninstructions with one command:\n\n```bash\nsail project migrate --all --pull-specs\n```\n\nFor a single project:\n\n```bash\nsail project migrate acme-health --pull-specs\n```\n\nThe migration starts stopped projects, regenerates agent context files, converts legacy\n`specs/index.yaml` entries into `specs/\u003cid\u003e/spec.yaml`, removes the legacy index after a safe\nconversion, and reports spec Git sync state. Use `--json` for automation or `--keep-index` if you\nwant to retain the old index file during manual review.\n\n## Context Generation\n\n`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.\n\n| Generated | Purpose |\n|-----------|---------|\n| `CLAUDE.md` / `AGENTS.md` | Tech stack, conventions, runtimes, services, autonomous work protocol |\n| `SECURITY.md` | Zero-trust principles, OWASP Top 10, input validation, secrets management |\n| `.context/` repository | Persistent knowledge across sessions (system overview, patterns, failure log) |\n| Methodology skills | `/spec` (write spec first), `/verify` (run tests and block on failures) |\n| Post-task hooks | Auto-trigger security audit and code review at spec completion |\n\nThe 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.\n\n### `.context/` — Institutional Memory\n\n```\n.context/\n  system/       # always loaded — project overview, key decisions\n  patterns/     # discovered architectural patterns and conventions\n  failures/     # what went wrong and how it was fixed\n```\n\nAgents read `system/README.md` at session start and update these files as they learn. Committed alongside code so knowledge persists across sessions and engineers.\n\n## Methodology\n\n```yaml\nagent:\n  methodology:\n    approach: spec-driven    # spec-driven | tdd | free-form\n    verify: \"mvn clean test\"\n    lint: \"mvn spotless:check\"\n```\n\n- **`spec-driven`**: Agent writes a spec before coding. Generated as a `/spec` skill.\n- **`tdd`**: Agent writes failing tests first, then implements until green.\n- **`free-form`**: No methodology constraints.\n- **`verify`** / **`lint`**: Commands injected as skills the agent runs after implementation.\n\n## Guardrails\n\n```yaml\nagent:\n  guardrails:\n    max_duration: 4h\n    action: snapshot-and-stop\n```\n\nWhen 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`.\n\nActions: `snapshot-and-stop` (rollback), `stop` (keep changes), `notify` (webhook, agent continues).\n\n## Agent Commands\n\n```bash\n# Dispatch\nsail spec dispatch acme-health              # next ready spec, background launch\nsail spec dispatch acme-health --spec auth  # specific spec by ID\n\n# Run (context regen + launch)\nsail agent run acme-health                   # interactive mode (Zed)\nsail agent run acme-health --task \"...\"      # headless with explicit task\nsail agent run acme-health --background      # background, picks next spec\n\n# Monitor\nsail agent status                      # all projects at a glance\nsail agent status acme-health          # single project detail\nsail agent log acme-health -f          # stream output live\nsail agent report acme-health          # morning-after summary\n\n# Control\nsail agent stop acme-health            # SIGTERM → SIGKILL after 3s\nsail agent watch acme-health           # enforce guardrails (auto-started by dispatch)\n\n# Quality\nsail agent audit acme-health           # cross-agent security audit\nsail agent review acme-health          # cross-agent code review\nsail agent sweep acme-health           # codebase cleanup pass\n```\n\n## Multi-Agent Support\n\n`sail` is agent-agnostic. Configure the primary agent and optionally install others for cross-agent review:\n\n```yaml\nagent:\n  type: claude-code\n  install:\n    - claude-code\n    - codex\n  security_audit:\n    enabled: true\n    # auditor: codex      # defaults to a different agent than primary\n  code_review:\n    enabled: true\n```\n\nClaude or Codex can execute a spec. Set `agent: codex` in `spec.yaml` to override the\nproject default for that unit of work. For Codex, `model` and `reasoning_effort` map to\n`codex exec --model ... --config model_reasoning_effort=...`. The hooks fire at spec completion,\nnot session stop — so reviews always see complete, coherent work.\n\n## Example `sail.yaml`\n\n```yaml\nname: acme-health\ndescription: \"Acme Health Platform\"\n\nresources:\n  cpu: 4\n  memory: 12GB\n  disk: 150GB\n\nimage: ubuntu/24.04\n\nruntimes:\n  jdk: 25\n  node: 22\n  maven: \"3.9.9\"\n\ngit:\n  name: \"Acme Engineering\"\n  email: \"eng@acme.com\"\n  auth: token\n\nrepos:\n  - url: \"https://github.com/acme/backend.git\"\n    path: \"backend\"\n    branch: \"main\"\n  - url: \"https://github.com/acme/webapp.git\"\n    path: \"webapp\"\n\nservices:\n  postgres:\n    image: postgres:16\n    ports: [5432]\n    environment:\n      POSTGRES_DB: acme\n      POSTGRES_USER: dev\n      POSTGRES_PASSWORD: dev\n    volumes:\n      - pgdata:/var/lib/postgresql/data\n\n  meilisearch:\n    image: getmeili/meilisearch:latest\n    ports: [7700]\n    environment:\n      MEILI_ENV: development\n\nagent:\n  type: claude-code\n  auto_branch: true\n  auto_snapshot: true\n  specs_dir: specs\n  methodology:\n    approach: spec-driven\n    verify: \"mvn clean test\"\n    lint: \"mvn spotless:check\"\n  guardrails:\n    max_duration: 4h\n    action: snapshot-and-stop\n\nssh:\n  user: dev\n  authorized_keys:\n    - \"ssh-ed25519 AAAA... you@laptop\"\n```\n\n## Project Lifecycle\n\n```bash\nsail project create acme-health   # provision container from sail.yaml\nsail project start acme-health               # start stopped container\nsail project stop acme-health             # stop container (preserves state)\nsail project restart acme-health           # start + show connection info\nsail project containers                           # list all projects with status\nsail project snapshot create acme-health             # create snapshot\nsail project snapshot restore acme-health snap-01  # rollback to snapshot\n\n# Modify running projects\nsail project add service acme-health\nsail project add repo acme-health\nsudo sail project resources set acme-health --memory 16GB\nsail project destroy acme-health  # delete container and state\n```\n\n## Building from Source\n\nRequires JDK 25+ and Maven 3.9+.\n\n```bash\nmvn clean test                    # run tests (588 tests)\nmvn clean package                 # build JAR\n\n# Native image (requires GraalVM JDK 25)\nJAVA_HOME=/usr/lib/jvm/graalvm-jdk-25 mvn clean package -Pnative -DskipTests\n```\n\nEvery command supports `--help`. State-modifying commands support `--dry-run`. All commands support `--json` for machine-parseable output.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinglr-ai%2Fsing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsinglr-ai%2Fsing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinglr-ai%2Fsing/lists"}