Codync
免费开源的 1:1 Grok Bot 与 Muse 替代方案。可在 iPhone、Mac 或 Linux 桌面上将 Claude 代码、Codex、Cursor 以及 40 多个编码代理作为持久机器人使用。支持群组聊天、线程、应用。
AI 翻译
代理沙盒的 SQLite —— 自托管,兼容 E2B。单机运行,沙盒永久存活,空闲不产生成本。
AI 翻译
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.