Repository navigation
Expand file tree
/
Copy pathllms.txt
More file actions
177 lines (135 loc) · 20.4 KB
/
Copy pathllms.txt
File metadata and controls
177 lines (135 loc) · 20.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# Ramune
> Foundation for building Workers-style platforms in Go; Cloudflare-Workers-compatible out of the box. Author handlers as Workers-style ES modules (`export default { fetch(req, env, ctx), scheduled }`), serve them with the `ramune serve` CLI or the `workers.Register` Go API, and **design your own `env`** (Redis, Postgres, S3, SMTP, your own gRPC service, anything) by registering a callback and a tiny JS facade. Code written against Cloudflare Workers runs unchanged because the default surface is CF-compatible. `ramune compile --hybrid` performs soundness-gated AOT native compilation: functions whose signature and body are statically provable to be semantics-equivalent to Go are extracted into native Go at compile time; the rest stay on the JS floor. Also a complete JS/TS runtime (run/test/check/fmt/lint/repl/compile) and embeddable JS engine. Tri-backend: JavaScriptCore (JIT, macOS/Linux) via [purego](https://github.com/ebitengine/purego), qjswasm (pure Go, cross-platform incl. Windows — QuickJS-NG compiled to WebAssembly and driven by wazero) via [fastschema/qjs](https://github.com/fastschema/qjs), and goja (pure Go, reflect-based) via [dop251/goja](https://github.com/dop251/goja) — no Cgo required for any of them.
## Backends
Three backends, same API:
- **JSC** (default): Apple JavaScriptCore via purego. JIT, macOS/Linux.
- **qjswasm** (`-tags qjswasm`): QuickJS-NG compiled to WebAssembly, driven by wazero's compiler-mode JIT (AOT WASM→native). Pure Go, macOS/Linux/Windows/FreeBSD. Beats the previous modernc.org/quickjs backend (removed 2026-04) by 1.7-2.3× on req/s and scales 5.72× to 6 workers.
- **goja** (`-tags goja`): dop251/goja, pure Go, reflect-based. Smallest footprint (no ~1 MB wasm embed). ~94% ECMAScript coverage, macOS/Linux/Windows/FreeBSD.
## Getting Started
- [README](https://github.com/i2y/ramune/blob/main/README.md): Install, quick start, all CLI commands, embedding in Go, benchmarks
- [Go Package Documentation](https://pkg.go.dev/github.com/i2y/ramune): Full API reference
## CLI Runtime
- [CLI (cmd/ramune)](https://github.com/i2y/ramune/blob/main/cmd/ramune/main.go): `ramune run`, `ramune serve`, `ramune eval`, `ramune repl`, `ramune test`, `ramune build`, `ramune bench`, `ramune x`, `ramune init/add/remove/install`, `ramune setup-jit`, `ramune skills install`. Dispatches to the separate `ramune-toolchain` binary for `check` / `fmt` / `lint` / `compile` / `transpile` / `typegen` (keeps the main ramune binary free of the tsgo + rslint + gotranspiler init cost).
- [Toolchain CLI (cmd/ramune-toolchain)](https://github.com/i2y/ramune/blob/main/cmd/ramune-toolchain/main.go): `check` (tsgo type check), `fmt` (tsgo formatter), `lint` (rslint), `compile` (bundle handler + runtime into a single Go binary; the `--native` TS→Go path for extension modules is experimental, see below), `transpile` (TS→Go source, experimental), `typegen` (Go→.d.ts). Install alongside `ramune` via `go install github.com/i2y/ramune/cmd/ramune-toolchain@latest`.
- TypeScript 7.0 compiler (typescript-go) across `run` / `check` / `fmt` / transpile / workers dispatch / nodecompat `require('./*.ts')` — one Go-native tsc across every TS surface, no subprocess
- ESM (import/export) and CommonJS support — per-file emit via typescript-go, multi-file bundling via esbuild Build API
- `ramune compile` — compile JS/TS to standalone Go binary via go:embed
- `ramune compile --hybrid` — soundness-gated AOT: picker extracts top-level functions / pure classes whose signature and body provably round-trip to Go; everything else stays on the JS floor. Postlude shim is prepended so module-scope reassignments override hoisted user bindings before any top-level call (no `setTimeout(0)` workaround needed). Apple M4 Max Fib(40) wallclock: hybrid 243 ms, JSC 358 ms, Bun 364 ms, Node 535 ms — hybrid is the fastest single-process JS/TS runtime on the box for compute-bound TS.
- `ramune compile --hybrid-backend tinygo` — emits `jsbridge.Func` (interface) instead of `*ramune.JSFunc` (host concrete) for callable-typed params, so the artifact's transitive deps stay inside TinyGo's stdlib subset.
- `ramune compile --target wasm-wasi -o app.wasm app.ts` — TinyGo-built standalone WASI reactor, no JS runtime bundled. Numerics-only (`float64`/`int*`/`bool`) functions get `//go:wasmexport` wrappers; non-numeric ones compile in but aren't exposed via the WASI ABI. Artifact is ~110-320 KB. Requires `tinygo` on PATH.
- `ramune compile --native <file.ts>` — transpile TypeScript to native Go extensions callable from JS via `require('native:name')` (experimental; inherits transpiler's status)
- `ramune transpile` — transpile TypeScript source files to Go source code
- `ramune typegen go:pkg... -o types.d.ts` — generate TypeScript .d.ts declarations from Go packages
- `ramune run --workers N` — multi-worker HTTP serving with parallel JSC VMs
- `ramune serve <entry.ts>` — Cloudflare-Workers-style ES-module handler (`export default { fetch(request, env, ctx), scheduled(event, env, ctx) }`). Reads optional `ramune.toml`, supports `--workers N` (round-robin across independent runtimes), `--sqlite <path>` (default `.ramune/data.db`) for env.DB / env.KV, `--sandbox` + `--allow-*`. Works with Hono directly.
- `ramune run --env-file` — .env file auto-loading (like Bun/Deno)
- `ramune run <script>` — package.json scripts runner
- package.json entry point, dependency resolution, and `exports` field support
- Watch mode (`-w` flag) via fsnotify
- Test runner with Jest/Bun-compatible API (describe, test, expect, jest.fn, jest.spyOn)
- Type checking via tsgo (`ramune check`, `ramune run --check`)
- Formatting via tsgo (`ramune fmt`)
- Linting via rslint (`ramune lint`)
- Deno-style permissions (`--sandbox`, `--allow-read`, `--allow-write`, `--allow-net`)
- Rich REPL with history, tab completion, colors (ergochat/readline + charmbracelet/lipgloss)
## Hybrid AOT (--hybrid)
- Picker accepts: primitive / T[] / Promise<primitive> signatures; pure classes (primitive fields, constructor-initialized, `this`-method bodies, `static` methods including cross-file calls); arithmetic, comparison, `%`, `switch`, `for` / `while` / `for-of`, template literals, `await`-on-extractable; `Math.*` / `Number.*`; string and array method safelists (`map`, `filter`, `forEach`, `some`, `every`, `find`, `findIndex`, `reduce`, `push`, `charAt`); named-interface struct params (including nested struct fields and literal union types like `"a" | "b"`); same-file `*JSFunc` callback params; module-scope `const` declarations extracted alongside dependent functions; `Map<string, primitive>` and `Set<primitive>` (`.has` / `.get` / `.set` / `.delete` / `.size` / `.clear`); array spread (`[a, ...rest]`).
- Picker rejects: inline object literal params, `Date` / `RegExp`, `try` / `catch` / `throw`, generics, generators, closure capture beyond params/locals, parameter mutation, class inheritance / `#private` / decorators / getters-setters, `str.charCodeAt`, and more. Each rejection ships an actionable hint suggesting how to rewrite for extraction; print the full report with `--hybrid-report` on stderr.
- Shim prepend: the composer's postlude rebinds module-scope user identifiers to native exports. The shim is prepended (not appended) so hoisted `function` declarations bind first, then the shim runs before any top-level call site (no `setTimeout(0)` workaround needed).
- TinyGo backend: `--hybrid-backend tinygo` emits `jsbridge.Func` (interface) instead of `*ramune.JSFunc` so the artifact stays inside TinyGo's stdlib subset; `--target wasm-wasi` produces a standalone WASI reactor of the picker-extracted Go alone (no JS runtime bundled, ~110-320 KB).
- Real-world: `examples/hybrid-realworld/` extracts lodash_mini at 16/17 (~94%) and zod_lite at 17/17 (100%).
- Examples: `examples/hybrid/`, `examples/hybrid-hono/`, `examples/hybrid-multifile/`, `examples/hybrid-realworld/`, `examples/hybrid-tui/`.
## TypeScript-to-Go Transpiler (Experimental)
- [Transpiler (internal/gotranspiler/)](https://github.com/i2y/ramune/blob/main/internal/gotranspiler/): Built-in TypeScript-to-Go transpiler (experimental — under active development)
- [Native Bridge (internal/gotranspiler/nativebridge.go)](https://github.com/i2y/ramune/blob/main/internal/gotranspiler/nativebridge.go): Discovers exported Go functions, generates NativeModuleFromFuncs bridge code
- Supported: number, string, boolean, arrays, Map, Set, Promise, generics, classes (static, abstract, getter/setter), interfaces, enums, discriminated unions, async/await, destructuring with defaults, template literals, array/string methods
- Operators: typeof, instanceof, in, delete, ?. (optional chaining), ?? (nullish coalescing), ** (exponentiation), >>>, &&=, ||=, ??=
- Loops: for, for...of, for...in, for await...of, while, labeled break/continue
- Modules: relative imports, Node.js built-in modules, npm packages (uuid, lodash, zod adapters), Go packages via `go:` prefix, export default, re-exports
- Type mapping: number→float64, string→string, boolean→bool, T[]→[]T, T|null→*T, Map<K,V>→map[K]V, Promise<T>→*promise.Promise[T], Class→struct+methods, conditional/mapped/intersection types resolved via checker
- Go interop: `go:` prefix imports any Go stdlib/third-party package, multi-return destructuring (`const [resp, err] = http.Get(url)`), auto go.mod for third-party modules
- Type generation: `ramune typegen go:fmt go:net/http` generates .d.ts with full function signatures, interfaces, and type mappings
- Limitations: no decorators, no generators/yield, no Symbol/Proxy, all numbers float64
## Core Library API
- [Runtime (engine_jsc.go)](https://github.com/i2y/ramune/blob/main/engine_jsc.go): New(), Close(), Eval(), Exec(), EvalAsync(), NewObject(), NewArray(), NewUint8Array(), RegisterFunc(), GlobalObject(), dispatch(), Wake()
- [Value (value_jsc.go)](https://github.com/i2y/ramune/blob/main/value_jsc.go): String(), Float64(), Bool(), Bytes(), Attr(), SetAttr(), Call(), Keys(), Len(), Index(), Has(), Delete(), ToMap(), ToSlice(), IsArray(), IsFunction(), Close()
- [JSFunc (jsfunc_jsc.go)](https://github.com/i2y/ramune/blob/main/jsfunc_jsc.go): Wraps JS function references passed to GoFunc callbacks; Call(args...) invokes the function, Close() releases the reference
- [Typed Registration (register.go)](https://github.com/i2y/ramune/blob/main/register.go): Register[F]() — generics-based typed Go function registration (supports *JSFunc parameters)
- [Struct Binding (bind.go)](https://github.com/i2y/ramune/blob/main/bind.go): Bind() — expose Go structs as JS objects with getters/setters/methods
- [Plugin System (module.go)](https://github.com/i2y/ramune/blob/main/module.go): Module, WithModule(), LoadModule(), NativeModuleFromFuncs() — custom require() modules and reflection-based native module creation
- [Native Instance (native_instance.go)](https://github.com/i2y/ramune/blob/main/native_instance.go): Per-type callback registry for struct→JS conversion with live getter/setter properties and methods
- [Type Conversion (convert_jsc.go)](https://github.com/i2y/ramune/blob/main/convert_jsc.go): Go↔JS conversion for bool, numbers, strings, nil, map[string]any, []any, []byte (Uint8Array), structs (live binding), *promise.Promise[T] (→JS Promise), *JSFunc (→JS function)
- [Error Handling (errors.go)](https://github.com/i2y/ramune/blob/main/errors.go): JSError with Message and Stack trace, ErrAlreadyClosed, ErrNilValue
- [GC Config (types.go)](https://github.com/i2y/ramune/blob/main/types.go): WithGC(GCConfig) — GCInterval, GCPercent for JSC GC tuning
- [Permissions (permissions.go)](https://github.com/i2y/ramune/blob/main/permissions.go): WithPermissions() — read/write/net/env/run access control
- [RuntimePool (pool.go)](https://github.com/i2y/ramune/blob/main/pool.go): NewPool(n) for multi-core parallel JS execution with HTTP dispatch
- [Workers Subpackage (workers/)](https://github.com/i2y/ramune/tree/main/workers): `workers.Register(rt, file, src, opts...)` returns an `http.Handler` for Cloudflare-Workers-style ES-module handlers. `workers.Prepare` + `workers.AttachPrepared` share one typescript-go transpile across N runtimes. `ctx.waitUntil(promise)` holds the executor post-response up to `WithWaitUntilTimeout`. `WithSQLite(path)` installs a D1-style subset env.DB (`prepare`/`bind`/`all`/`first`/`run`/`exec`; no `batch`/`raw`) and a Workers-KV-like env.KV; `WithKVBackend` / `WithDBBackend` accept user-supplied `KVBackend` / `DBBackend` implementations (Redis, Postgres, in-memory...). `workers.d.ts` declares `Env`, `WorkersHandler`, `ExecutionContext`, `D1Database`, `KVNamespace`. `LoadRamuneTOML` / `ApplyRamuneTOML` parse the declarative `[dependencies]` / `[permissions]` / `[[kv_namespaces]]` schema.
- [Custom env Bindings (workers/BINDINGS.md)](https://github.com/i2y/ramune/blob/main/workers/BINDINGS.md): Pattern for adding any `env.FOO` — `env.QUEUE` (NATS / Kafka / Redis Streams), `env.R2` (S3 / minio), `env.EMAIL` (SMTP / SendGrid), `env.AI` (OpenAI / Anthropic), `env.DURABLE` (per-key singleton actors) — in a few lines of Go. Three pieces: (1) `rt.RegisterFunc("__env_foo_op", ...)` Go callback, (2) `WithExtraEnvJS` JS facade that assigns `env.FOO`, (3) optional TypeScript `interface Env { FOO: ... }` augmentation. The IIFE composition pattern on `globalThis.__extraEnvBindings` lets multiple packages stack bindings without collisions. Runnable example: [`examples/workers/custom-binding/`](https://github.com/i2y/ramune/tree/main/examples/workers/custom-binding).
## Event Loop & Async
- [Event Loop (eventloop.go)](https://github.com/i2y/ramune/blob/main/eventloop.go): Tick(), RunEventLoop(), RunEventLoopFor(), EvalAsync(), Wake() — channel-driven, zero-latency event delivery
- [Fetch (fetch.go)](https://github.com/i2y/ramune/blob/main/fetch.go): globalThis.fetch backed by Go net/http
- [Async Spawn (asyncspawn.go)](https://github.com/i2y/ramune/blob/main/asyncspawn.go): child_process.spawn with goroutine-backed I/O, channel-driven event delivery
- [Async FS (asyncfs.go)](https://github.com/i2y/ramune/blob/main/asyncfs.go): Real async fs.readFile/writeFile/stat/readdir via goroutines
- [Async Net (asyncnet.go)](https://github.com/i2y/ramune/blob/main/asyncnet.go): TCP/TLS client sockets via goroutines, channel-driven delivery
- [FS Watch (fswatch.go)](https://github.com/i2y/ramune/blob/main/fswatch.go): fs.watch() via fsnotify, integrated with event loop
- [Worker Threads (worker.go)](https://github.com/i2y/ramune/blob/main/worker.go): worker_threads with independent JSC contexts
## Web Platform APIs
- [Web Streams (webstreams.go)](https://github.com/i2y/ramune/blob/main/webstreams.go): ReadableStream, WritableStream, TransformStream with pipeTo/pipeThrough/tee/async iterator
- [Web Crypto (webcrypto.go)](https://github.com/i2y/ramune/blob/main/webcrypto.go): crypto.subtle — digest, sign/verify, encrypt/decrypt, importKey/exportKey, deriveBits/deriveKey, getRandomValues, randomUUID
- Blob, File, FormData, Headers, Request, Response (with ReadableStream body)
- performance.now/mark/measure, structuredClone, AbortController, TextEncoder/TextDecoder, URL/URLSearchParams, navigator, WebSocket (server-side)
## Terminal UI (Ramune.tui)
- [Ramune.tui (tui.go)](https://github.com/i2y/ramune/blob/main/tui.go): TUI module backed by Bubbletea + Lipgloss + bubbles + glamour, authored in TSX. Elm-style `init` / `update` / `view`; `Ramune.tui.run({init,update,view})` for a local TTY, `Ramune.tui.serveSSH({addr,program})` for the same program served via charmbracelet/wish (per-connection isolated session).
- Components: Box / Stack / Row (block layout via lipgloss JoinVertical/JoinHorizontal with align/valign/gap), List, Input, Textarea, Table, Form (huh-style), Markdown (glamour-rendered), Spinner, Progress, Viewport, Tabs, Help, Filepicker, Paginator, Stopwatch, Timer.
- Cmd dispatch: Cmd.every(ms, msg) for tick-driven re-render, Cmd.quit, Cmd.cancelEvery. Chord-aware keymap (multi-key sequences like `g g`, `d d`).
- Headless test harness: `Ramune.tui.test(program)` drives keys, returns frame snapshots; golden-tests `view()` output without a real TTY.
- Lives in `github.com/i2y/ramune/tui` (subpackage). The CLI binary auto-imports it; Go library embedders skip it by simply not importing the subpackage (keeps Bubbletea, Lipgloss, glamour, bubbles, wish SSH server out of their go.mod, ~7 MB smaller binary, ~6 ms faster startup). To enable in an embedded runtime: `tui.Install(rt)` after `ramune.New`.
- Examples: `examples/tui-{clock,counter,todo,pomodoro,survey,themes,ssh,issues}/`, plus `examples/hybrid-tui/` for AOT-extractable view() functions.
## Ramune APIs & Bun Compatibility
- [Ramune/Bun APIs (buncompat.go)](https://github.com/i2y/ramune/blob/main/buncompat.go): Ramune.serve() (HTTP server), Ramune.file(), Ramune.write(), Ramune.password, Ramune.sleep(), Ramune.hash(), Ramune.plugin() (onLoad filters, virtual modules), Request/Response with ReadableStream body. Bun.* available as alias. Works with Hono.
- [WebSocket (websocket.go)](https://github.com/i2y/ramune/blob/main/websocket.go): WebSocket server for Ramune.serve()
- [SQLite (sqlite.go)](https://github.com/i2y/ramune/blob/main/sqlite.go): bun:sqlite — pure Go SQLite via modernc.org/sqlite
## Node.js Compatibility
- [NodeCompat (nodecompat.go)](https://github.com/i2y/ramune/blob/main/nodecompat.go): fs (90%, async + sync + watch), path (100%), crypto (85% + crypto.subtle), child_process (80%), stream (85%, class extends, asyncIterator, backpressure, cork/uncork), zlib (75%, gzip/deflate/brotli), os (85%), events (85%), http/https (80%), http2 (75%, trailers, multiplexing), net/tls (70%, incl. net.createServer), Buffer (90%), url (80%), assert (80%), util (80%, types/promisify/format/debuglog), readline (70%), dns (basic), worker_threads (80%, SharedArrayBuffer, Atomics.waitAsync), vm (70%), querystring (80%), timers/promises (70%), perf_hooks (basic), process (85%, signals/exit/env/tty), tty (70%, isatty/WriteStream), dgram (70%, UDP), async_hooks (basic AsyncLocalStorage), module (createRequire, file-based require with ESM-to-CJS)
- [npm Bundling (bundle.go)](https://github.com/i2y/ramune/blob/main/bundle.go): Dependencies() fetches from npm registry and bundles via esbuild (no npm/bun CLI required). Subpath imports supported (e.g., "react-dom/server"). PreloadJS() injects polyfills before bundles
- [Package Registry (internal/registry/)](https://github.com/i2y/ramune/blob/main/internal/registry/): npm registry client, semver resolution, lockfile (ramune.lock)
- [VM Module (vm_jsc.go)](https://github.com/i2y/ramune/blob/main/vm_jsc.go): vm.createContext, runInContext, runInNewContext, Script — isolated JSC contexts
## Benchmarks
### JSC backend (default)
| Test | Ramune | Bun | Node.js |
|------|--------|-----|---------|
| Hello World | 17.7 ms | 7.7 ms | 19.6 ms |
| Fibonacci(35) | 53.5 ms | 44.6 ms | 71.6 ms |
| JSON 10K | 20.5 ms | 10.0 ms | 24.6 ms |
| HTTP req/s (single) | 90.5 K | 111 K | 89.8 K |
### qjswasm backend (`-tags qjswasm`)
Multi-Runtime Pool scaling (JSON handler, Apple M4 Max, wrk):
| Workers | req/s | Scaling |
|---------|-------|---------|
| 1 | 2,348 | 1.0x |
| 2 | 4,666 | 1.99x |
| 3 | 6,782 | 2.89x |
| 4 | 9,152 | 3.90x |
| 6 | 13,435 | 5.72x |
Monotonic out to 6 workers and still linear. QuickJS-NG on wazero sidesteps the global-allocator contention that required a forked libc for the previous modernc backend.
### goja backend (`-tags goja`)
Multi-Runtime Pool scaling (JSON handler, Apple M4 Max, wrk):
| Workers | req/s | Scaling |
|---------|-------|---------|
| 1 | 3,518 | 1.0x |
| 2 | 5,833 | 1.66x |
| 3 | 7,404 | 2.10x |
| 4 | 8,374 | 2.38x |
| 6 | 10,173 | 2.89x |
Faster than qjswasm at 1-3 workers (lower setup cost); qjswasm pulls ahead at 4+ workers.
Multi-runtime pool (JSC): 1 worker 40K → 3 workers 58K req/s (JSON handler).
vs Go runtimes (fib(35)): Ramune (JSC+JIT) 35ms vs Ramune (qjswasm) 1,987ms vs Ramune (goja) 2,400ms vs otto 26,413ms.
Run `make bench` to reproduce.
## Agent Skills
Ramune ships with an embedded [Agent Skill](https://agentskills.io/) that teaches AI agents how to use Ramune. Install via `ramune skills install` (writes to both `~/.agents/skills/` and `.claude/skills/`).
- [ramune](https://github.com/i2y/ramune/blob/main/cmd/ramune/skills/ramune/SKILL.md): Use Ramune — CLI commands, Go library API, HTTP server, multi-core pool, Node.js compatibility
## Platform Support
- macOS: JavaScriptCore built-in, JIT via `ramune setup-jit`
- Linux: libjavascriptcoregtk (4.0/4.1/6.0)
- Windows / FreeBSD: qjswasm backend (`-tags qjswasm`) or goja backend (`-tags goja`), no system deps
- [CI](https://github.com/i2y/ramune/blob/main/.github/workflows/ci.yml): macOS + Ubuntu 22.04/24.04