Codync
무료 오픈소스 1:1 대안, Grok Bot과 Muse 대신
에이전트 샌드박스의 SQLite, 자체 호스팅·E2B 호환. 한 대의 머신에 영구 샌드박스, 유휴 시 비용 없음
The SQLite of agent sandboxes — self-hosted, E2B-compatible. One machine, sandboxes that live forever, idle costs nothing.
개발 도구TypeScript · MDXGitHub @BitMiracle-AI직접 설치운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
설치형 프로젝트는 배포 도메인 없이도 확인할 수 있습니다. 개인 저장소는 GitHub 로그인으로, 조직 저장소는 위의 저장소 확인 파일로 직접 확인해 주세요.
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
The SQLite of agent sandboxes — a self-hosted sandbox platform for AI agents. One machine or a fleet of them, sandboxes that live forever, idle costs nothing.
Status: early development. The daemon, its lifecycle engine, the SDK, the CLI, the web console, the real Docker + gVisor executor, the S3 archiver, and the E2B-compatible API work end to end — the full create → freeze → stop → archive → restore cycle, command execution, file I/O, and the official e2b SDK against real infrastructure. Nothing here is ready for production yet.README 전문 보기 ↗The SQLite of agent sandboxes — a self-hosted sandbox platform for AI agents. One machine or a fleet of them, sandboxes that live forever, idle costs nothing.
Status: early development. The daemon, its lifecycle engine, the SDK, the CLI, the web console, the real Docker + gVisor executor, the S3 archiver, and the E2B-compatible API work end to end — the full create → freeze → stop → archive → restore cycle, command execution, file I/O, and the official
e2bSDK against real infrastructure. Nothing here is ready for production yet.
Cloud sandbox platforms charge for every second a sandbox exists, so their sandboxes are disposable. Dormice inverts that: you run it on a machine you already pay for, and sandboxes are permanent — they just get cheaper to keep the longer they sit idle.
acquireSandbox(userKey) is the entire mental model. Idempotent: the same key always comes back to the same sandbox, whatever state it was in. No sandbox → create; frozen → wake; stopped → start; archived → restore.active → frozen → stopped → archived — one rung at a time, and any acquire brings them back. Measured on real hardware: freezing takes an idle sandbox holding 1 GiB down to ~5 MiB of resident memory, and waking it takes ~50 ms.e2b SDK works against Dormice by changing two URLs.One command on a bare Ubuntu/Debian x86_64 host (as root):
curl -fsSL https://raw.githubusercontent.com/BitMiracle-AI/Dormice/main/deploy/install.sh | bash
Behind a slow connection to the usual sources, add -s -- --mirror cn.
The installer is idempotent — re-running it upgrades the code and repairs
drift, and never rotates your API token. It ends by running dor doctor,
a battery of read-only checks — three of them boot a real gVisor
container — that decides whether the install actually succeeded;
dor doctor can be re-run on its own at any time.
A second machine joins the same fleet with one more command
(--role node --gateway http://<first machine>:80, the token in the
environment) and needs no settings of its own; upgrades then run from
the gateway, one node at a time. See the
installation and
upgrading docs.
@dormice/sdk is the native TypeScript client. (Not on npm yet — the
first release is queued; inside this repo, pnpm build produces it.)
import { Dormice } from '@dormice/sdk';
const client = new Dormice({
endpoint: 'http://127.0.0.1:3677',
token: process.env.DORMICE_API_TOKEN!,
});
// One key, one sandbox — created, woken or restarted as needed.
// stopAfterSeconds: null makes it a resident agent: it may freeze when
// idle (~50 ms to wake) but never cold-starts.
await client.acquireSandbox('my-agent', { policy: { stopAfterSeconds: null } });
const result = await client.execCommand('my-agent', 'python3 -c "print(6 * 7)"');
console.log(result.exitCode, result.stdout); // 0 42
await client.writeFiles('my-agent', [
{ path: 'notes.txt', content: 'survives freeze and stop' },
]);
await client.destroySandbox('my-agent'); // destroy — the only verb that loses data
The wire is plain HTTP RPC (POST /acquireSandbox, POST /execCommand, …),
so curl works where the SDK doesn't reach, and the dor CLI covers the
operator side: dor sandbox ls / exec / push / pull / rebuild / destroy,
plus dor doctor. The full native surface is documented in
packages/sdk, and runnable versions of these
flows live in examples/.
Dormice's users are agents, so the manual comes in a form an agent can install — a skill in the open Agent Skills format:
npx skills add BitMiracle-AI/Dormice
One file, skills/dormice/SKILL.md, teaching a
coding agent the whole surface: how to connect, pick between the E2B SDKs /
native API / CLI, run commands, move files, and set lifecycle policy. The
documentation site is AI-readable too — its build emits /llms.txt,
/llms-full.txt, and a plain-markdown .md twin of every docs page.
The daemon speaks the E2B protocol on two prefixes (/e2b/api,
/e2b/envd). The official e2b package — unmodified, straight from
npm — runs against Dormice with two URLs and an API-key prefix; migrating
an application is configuration, not code:
import { Sandbox } from 'e2b';
const sbx = await Sandbox.create({
apiKey: `e2b_${process.env.DORMICE_API_TOKEN}`,
apiUrl: 'http://127.0.0.1:3677/e2b/api',
sandboxUrl: 'http://127.0.0.1:3677/e2b/envd',
});
Everything below is exercised by the black-box e2e suite through the official package, and has passed against a real Docker + gVisor daemon:
| Surface | Notes |
|---|---|
Sandbox.create / connect / kill / list | list filters by state and metadata, and paginates |
| Timeouts | timeoutMs and setTimeout() are real absolute deadlines; lifecycle: { onTimeout: 'pause' } parks the sandbox instead of killing it |
pause() / resume | explicit pause; connect revives it, files intact |
commands.run | live streaming (onStdout / onStderr), background + connect / disconnect, sendStdin, kill, list, per-command envs, user: 'root'; a non-zero exit raises the SDK's own CommandExitError |
pty.* | create / sendInput / resize / kill — a real interactive bash |
files read / write | text or bytes, streamed, no artificial size cap — the disk quota is the cap |
uploadUrl() / downloadUrl() | signed URLs: expiry enforced, a tampered signature is a 401 |
files.list / exists / makeDir / rename / remove | typed errors match the SDK's expectations |
files.watchDir | streamed events, and the polling watcher API the Python sync SDK uses |
getHost(port) | port proxy with wake-on-traffic (set DORMICE_SANDBOX_DOMAIN) |
getMetrics() | one live sample; observing never wakes a frozen sandbox |
Deliberate deltas from the hosted product:
dor template add, and Sandbox.create('name')
resolves it (an unregistered name is an honest 404). The hosted
product's build pipeline (e2b template build) is not implemented.metadata.externalId turns Sandbox.create into Dormice's idempotent
acquire: the same key returns the same sandbox instead of a new one.unimplemented on the
wire: Process/StreamInput (the JS SDK never calls it) and xattr-based
file metadata. The daemon reports envd 0.6.1, so the SDK itself gates
those features client-side.The gateway — the fleet's front door, installed beside the daemon — serves
a small web console at http://127.0.0.1:3677/console: sign in with the
API token once and it becomes an httpOnly session cookie; the token itself
is never stored anywhere the page can read. The console
shows every sandbox with its live lifecycle state (the same
/listSandboxes the SDK sees), opens a per-sandbox detail view, creates
sandboxes (the same idempotent acquire, with the lifecycle knobs),
releases them, and has a Connect page with copy-paste snippets for every
client (E2B SDK, native SDK, CLI) pointed at your own endpoint.
Both processes listen on 127.0.0.1 only (the gateway on 3677, the daemon on 3676), so reaching them from another machine is a choice you make explicitly, one of two ways:
SSH tunnel (private, zero setup):
ssh -L 3677:127.0.0.1:3677 root@host, then open
http://127.0.0.1:3677/console.
Reverse proxy for the console, the API, and the E2B surface at once — e.g. Caddy pointed at the gateway, which also handles TLS certificates automatically once you give it a domain:
your-domain.example {
reverse_proxy 127.0.0.1:3677 {
flush_interval -1
}
}
flush_interval -1 matters: streamed command output is written frame by
frame, and a buffering proxy would turn it into one lump at the end.
Anything exposed beyond localhost should be HTTPS — the API token and the
session cookie travel in every request.
Configure a store in the console's settings page — or seed the four
DORMICE_S3_* variables in the gateway's env (/etc/dormice/gateway.env)
— and idle sandboxes take the last step down: a week after stopping (tunable per sandbox via
archiveAfterSeconds), the disk is packed with tar + zstd, shipped to
any S3-compatible bucket (AWS, Cloudflare R2, MinIO, Alibaba OSS in
S3-compat mode), and freed locally. The next acquireSandbox answers
{ status: 'restoring', progress } immediately and flips to ready once
the disk is back — slow wake-ups are honest, never a silent hang.
DORMICE_S3_ENDPOINT=https://s3.example.com # full URL; MinIO speaks http
DORMICE_S3_BUCKET=dormice-archive
DORMICE_S3_ACCESS_KEY_ID=...
DORMICE_S3_SECRET_ACCESS_KEY=...
# DORMICE_S3_REGION=us-east-1
# DORMICE_S3_FORCE_PATH_STYLE=true # MinIO needs this
Unset, the feature is honestly absent: sandboxes park at stopped
forever, and a policy asking to archive is refused rather than silently
stored. The bucket must exist; the host needs zstd (install.sh
installs it, dor doctor checks it).
The daemon itself runs anywhere Node 22+ runs, with an in-memory fake
executor for development. Running real sandboxes needs a Linux host
prepared as above — install.sh automates all of it and dor doctor
verifies it, but these are the facts underneath:
runsc), and root (loop mounts, cgroup writes).vm.swappiness=100. Freezing squeezes an idle sandbox's
memory out to swap; gVisor holds sandbox memory as shared memory, which
the kernel refuses to swap at the default swappiness — measured on real
hardware: 0 bytes reclaimed at the default, 99.5% reclaimed at 100. Note
that some cloud images (Alibaba Cloud, for one) ship vm.swappiness=0;
check the effective value with sysctl vm.swappiness, not the config
files.iptables -I DOCKER-USER -d 169.254.0.0/16 -j DROP, persisted) and
disable inter-container traffic ("icc": false in daemon.json). The
daemon binds to 127.0.0.1 only, by design without a knob; exposing it is
a reverse proxy's job.Pick something else if:
pnpm monorepo:
| Path | What it is |
|---|---|
packages/shared | Protocol schemas (zod) — the single source of truth for wire types |
packages/server | The daemon: Fastify + SQLite ledger + lifecycle engine |
packages/sdk | @dormice/sdk — TypeScript client for the native API |
packages/cli | dormice command-line tool (dor for short) |
packages/console | Web console: React SPA, served by the gateway at /console |
packages/gateway | The fleet's one door in front of one or more daemons: holds the fleet's settings, templates, API keys and the console; places new sandboxes, finds existing ones by asking the nodes, forwards everything else |
e2e | Black-box suite: boots the built daemon, drives it over the wire |
examples | Runnable demos: the native SDK, the official e2b package, a resident agent |
pnpm install
pnpm build # the e2e suite boots the built daemon, so build comes first
pnpm typecheck
pnpm lint
pnpm test
Dormice runs production fleets for several commercial services, so code changes come from the maintaining team only. Issues are welcome and are how outside fixes reach the project: report the bug, describe the fix you have in mind, and a maintainer will implement it and credit you. Pull requests are not accepted; see CONTRIBUTING.md for the reasoning.
E2B is a trademark of its respective owner. Dormice is an independent project and is not affiliated with, endorsed by, or sponsored by E2B. References to the e2b package describe interoperability with its published API only.