Codync
A free, open-source 1:1 alternative to Grok Bot and Muse. Message Claude Code, Codex, Cursor and 40+ coding agents as persistent bots from your iPhone, Mac or Linux desktop. Group chats, threads, appr
Try Bynk in your browser: write a little Bynk, run it, and share the link.
Developer toolsJavaScript · TypeScriptGitHub @bynk-langOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The Bynk playground: write, compile and run Bynk in the browser
Taken from the repository README
Loading the full README.
Read the full README ↗The in-browser REPL for Bynk (ADR 0140). Type Bynk, press Run, see it execute — with no install and no server: the compiler runs in the browser as wasm, and the compiled JavaScript runs in a sandbox.
A fully static, client-side app, served from two origins:
playground.bynk-lang.dev — the app: the editor + the bynk_compile wasm.sandbox.bynk-lang.dev — the execution document: a sandboxed <iframe>
wrapping a Web Worker. Untrusted code runs only here (the safety boundary).The compiler is not built here. The app runs a pinned Bynk release (BYNK_VERSION):
each release publishes its browser artefacts (the wasm compiler, its glue and types, the
grammar wasm and highlight query) as bynk-web-<tag>.tar.gz, and
scripts/fetch-assets.sh stages that tarball in src/vendor/. The pin moves when the
Bynk canary has checked the playground against a newer release.
| Path | What |
|---|---|
src/app.ts | The app: editor (CodeMirror 6, with Reset to original for an edited example or shared snippet), compile, diagnostics, run, the compiled JS (a tab, or a column beside the editor on a screen 1200px or wider), deep-link, Share, examples picker, Learn links (the Book, install, source), and the "What runs here" note (the entry handler, the 3 s limit, which capabilities work in the browser), which each limit message links to. Format (the compiler's bynk_format, the same house style as the CLI and language server; Shift+Alt+F). |
src/examples.ts | The examples gallery — curated, runnable in-process snippets; the header picker loads them. Listed in reading order under GROUPS ("Start here" first), each linked to the tour step that teaches the same idea (tour), and back. test/examples.test.mjs compiles and runs every one. |
test/e2e/ | Browser tests with no extra dependencies: build for two localhost ports, serve with a fake share service, drive headless Chrome over DevTools. Covers the run round trip, tabs, gallery, tour, share and fork, restore and Recent, theme and phone layout. workers.test.mjs runs the real app and sandbox Workers under npx [email protected] dev (built from the repo's wrangler.*.jsonc, with only the share service faked) and checks the sandbox redirect, the SHARE binding and the SHARE_LIMIT rate limit in a browser. |
worker/app.mjs | The app Worker: sends /api/* to the share service over the SHARE binding (503 when unbound), refuses the sandbox's files (/sandbox, sandbox.js: untrusted code never runs on the app origin), serves everything else from the assets. |
worker/sandbox.mjs | The sandbox Worker: serves only the execution document (sandbox.html, sandbox.js) and redirects every other request, / included, to the app origin. |
test/style.test.mjs | Every example and tour source is in the house style (bynk_format returns each unchanged), so Format on one changes nothing. The sources are indented with tabs, as bynk fmt writes them; the editor shows a tab as two columns (TAB_SIZE in src/app.ts). |
src/gallery.ts | The searchable examples dialog (cards with a blurb and code peek). |
fonts/ | The editor's code font: JetBrainsMono Nerd Font, trimmed woff2 with its ligatures (calt) kept, under the SIL OFL. See fonts/README.md. |
src/store.ts | Per-browser memory: the autosaved draft, the last 10 snippets you ran and the tour steps you have passed (localStorage, every access guarded). test/store.test.mjs covers the recent-list logic. |
src/tour.ts | The guided tour: nine small programs to fix, each with a check, then a "What next" card (examples, the Book's next tutorial, install). test/tour.test.mjs proves every starter fails its check and every solution passes. |
src/entry.ts | Which emitted module the sandbox runs: compose.js for a program with capabilities, the context module's own __makeSurface for one with none (the compiler emits no compose.js then). |
src/sandbox.ts | The execution document: links the JS graph to blob-URL modules, runs it in a Worker under a wall-clock timeout, posts results back. |
| live diagnostics | A CodeMirror linter (in src/app.ts) calls bynk_analyze (debounced, on-type) → inline squiggles + gutter. Non-bailing — type errors in a context show live, not only on Run. |
src/args.ts | Arguments for a run (#82): when no service handler takes zero arguments, the first service's on call(…) signature, read from the source (the wasm API doesn't report it), drives an Arguments row above the results. String, Int, Float, Bool and refinements of them can be entered (the sandbox checks a refinement with the compiled T.of); links carry the values as ?args=. test/args.test.mjs covers the scanner and the conversion. |
src/reference.ts | The standard library reference (#85, Learn → Standard library): built-in types and their functions, the bynk capabilities and their operations, and the first-party modules' functions, harvested from the running compiler's own completion (bynk_complete), so it matches the release. test/reference.test.mjs checks it against the staged compiler. |
src/diagnostics.ts | A diagnostic row's help: its code links to that code's section of the Book's diagnostic index, and the common newcomer mistakes (a missing given, a match missing a case, a type mismatch, a broken refinement) carry a "Try:" hint. test/diagnostics.test.mjs triggers each hinted code in the staged compiler. |
| hover + completion | src/app.ts calls bynk_hover (the inferred type at the cursor) and bynk_complete (context-aware candidates). |
src/positions.ts | UTF-16 (CodeMirror) ↔ UTF-8 byte (bynk-wasm) offset mapping, applied at every wasm call; unit-tested by test/positions.test.mjs. |
src/deeplink.ts | The shared snippet format: #base64url(deflate-raw(utf8(source))). |
src/highlight.ts | CodeMirror Bynk highlighting (stream-based; see Highlighting below). |
src/shared.ts | Origin config + the postMessage protocol. |
BYNK_VERSION | The Bynk release the app is built from. The page shows the release it bundles (the staged tarball's VERSION, else this pin) at the foot of the Learn menu, linking to its notes. |
scripts/fetch-assets.sh | Download a release's bynk-web-<tag>.tar.gz, verify it against the release's SHA256SUMS, and unpack it into src/vendor/. |
build.mjs / serve.mjs | esbuild build into dist/, minified (BYNK_MINIFY=0 to skip), with the app bundle, wasm and fonts content-hashed under static/ and cached for a year by _headers, which also carries the page's Content-Security-Policy / a two-port local static server that applies the same _headers. |
wrangler.app.jsonc / wrangler.sandbox.jsonc | The two Workers that serve dist/, one per origin. |
share/ | The short-link share service, written in Bynk (below). |
The share sheet offers an <iframe> for the snippet. It points at the same link with ?embed=1, a compact view that runs the snippet and offers Open in playground. An embed never reads or writes the visitor's own draft, recents, tour progress or hints.
npm install
npm run fetch:assets # the release in BYNK_VERSION; or pass a tag: -- v0.403.3
npm test # unit tests + every gallery example through the staged compiler
npm run test:e2e # the flows in a real browser (needs Chrome; CHROME=/path/to/chrome)
npm run build # esbuild → dist/ (production origins by default)
To try a compiler build before it is released, point BYNK_RELEASE_BASE_URL at a
file:// directory holding a bynk-web-<tag>.tar.gz (from bynk-lang/bynk's
scripts/package-web-assets.sh) and a SHA256SUMS.
The app and sandbox must be different origins. Build for localhost and serve on two ports:
BYNK_APP_ORIGIN=http://localhost:8080 BYNK_SANDBOX_ORIGIN=http://localhost:8081 node build.mjs
node serve.mjs # app → http://localhost:8080 , sandbox → http://localhost:8081
Open http://localhost:8080, then check:
consumes bynk.cloudflare { … } program shows not runnable in-browser (the platform lock).?s=<id> link from the share service, or a self-contained #… link if the service is unavailable; reloading that URL restores the source.fn that never returns) is terminated after the wall-clock budget.The compile, the emitted graph running, and the deep-link round-trip are verified in Node (
npm test); the browser DOM/iframe/Worker flow is verified by the steps above.
.github/workflows/ci.yml runs on every push and pull request:
test.yml): stage the pinned release, type-check, npm test, bundle.bynk-ci (format, check, test) on share/ at the pinned release.main it deploys both Workers with
wrangler deploy; anywhere else (and on main before the secrets exist) it does a
--dry-run of both, so a broken Worker config fails before it merges.Security note — the app and the sandbox MUST be two distinct origins. The sandbox origin is the safety boundary defined by ADR 0140: untrusted snippet code executes only on the opaque sandbox origin and can never reach the app origin's storage. Never collapse them into one Worker or one domain — doing so dissolves the boundary.
Add the repository secrets CLOUDFLARE_API_TOKEN (scoped to Account → Workers Scripts → Edit and, for the custom domains, Zone → Workers Routes → Edit and Zone → DNS → Edit on bynk-lang.dev) and CLOUDFLARE_ACCOUNT_ID.
Push to main, or run CI by hand (Actions → CI → Run workflow on main). The first deploy creates both Workers:
playground → playground.bynk-lang.workers.dev, custom domain playground.bynk-lang.dev;playground-sandbox → playground-sandbox.bynk-lang.workers.dev, custom domain sandbox.bynk-lang.dev.Wrangler attaches the custom domains (and creates their DNS records) because the bynk-lang.dev zone is in the same account.
Once both origins serve, re-run the checks in "Verify locally" against https://playground.bynk-lang.dev. Confirm the sandbox iframe loads from https://sandbox.bynk-lang.dev — that is how you know the origin split is real and not just configured.
The playground is enrolled in the bynk-lang org canary (canary/README.md) as kind app. On every Bynk release (and weekly), .github/workflows/bynk-canary.yml:
test.yml at that release: the unit tests, every gallery example through that release's wasm compiler, and the bundle;canary.yml, which runs bynk-ci on share/ at the same release and opens, updates or closes the canary issue here;BYNK_VERSION, opens a pull request moving the pin (closing any older one); CI runs on it, and merging it deploys the new compiler.The org does not let GITHUB_TOKEN open pull requests, so step 3 uses a GitHub App with Contents and Pull requests: Read and write, installed on this repository, through the secrets BUMP_APP_ID (its client id) and BUMP_APP_KEY (a private key). Until they are set, the canary still runs and reports, and the bump step warns and skips.
A manual run: Actions → Bynk canary → Run workflow, with a version or latest.
share/) — written in BynkShort share links (?s=<id>) are backed by a Bynk program (share/)
compiled by bynkc to a Cloudflare Worker + KV — dogfooding: the playground that
compiles Bynk has a backend written in Bynk. POST /api/snippets stores the source
under a random id; GET /api/snippets/:id returns it. The Source refined type
bounds the body, so oversized/empty payloads are rejected at the boundary (400).
Stored snippets expire 30 days after creation (Kv.putTtl,
bynk-lang/bynk#398) — a share link is
for showing someone a program, not permanent hosting, so retention is bounded rather
than unbounded KV storage/cost.
The browser calls it same-origin (/api/* on the app origin) — Bynk's from http
emits no CORS headers, so cross-origin would not work; same-origin routing avoids CORS
entirely. If the service is unavailable, Share falls back to the self-contained
#hash link, so the playground works without it.
Build + run + verify locally:
# Compile the Bynk service to a JS Worker:
bynkc compile share --target workers --platform cloudflare --emit js -o /tmp/share-js
# Run it (set wrangler.toml main=index.js + a dummy local KV id):
cd /tmp/share-js/workers/snippets && npx wrangler@4 dev --port 8799 --local
# serve.mjs proxies /api/* → http://localhost:8799 (override with BYNK_SHARE_WORKER),
# so the app at :8080 reaches it same-origin.
curl -X POST :8080/api/snippets -d '{"source":"context x.y\n"}' # → {"id":"…"}
CI deploys the service with bynk-deploy (the deploy-share job in ci.yml): bynk deploy compiles share/, creates its KV namespace (snippets) and uploads the Worker snippets. The app Worker then reaches it over a service binding (SHARE): worker/app.mjs runs first only for /api/* and forwards those calls, so the browser still talks to the app origin and CORS never comes into it. The binding is added (scripts/with-share-binding.mjs) only in a run that has just deployed the share service, because Cloudflare rejects a binding to a Worker that does not exist. Without it /api/* answers 503 and Share falls back to the self-contained #… link, so the app never depends on the service being up.
First deploy (once), done locally. bynk deploy refuses, in CI, to create a KV namespace, because Cloudflare mints the id and a CI job that cannot commit it would leave an orphan nobody could find again. So the first deploy is yours:
Give your Cloudflare API token Account → Workers Scripts → Edit and Workers KV Storage → Edit.
Create the namespace and record it. bynk deploy cannot do this step itself yet: it runs wrangler kv namespace create --json, a flag wrangler does not have (bynk-lang/bynk#2428). Until that is fixed, from share/:
wrangler kv namespace create snippets # note the id it prints
printf 'version = 1\n\n[environments.default.kv.snippets]\nid = "<id>"\n' > bynk.deploy.lock
Deploy the Worker; with the namespace recorded the driver only uploads it, and adds the Worker to the lock:
CLOUDFLARE_API_TOKEN=… CLOUDFLARE_ACCOUNT_ID=… bynk deploy
Commit share/bynk.deploy.lock (it holds the namespace id and no secrets) and merge.
From then on every push to main redeploys the service, and the app deploys with the SHARE binding. Until the lock is committed the job only prints the plan (bynk deploy --dry-run), on pull requests too.
Things to know: the Worker is named snippets (the Bynk context's name) in your account; POST /api/snippets is open to anyone who can reach it and writes to KV, bounded by the 64 KiB Source refinement and the 30-day expiry, and rate limited by the app Worker to 10 creates a minute per client address (the SHARE_LIMIT binding; over the limit answers 429 and the app falls back to the self-contained link; reads are not limited). The Worker has no public address of its own: Wrangler turns its workers.dev route and preview URLs on at every bynk deploy (the generated wrangler.toml sets no workers_dev, and bynk.toml has no key for it), so CI turns both off again straight after each deploy and fails if they stay on. A bynk deploy run by hand leaves them on until the next CI deploy, so follow it with the same call (the "Turn off the share service's workers.dev route" step in .github/workflows/ci.yml).
Highlighting is web-tree-sitter: the tree-sitter-bynk grammar wasm from the
release tarball, parsed and queried (highlights.scm, also from the tarball) in
src/tshighlight.ts, with captures rendered as CodeMirror decorations — the same
grammar the editor and CLI use. The runtime tree-sitter.wasm comes from this app's
web-tree-sitter dependency.
The editor starts on the lightweight CodeMirror stream highlighter
(src/highlight.ts) and swaps to web-tree-sitter once its wasm loads (via a
Compartment). If the grammar wasm is absent or fails to load, the stream highlighter
stays.
The playground is built to need as little as possible from the people who use it.
?s= link stores the program with the share service, hosted on
Cloudflare, for 30 days, after which it is deleted. Anyone with the link can read it
in that time. It is stored under a random id and nothing else: no account, name or
address goes with it. The self-contained #… link stores nothing at all: the program
travels in the link itself, and browsers do not send that part of a link to the server.Licensed under either of Apache License, Version 2.0 or MIT license at your option.