This is a hobby/research project to see how far can we push Cloudflare durable objects to. Although it works, there are several rough edges, and I only work on it in my spare time. This README is edited and maintained with Claude (AI) and presented as-is.
Give every agent its own computer. Nimbus is a free and open-source, POSIX-like cloud OS that runs entirely on Cloudflare's network. A sandbox is a Worker isolate rather than a container, so it starts in about a second. Open a URL or call the SDK, and you get a real shell with node + bun (Cloudflare workerd nodejs_compat runtime), npm, git, real python (Pyodide-compiled CPython 3.13), real ruby (ruby.wasm 3.3), real clang (LLVM 8 → wasm32-wasi-nimbus), and 60+ Unix commands.
The OS half is also a library. @nimbus-sh/core runs the same durable filesystem, shell, and wasm runtimes in bun or node over a local SQLite, with no Cloudflare account involved. It also embeds inside other people's Durable Objects. See Use Nimbus as a library.
🌐 Try it now: https://nimbus-os.dev
Nimbus is an MIT-licensed hobby alpha. The repo, SDK, Worker runtime, React bindings, CLI, and config helpers are public and self-hostable.
The hosted demo at https://nimbus-os.dev is free for evaluation.
It is not a managed service, has no SLA, and may be rate-limited or reset. Do
not put secrets or production data in it. For real workloads, deploy Nimbus to
your own Cloudflare account with npx create-nimbus-app.
A VM-backed cloud dev environment is slow to start and expensive to idle. A browser sandbox starts fast and cannot run a real toolchain.
- Linux-like userland.
nodeandbunrun on the Cloudflare workerdnodejs_compatruntime, the same V8 your Workers code runs on. They are not a JS interpreter stub, and they are not the upstream Node or Bun binaries. Realgit cloneover HTTPS via isomorphic-git. Realnpm installagainst the live npm registry. Realpython(Pyodide-compiled CPython 3.13, WebAssembly), realruby(ruby.wasm 3.3, WebAssembly), realclang(LLVM 8 with modern wasi-libc, compiles C towasm32-wasi-nimbusin-session). - Sub-second start. Each session is a Cloudflare Durable Object backed by SQLite. Session create → first command runs in ~0.7 s median (measured with the ComputeSDK TTI methodology, N=200, 100% success). There is no VM boot and no image pull.
- Built for agents. Every agent can mint its own sandbox through the SDK. Sandboxes are cheap enough to create per-task, and 100 simultaneous creates succeed without a warm pool.
- One process, one isolate, 128 MiB each. Every isolate on Workers is capped at 128 MiB. Nimbus treats processes the way an OS treats them, so a heavy app spans several isolates. Each process gets its own isolate, with its own memory and CPU budget, wired to the others over the session's loopback network. opencode runs this way, as a server process and a TUI process in two isolates.
- $0 when idle. Sessions hibernate. Your filesystem persists. Come back tomorrow, the URL still works, your files are still there.
- The URL is the session. Bookmark it, share it, hand it to a teammate. They join the same filesystem.
- 10 GB of persistent storage per session, SQLite-backed, durable across reconnects and DO eviction.
A behavioral probe suite in tests/behavioral/ covers this table. Run it against a live deployment; see Tests.
| Capability | Status |
|---|---|
| Real shell, 60+ Unix commands, persistent 10 GB filesystem | ✅ |
node, bun via Cloudflare workerd nodejs_compat (V8 + Node-API shim, not the upstream binaries) |
✅ |
python / python3 — CPython 3.13 on wasm32-wasi (script + -c + -m + stdlib) |
✅ |
ruby / ruby3 — ruby.wasm-based Ruby 3.3 (script + -e + -r + stdlib) |
✅ |
clang — LLVM 8 → wasm32-wasi-nimbus, modern wasi-libc sysroot default, multi-TU + user headers + fopen |
✅ |
Interactive REPLs — python, ruby, node, bun (see REPL for state semantics) |
✅ |
npm install against the live registry, with cross-session L2 cache |
✅ |
npm alias dependencies such as alias: "npm:<pkg>@<version>" |
✅ |
git clone over HTTPS — chunked checkout engine; facebook/react (7,300 files) in ~28 s; 84,000-file worktrees materialize via bounded continuation |
✅ |
In-session loopback networking — curl http://127.0.0.1:<port> reaches servers in other isolates; node server.js auto-promotes to a routeable resident process |
✅ |
| Streaming HTTP through the fabric — SSE / chunked bodies flow live (per-chunk) across the isolate boundary, loopback and external preview alike | ✅ |
Unix permissions — real uid/gid ownership with EACCES enforced on read/write (including inside bash), durable st_mode, persisted chmod (octal + symbolic) + chown, exec-bit enforcement: ./binary runs only if executable (Permission denied, exit 126 otherwise), generic #! shebang dispatch |
✅ |
| Multi-isolate processes — client/server apps span facets (opencode runs as a serve + attach pair, each in its own isolate) | Alpha |
| Vite SPA dev server — full HMR to the preview iframe | ✅ |
wrangler dev for single-file Workers; Workers + Static Assets |
✅ |
| Programmatic sandbox SDK — exec/files/runtimes/processes/ports/Proteus-style tools | ✅ |
JS agent CLI primitives — env/home, npm/npx, child_process.spawn/exec/execFile, piped stdio, streams, logs |
✅ |
| Foreground attached npm-bin TTY tabs — stdin, resize, ANSI output, clean exit; Pi official installer and npm path probed | Alpha |
Python package workflows — pip, PyPI pure wheels, requirements/constraints, curated pure source artifacts, declared Pyodide startup-module packages, Flask, python -m flask run, python -m http.server preview |
Alpha |
Ruby package workflows — gem, bundle, pure gems, Rack/WEBrick preview |
Alpha |
| Session Agent — editor-workspace chat with Cloudflare OAuth / Workers AI and sandbox tools | ✅ |
npx <pkg> — first-class shebang + auto-install fallback |
✅ |
node_modules/.bin/* resolves and executes |
✅ |
Binary file round-trip via fs.writeFileSync / readFileSync |
✅ |
| Session recovery — WebSocket drop → reconnect preserves cwd, env, files | ✅ |
WASI preview1 — all 46 spec functions; outbound TCP via path_open('/dev/tcp/<host>/<port>') (JSPI); full poll_oneoff (fd / clock / socket subscriptions) |
✅ |
wasi-threads / pthreads — mutex, condvar, pthread_join, TLS, barriers, semaphores; cooperative, never parallel |
✅ (how) |
Nimbus is under active development. Support today:
- Stable: Vite + React, the Cloudflare Vite Plugin, single-file Workers, Workers with Static Assets, npm + git workflows, Python and Ruby scripts, clang C compilation (single-file and multi-file).
- Vite-based frameworks: Astro, SvelteKit, and Remix/React Router use the Vite path. Nuxt has Vite/Nitro caveats.
- Unfinished OS work: broader binary-extension artifact catalogs beyond declared packages, complete upstream
pip/Bundler CLI parity, full POSIX PTY parity, live filesystem bridges for every long-running runtime, and a realumask.opencode runagainst a real model is slow, because the one-shot path gets no provider warmup and exceeds its dispatch budget. Clones of 75,000+ objects need more index-pack CPU headroom, because fetch can exceed the per-invocation CPU budget on repos like microsoft/TypeScript. - Active research, mechanism proven live: real
fork()/exec()for compiled binaries over the isolate fabric via Binaryen Asyncify. Execution-state capture, parent/child divergence, and grandchild forks are all validated inside a production facet (fork of a 16 MiB image in under 1 ms). Unmodified GNU bash 5.2 runs live (nimbus install bash) with fork, pipes, subshells, and command substitution. A BusyBox coreutils set (ls, cat, cp, mv, rm, mkdir, grep, sed, awk, find, wc, sort, chmod, ...) is compiled to wasm32-wasi and exec'd as real external commands on bash's PATH, under S2a permission enforcement. - Explicit limits: Next.js dev server, Cloudflare Pages (
wrangler pages dev), Docker, apt, native Linux ELF execution, native platform-only CLI shards, native Linux Python wheels, native Ruby extensions without Nimbus-compatible artifacts, and raw public TCP listeners. A single session allows one active terminal owner at a time; sequential reconnect/share preserves filesystem and shell state.
1. Visit https://nimbus-os.dev
2. Click "Launch" — you'll be redirected to /s/<your-session-id>/
3. The URL is now your dev environment. Bookmark it.
You're in a real shell. Try:
node --version # workerd nodejs_compat (V8 + Node-API shim)
git clone https://github.com/AshishKumar4/Markflow # real git over HTTPS
cd Markflow && npm install # real npm against registry.npmjs.org
npm run dev # vite dev server — preview in the iframeThe preview pane on the right is tabbed. It keeps Markdown preview, the default
app preview at /s/<id>/preview/, Worker preview, and live port previews
together. When a new process exposes a port, Nimbus opens and focuses that port
tab automatically.
Or write some C:
cat > hello.c <<EOF
#include <stdio.h>
int main(void) { printf("hello from clang on the edge\n"); return 0; }
EOF
clang hello.c -o hello.wasm
./hello.wasmgit clone https://github.com/AshishKumar4/Nimbus.git
cd Nimbus
bun install
bun run dev # wrangler dev --ip 0.0.0.0 --port 8787Open http://localhost:8787 and click Launch.
One session = one Cloudflare Durable Object (the supervisor) plus a fabric of Worker Loader isolates (facets). The supervisor owns the durable state: the SQLite-backed filesystem, the shell, the process table, and the port registry. Every process runs in its own facet isolate with its own 128 MiB memory and CPU budget: one-shot facets for commands, resident keyed facets for servers, and a dedicated git engine. Facets write back through a streamed, credit-backpressured RPC pipeline so a parallel npm install or an 84,000-file checkout can't overwhelm the supervisor.
flowchart LR
C[Browser terminal · SDK client] -- "WebSocket + HTTPS" --> DO
subgraph session ["One session — supervisor DO + its facet fabric"]
DO["Session DO (supervisor)<br/>SQLite VFS · shell · process table<br/>port registry · agent"]
DO -- spawn --> F1["one-shot facets<br/>node · bun · python · wasm<br/>own 128 MiB + CPU each"]
DO -- "keyed resident facets" --> F2["server processes<br/>vite · flask · opencode serve<br/>routeable ports"]
DO -- "git engine facet" --> F3["clone-prepare · chunked checkout<br/>fresh CPU budget per phase"]
F1 & F2 & F3 -- "streamed writes (backpressured)" --> DO
F1 & F2 & F3 <-. "loopback 127.0.0.1:port<br/>routed by the supervisor" .-> F2
end
DO -- "peer-DO fanout<br/>(npm install shards)" --> P[("peer DOs")]
DO -- "L2/L3 cache" --> R2[("R2 + edge cache<br/>npm tarballs · runtime blobs · staged apps")]
Loopback networking is real. A process can curl http://127.0.0.1:5000/ and reach a server running in a different isolate. The supervisor's port registry routes it, on the same path the browser preview uses. That is how one app spans several isolates. opencode runs as a two-process app:
sequenceDiagram
participant T as Terminal
participant S as Session DO (supervisor)
participant A as facet A — opencode serve
participant B as facet B — opencode TUI
T->>S: opencode
S->>A: spawn resident facet: opencode serve --port 4096
A->>S: registerPort(4096) + route stub
S->>A: health-gate GET /doc (loopback)
S->>B: spawn TTY facet: opencode attach http://127.0.0.1:4096
B->>S: fetch 127.0.0.1:4096/…
S->>A: route → handleHttpRequest
A-->>B: responses stream back
Note over A,B: one app, two processes, two isolates —<br/>each with its own 128 MiB
T->>B: exit TUI
S->>A: lifecycle tie — serve is killed too
@nimbus-sh/core is the OS without the Worker: the durable
filesystem, the shell with 60+ Unix commands, and the WASI runtime layer. It
needs two SQL ports and no Cloudflare API. The same class runs
inside a Durable Object (ctx.storage.sql) and in a plain bun or node
process (bun:sqlite, node:sqlite).
import { NimbusWorkspace } from '@nimbus-sh/core/workspace';
const ws = await NimbusWorkspace.create({ sql, transactions, generation: 1 });
await ws.fs.writeFile('/home/user/hello.txt', 'hi\n');
await ws.exec('cat /home/user/hello.txt | wc -c'); // exitCode 0, stdout "3\n"The wasm runtimes ship as separate npm packages, so a filesystem-only embedder never downloads a Python interpreter:
npm install @nimbus-sh/runtime-bash @nimbus-sh/runtime-cpythonimport bash from '@nimbus-sh/runtime-bash';
import cpython from '@nimbus-sh/runtime-cpython';
import { localFacetHost } from '@nimbus-sh/core';
const ws = await NimbusWorkspace.create({
sql, transactions, generation: 1,
facets: localFacetHost(),
runtimes: [bash, cpython],
});
await ws.exec('bash -c "echo $((6*7))"'); // GNU bash 5.2, real BusyBox children
await ws.exec('python -c "print(6*7)"'); // CPython 3.13 with the real stdlibRuby 3.3 and clang work the same way. Every runtime package carries the same
manifest and sha256-verified blobs the hosted product serves from R2. The
workspace is a tenant in a database you own. It touches only its own tables,
and destroy() drops them.
Full details in the package README.
@nimbus-sh/fabric is the other half, for people building
on Durable Objects rather than embedding Nimbus. It carries
the facet and process fabric behind resident processes, warm Worker Loader pools,
the multi-reason alarm multiplexer, the generation counter that detects
instance resets, the durable launch journal, and byte-accounted turn pacing.
Its README lists the measured DO storage, CPU, facet, and RPC ceilings the
machinery is built against, and
PLATFORM.md is the full evidence-graded
catalog.
Embed Nimbus as an interactive dev environment, as a programmatic sandbox layer for backend Worker and Durable Object apps, or as both.
Use @nimbus-sh/sdk/worker for the deployed Worker embedder and
@nimbus-sh/sdk for programmatic sandboxes. The same SDK handle works
through a colocated Durable Object binding or through an authenticated
remote Nimbus deployment:
npx create-nimbus-app my-nimbus-worker
cd my-nimbus-worker
npm install
CLOUDFLARE_ACCOUNT_ID=<account-id> npx @nimbus-sh/cli setup cloudflare --name my-nimbus-worker
npx wrangler secret put JWT_SECRET
npx wrangler deploysetup cloudflare creates the account-local R2 buckets Nimbus binds to
and seeds the runtime cache for Python, Ruby, and clang. If Wrangler
reports Cloudflare R2 error 10042, enable R2 in the Cloudflare Dashboard
once for that account and rerun the setup command.
import { Nimbus } from '@nimbus-sh/sdk';
import { defineNimbusConfig } from '@nimbus-sh/config';
const nimbusConfig = defineNimbusConfig({
sandboxes: {
default: {
root: '/home/user',
tools: { namespace: 'sandbox', kind: 'sandbox' },
runtimes: {
preinstall: ['python', 'clang'],
onDemand: true,
allow: ['node', 'bun', 'npm', 'git', 'python', 'ruby', 'clang', 'shell'],
},
},
},
});
export default {
async fetch(_request: Request, env: Env) {
const nimbus = Nimbus.fromEnv(env, nimbusConfig);
const box = nimbus.sandbox('job-123', {
tenant: 'acme',
subject: 'agent',
});
const result = await box.exec('python -c "print(2 + 2)"');
return Response.json(result);
},
};For a remote Nimbus deployment, mint a scoped token and connect by URL:
import { Nimbus, issueNimbusToken } from '@nimbus-sh/sdk';
const token = await issueNimbusToken(env, {
tn: 'acme',
sub: 'agent',
scopes: ['sandbox:use'],
sid: 'job-123',
});
const box = Nimbus.connect({
endpoint: 'https://my-nimbus.workers.dev',
token,
config: nimbusConfig,
}).sandbox('job-123');Useful programmatic calls:
await box.ready(); // headless session boot
await box.files.write('/home/user/app/server.js', code);
await box.runtimes.ensure(['python', 'clang']); // package-manager backed
await box.runCode('print(2 + 2)', { language: 'python', install: 'ifMissing' });
const proc = await box.startProcess('node --watch /home/user/app/server.js');
// returns a live pid, does not block
const port = await box.ports.expose(3000); // /s/<id>/port/3000/
const provider = box.tools({ namespace: 'sandbox' }); // Proteus-style toolsUse @nimbus-sh/sdk/flue when an agent harness speaks Flue's sandbox
provider contract:
import { nimbusFlue } from '@nimbus-sh/sdk/flue';
const sandboxFactory = nimbusFlue(box);
const sessionEnv = await sandboxFactory.createSessionEnv({
id: 'job-123',
cwd: '/home/user',
});Nimbus is a Cloudflare Worker, Durable Object, and WebAssembly sandbox. It supports owned VFS, shell, npm/npx, git, long-running HTTP-like processes, Python, Ruby, clang-to-WASI, process logs, and port routing. It does not provide Docker, apt, GPUs, custom Linux images, native Linux ELF execution, or raw TCP listeners.
| Package | What |
|---|---|
@nimbus-sh/core |
The backend-agnostic OS: durable SQLite filesystem, shell + coreutils, WASI runtime layer, and NimbusWorkspace. Runs in Durable Objects, bun, and node. |
@nimbus-sh/runtime-bash / -cpython / -ruby / -clang |
The wasm runtimes as optional npm packages — same manifests and sha256-verified blobs the hosted product serves from R2. Pass to NimbusWorkspace.create({ runtimes }). |
@nimbus-sh/sdk |
Public SDK surface: Worker embedder (@nimbus-sh/sdk/worker), programmatic sandboxes (@nimbus-sh/sdk/sandbox), Flue connector (@nimbus-sh/sdk/flue), token mint/verify, typed errors, and session URL helpers. |
@nimbus-sh/fabric |
The Durable Object / facet / Worker Loader machinery as a standalone library: process fabric, loader pools, alarm multiplexing, launch journal, and the measured platform-invariant tables. |
@nimbus-sh/worker |
The Cloudflare half, composed on core and fabric: NimbusSession DO, router, assets, and auth internals. |
@nimbus-sh/react |
<NimbusTerminal /> React component. |
@nimbus-sh/cli |
nimbus init, nimbus setup cloudflare, token mint, and runtime sync. |
create-nimbus-app |
npx create-nimbus-app scaffold wrapper. |
@nimbus-sh/config |
Typed defineNimbusConfig() and buildNimbusWranglerConfig() helpers. |
The live demo at https://nimbus-os.dev runs from
apps/hosted-demo and is the canonical reference embedder.
It has the same shape any external project ships.
python, ruby, node, and bun launch interactive REPLs when given no arguments. There are two categories:
Stateful (real interpreter, real persistence):
python/python3— drives Pyodide'sPyodideConsoledirectly. Variables, functions, imports, multi-line blocks persist across submits.>>>primary,...continuation.ruby/ruby3— drives the long-lived ruby.wasm runtime.irb-styleirb>/irb*prompts. Variables, methods, requires persist.
Stateless emulation (workerd CSP-bounded):
node/bun— workerd's CSP blocks runtimeevalandnew Function, sovar/let/constdeclarations cannot persist across submits the way upstream Node/Bun keep them.console.logand per-line side effects work. For stateful work, run a script (node -e '<code>'ornode script.js). The REPL banner says this on launch.
Press Ctrl-D or type exit / .exit to leave. Probes: tests/behavioral/repl/ (13 probes covering exit semantics, prompts, stateful Python, error recovery).
clang compiles C to the wasm32-wasi-nimbus ABI in-session, then wasm-ld links. Both binaries run in a child-facet isolate on the same WASI layer every other non-node runtime uses, so #include "your-header.h" and fopen("./data.txt", "r") work.
What's wired today (v12 sysroot, currently deployed):
- Modern wasi-libc sysroot (binji-shape, derived from upstream wasi-sdk-19).
- Multi-translation-unit compile + link (
clang a.c b.c -o prog). - User headers in cwd or under
-I<dir>. fopen("...", "r" | "w" | "a")against VFS paths (relative + absolute).- 128-bit math intrinsics (
__muloti4,__divti3) provided via linkedlibclang_rt.builtins-wasm32.a. - Binary dispatch:
clangmarks linked executables0o755, soclang hello.c -o hello && ./helloruns directly, with no wrapper and no manual step.chmod -x hello && ./hellofails withPermission denied(exit 126). Non-wasm files with the exec bit dispatch via#!shebang or fall back tosh.
The stdio/atexit behavior is covered by the v13 probes in tests/behavioral/clang-stdio/. Sysroot selection is catalog-driven in R2, so after a catalog flip, verify the live deploy with those probes.
Probes: tests/behavioral/clang/, tests/behavioral/clang-includes/, tests/behavioral/clang-stdio/, tests/behavioral/wasi-paths/.
-pthread / wasi-threads programs run correctly but never in parallel. One core, one thread at a time. Build them with --import-memory --shared-memory and the futex shim. See docs/wasi-threads.md.
Session create was measured on 2026-08-08, the rest against a live deployment in 2026-07.
| Operation | Wall time |
|---|---|
| Session create → first command (TTI, ComputeSDK methodology, N=200) | 0.74 s median · 1.00 s P95 |
| 100 sandboxes created simultaneously (burst, all succeed) | 1.02 s median |
git clone facebook/react (7,300 files) |
~28 s |
npm install 611-package app (52,500 files, cold session) |
~165 s |
npm install zod (cold session) |
~6 s |
node -e 'console.log(...)' (warm) |
102–152 ms |
| Vite hot reload | 302 ms median |
Cross-session caching gives 9–16× speedups for warm package installs vs cold. Perf-regression probes in tests/behavioral/perf-regression/ assert thresholds on every deploy.
Every Nimbus session includes an Agent surface inside the editor workspace.
The center pane switches between the file editor and chat, while the terminal
and preview stay visible. The agent lives inside the same NimbusSession
Durable Object as the terminal, so it can use the same filesystem, shell,
runtime package manager, process table, logs, and preview ports.
The agent uses the AI SDK with Cloudflare Workers AI's OpenAI-compatible endpoint and an optional AI Gateway name. User OAuth spends the user's own Cloudflare quota. The owner-token fallback spends the deployment owner's quota. Responses stream into the chat UI, and the UI renders thinking state, tool-call status, tool inputs, and tool results inline.
Configure OAuth when each user should spend their own Cloudflare quota. In Cloudflare's Create OAuth client form, use:
- Client Name:
Nimbus Agent - Response Type:
Code - Grant type:
Authorization Code - Token Authentication Method:
None - Redirect (Callback) URLs:
https://<your-nimbus-host>/api/nimbus/oauth/callback - Client URL:
https://<your-nimbus-host>
Nimbus uses Authorization Code + PKCE. User OAuth tokens are stored only in
encrypted, HttpOnly, Secure, SameSite=Lax browser cookies scoped to the
session URL. Nimbus does not persist user OAuth tokens in Durable Object
storage.
On the scopes step, select the narrow scopes needed for the Agent:
| Dashboard scope | Scope ID | Why |
|---|---|---|
User Details Read |
user-details.read |
Read the connected user's profile. |
Account Settings Read |
account-settings.read |
List accounts the user can choose from. |
Workers AI Write |
ai.write |
Run Workers AI inference. |
AI Gateway Run |
aig.run |
Required only when NIMBUS_AGENT_GATEWAY_ID is set. |
Do not select Account API Gateway; that is an API Shield permission, not
Cloudflare AI Gateway. Cloudflare exposes the current scope IDs in the
dashboard and through GET /client/v4/oauth/scopes.
Add non-secret values to wrangler.jsonc or generate them with
@nimbus-sh/config:
Store secrets with Wrangler:
npx wrangler secret put NIMBUS_AGENT_COOKIE_SECRETFor a deployment-owner fallback instead of user OAuth:
{
"vars": {
"NIMBUS_CLOUDFLARE_ACCOUNT_ID": "<account-id>",
"NIMBUS_AGENT_MODEL": "@cf/moonshotai/kimi-k2.6",
"NIMBUS_AGENT_GATEWAY_ID": "default"
}
}npx wrangler secret put NIMBUS_CLOUDFLARE_API_TOKENThe owner token should have the Cloudflare permissions required by AI Gateway and Workers AI for the model you choose.
Use apps/hosted-demo as the current code-backed reference. It
runs the live demo and exposes /api/sdk-smoke plus /api/sdk-remote-smoke,
which exercise both SDK transports against the deployed app.
tests/behavioral/ contains a large black-box probe suite that drives a real session via POST /new + WebSocket. Probes assert real user-visible behavior. Structural-only assertions (regex on a bundle, HTTP 200 alone) are not accepted as pass criteria. See tests/behavioral/PROBE-QUALITY.md for the contract.
Run them all against the live deploy:
BASE=https://nimbus-os.dev bun test:behavioralOr one probe:
BASE=https://nimbus-os.dev bun tests/behavioral/clang-stdio/new/multi-printf-no-fflush.mjsNimbus is MIT licensed. See LICENSE.
Built by Ashish Kumar Singh on top of
LIFO OS by
Sanket Sahu, which seeded the shell
interpreter, coreutils, and Node.js shim. See NOTICE.md for
third-party credits and runtime license notes.
Contributions are welcome. Start with CONTRIBUTING.md
and open an issue or PR at https://github.com/AshishKumar4/Nimbus.

{ "vars": { "NIMBUS_CF_OAUTH_CLIENT_ID": "<oauth-client-id>", "NIMBUS_CF_OAUTH_SCOPES": "<scope-id-1> <scope-id-2>", "NIMBUS_AGENT_MODEL": "@cf/moonshotai/kimi-k2.6", "NIMBUS_AGENT_GATEWAY_ID": "default" } }