/local-disk: nothing mounted
Leave the key blank and this runs on a shared demo gateway that supplies the key for you. It is rate limited per user against a small daily budget and serves MiMo only, so if it stops responding the day's budget is likely spent. Add your own key from openrouter.ai/keys to use any model on your own quota.
Running via the demo gateway · xiaomi/mimo-v2.5-pro · YOLO — type in the terminal.
The vanilla Claude Code binary hosted in a webpage, hardwired to a notebook environment. This is not endorsed by Anthropic in any way. Use your existing Anthropic account through /login with token copying, or use OpenRouter API endpoints. Defaults to our OpenRouter demo endpoint, restricted to MiMo models only.
Connected to Claude Code
⏳Waiting for activity…
🎙️
File Sync
Directory: — (not set)
Modules: 50 syncable
Notebook\u2192Files: Waiting for directory...
Files\u2192Notebook: Waiting for directory...
Watched Variables
Live values of variables being observed by Claude Code.
Claude Code Pairing
Bridges a lopecode notebook to Claude Code via WebSocket.
Claude Code CLI ←MCP→ Channel Server ←WS→ This Module (browser)
Cell groups (in dependency order):
- UI —
cc_chat(main interface),cc_watch_table(variable inspector) - State —
cc_config,cc_notebook_id,cc_activity,cc_status,cc_messages,cc_watches,cc_module,voiceEnabled - Module lookup —
cc_find_moduleresolves module names viaruntime.mains - Serialization —
cc_serialize_value(safe value→string for transport) - Variable watcher —
cc_watchersobserves variables, debounces & sends updates - Command handlers —
cc_handle_*(one per MCP tool) - Command dispatch —
cc_command_handlersroutes action→handler - WebSocket —
cc_wsmanages connect/pair/auto-reconnect and message dispatch - Side effects —
cc_change_forwarderstreams cell edits,cc_voiceoptional speech I/O - Imports —
currentModules,exportToHTML,compile,history, runtime-sdk helpers
State cells
Reactive Inputs.input() cells holding connection state. These are the shared mutable atoms that UI and WebSocket cells read/write.
cc_config = Object {port: 8787, host: "127.0.0.1"}
cc_notebook_id = "https://tomlarkworthy.github.io/lopebooks/notebooks/Caged_Code.html#view=S100(@tomlarkworthy/claude-code-browser,@tomlarkworthy/claude-code-pairing,@tomlarkworthy/exporter-3,@tomlarkworthy/module-map)"
Module lookup & serialization
cc_find_module resolves a module name (e.g. "@tomlarkworthy/exporter-3") to a runtime Module object by polling viewof currentModules.value at call time (not reactively). cc_serialize_value safely converts any runtime value to a truncated string for transport.
cc_find_module = ƒ(runtime, moduleName)
cc_serialize_value = ƒ(value, maxLen)
Variable watcher
Subscribes to Observable variables via observe(), debounces updates (1s), and forwards changes to Claude Code over the WebSocket. Also maintains the cc_watches table UI.
cc_watchers = Object {watchVariable: ƒ(runtime, name, moduleName), unwatchVariable: ƒ(name, moduleName), unwatchAll: ƒ(), setSend: ƒ(fn)}
Command handlers
One handler per MCP tool. Each receives a cmd object and the Observable runtime, returns {ok, result} or {ok:false, error}. Handlers: get-variable, define-variable, define-cell, delete-variable, list-variables, list-cells, run-tests, create-module, delete-module, eval, fork, watch, unwatch.
cc_handle_get_variable = ƒ(cmd, runtime)
cc_handle_define_variable = ƒ(cmd, runtime)
cc_handle_define_cell = ƒ(cmd, runtime)
cc_handle_delete_variable = ƒ(cmd, runtime)
cc_handle_list_variables = ƒ(cmd, runtime)
cc_handle_list_cells = ƒ(cmd, runtime)
cc_handle_run_tests = ƒ(cmd, runtime)
cc_handle_create_module = ƒ(cmd, runtime)
cc_handle_delete_module = ƒ(cmd, runtime)
cc_handle_eval = ƒ(cmd, runtime)
cc_handle_fork = ƒ(cmd, runtimeArg)
cc_handle_watch = ƒ(cmd, runtime)
cc_handle_unwatch = ƒ(cmd, runtime)
Command dispatch & WebSocket
cc_command_handlers maps action strings to handler functions. cc_ws manages the WebSocket lifecycle: connect, pair with token, dispatch incoming messages (commands, replies, tool-activity), and auto-reconnect from the URL hash cc= param or sessionStorage.
RuntimeError: fileSyncTools is not defined
cc_handle_call_tool = async ƒ(cmd)
cc_command_handlers = ƒ(cmd)
cc_ws = Object {connect: ƒ(token), paired: false, ws: null}
Side effects
cc_change_forwarder polls the local-change-history and streams new cell edits to Claude Code. cc_voice provides optional speech recognition input and TTS output for hands-free pairing.
cc_change_forwarder = "change forwarder active"
cc_voice = "voice: disabled"
cc_handle_delete_cell = ƒ(cmd, runtime)
cc_handle_update_cell = ƒ(cmd, runtime)
cc_handle_export_module = ƒ(cmd, runtime)
import {hash} from "d/57d79353bac56631@44"
Exporter 3
Serialize literate computational notebooks with their dependancies into single downloadable files. Double click to open locally. No server required, works in a file:// context for simplicity.
- File-first representation. The Observable Runtime and common builtins like
Inputs,htl,highlight,_(lodash) andmarkdownare bundled for offline operation. - Recursive and self-sustaining, the exporter is implemented in userspace and can be forked again after exporting.
- Fast, single file notebooks open fast!
- Moldable, the file format is uncompressed, readable, editable with a text editor, and diffable by Git.
- Runtime-as-the-source-of-truth, format derived from the live Obervable Runtime representation.
- No sandboxing, the notebook is rendered without an iframe
- Custom bootloaders, for control over the standard library
- Userspace, implementation is a normal notebook.
Exporter improves upon exporter 2 by refactoring out Observable Javascript concepts, it works on the low level reprentation directly.
Usage Guide
To put the exporter in one of your notebooks, first import the UI builder.
import {exporter, forkAnchor, exportAnchor } from '@tomlarkworthy/exporter'
Then call the builder to make the UI. You don't need to pass any options, but the options is where you can customise the output format.
exporter({
handler: (action, state) => {}, // Optional UI click handler
style: undefined,// customer reference to a style DOM node or a string to insert as a style block
output: (out) => {}, // hook to get result of exporting
notebook_url: undefined,// hardcode the default notebook_url
})
If you want to export without a UI, use the function exportToHTML, see the example
import {exportToHTML } from '@tomlarkworthy/exporter'
async function exportToHTML({
mains = new Map(), // (name -> module) Map of main modules
runtime = _runtime,
options = {} // Object, export options, e.g. head, title
} = {})
You can also just use inline anchor tags: forkAnchor() or downloadAnchor()
Lopecode HTML Format Specification
Inline http responses
The HTML file contains <script> blocks that hold content to serve internal network requests locally.
<script id="d/c2dae147641e012a@46"
type="text/plain"
data-encoding="base64+gzip"
data-mime="application/javascript"
>
...inline text or base64 string
</script>
Requests to the URL matching the id are served locally, this includes import, fetch, XMLHttpRequest and <script> src attribute.
Main script
The main script loads the Observable runtime with no standard library and loads a bootloader module. The bootloader is responsible for setting up the standard library and loading the first real modules, which it discovers by reading the bootconf.json. @tomlarkworthy/bootloader is the default which comes with d3, Plot, md, htl and lodash local.
Persisted Hash URL
To help carry state across an export, the URL hash parameter is remembered in the bootconf.json and set automatically when opening the file if one is not present. URLs are limited in size, ff you need to move large amount of data across an export, use a local FileAttachment instead.
Themes
Themes are sourced from NotebookKit. A theme is fetched once from Github once when switching themes, but integrated into the export, and reused locally on subsequent exports. This keeps the bundle small, and you only need a network connection if switching to obtain the new CSS source files.
disk_svg = ƒ(fill)
Implementation
exporter = ƒ(…)
copyTextToClipboard = async ƒ(text)
htmlToConsoleSnippet = ƒ(…)
exportAnchor = ƒ(…)
forkAnchor = ƒ(…)
downloadAnchor = ƒ(…)
actionHandler = async ƒ(action, state, options, feedback_callback)
exportToHTML = async ƒ(…)
getSourceModule = async ƒ(state)
createShowable = ƒ(…)
reportValidity = ƒ(view, invalidation)
top120List = Array(120) ["@jashkenas/inputs", "@d3/gallery", "@d3/learn-d3", "@makio135/creative-coding", "@observablehq/module-require-debugger", "@d3/zoomable-sunburst", "@observablehq/plot", "@tmcw/enigma-machine", "@d3/force-directed-graph-component", "@d3/bar-chart-race-explained", "@observablehq/data-wrangler", "@d3/collapsible-tree", "@sxywu/introduction-to-svg-and-d3-js", "@d3/sankey-component", "@d3/zoomable-circle-packing", "@d3/selection-join", "@bstaats/graph-visualization-introduction", "@d3/color-legend", "@uwdata/introducing-arquero", "@mbostock/10-years-of-open-source-visualization", …]
notebook_title = "@tomlarkworthy/save-in-place"
utf8ToBase64 = ƒ(str)
Single File Notebook Generator Flow
TRACE_MODULE = "@tomlarkworthy/lopepage"
buildModuleNames = ƒ(…)
isModuleVar = ƒ(v)
isDynamicVar = ƒ(v)
isImportBridged = ƒ(v)
findImportedName3 = async ƒ(v)
Object {module_definitions: Map(46), unresolved: Array(7)}
Map(52) {Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, …}
excluded_module_names = Array(5) ["TBD", "error", "builtin", "main", "bootloader"]
findImports = ƒ(cells)
getFileAttachments = ƒ(module)
streamingModuleOrder = ƒ(mainNames, specByName)
Generate a report on the sizes of components
Module Source Generator
exportModuleJS
Serialize a single module from the live runtime to a .js module source string. Unlike module_specs (which serializes all modules as part of the full HTML export pipeline), exportModuleJS works on-demand against the live runtime with no task dependency.
import {exportModuleJS} from "@tomlarkworthy/exporter-3"
const {source, fileAttachments} = await exportModuleJS(moduleId, {runtime, moduleNamesFn})
Parameters
moduleId— module name string, e.g."@tomlarkworthy/flow-queue"options.runtime— Observable runtime instance (default:_runtime)options.moduleNamesFn— function to build module name map (default:buildModuleNames)
Returns {source, fileAttachments}
source— full.jsmodule source withexport default function define(runtime, observer)fileAttachments—Map<name, {url, mimeType}>of the module's file attachments
exportModuleJS = async ƒ(…)
generate_module_source = async ƒ(…)
generate_definitions = ƒ(variables)
generate_define = async ƒ(…)
isLiveImport = ƒ(v)
variableToDefinition = ƒ(v)
restoreCanonicalImports = ƒ(source)
variableToDefine = async ƒ(…)
Assemble
es_module_shims = "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"
inspector_gz = "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"
inlineModule = ƒ(…)
inlineGzipModule = ƒ(id, source)
normalize = ƒ(url)
test_networking_script_is_streaming = "ok"
test_lopebook_main_at_top_with_sentinel = "ok"
test_lopebook_agent_orientation = "ok"
test_streaming_order_prioritizes_mains = "ok"
test_streaming_order_runtime = "ok"
isNotebook = ƒ(id)
networking_script = ` const normalize = url => url.replace(/^(?:https:\\/\\/api\\.observablehq\\.com)?\\/(.*?)\\.js(?:\\?.*)?$/, '$1').replace(/^(d\\/[a-f0-9]{16})@\\d+$/, '$1'); const isNotebook = id => /^(@[^/]+\\/[^/]+|d\\/[a-f0-9]{16})$/.test(id); // --- streaming gate --- // main runs from the TOP of the document, before the whole file has finished downloading, so a // block a boot import needs may not have streamed in yet. __waitForId blocks until the block's // <script> is fully parsed (el.nextSibling is non-null only after its </scr\\ipt> is seen), // bounded by window.__lopeStreaming, which flips to false once the document is fully parsed (so a // genuinely-absent id resolves to a 404 rather than hanging). // // The wait is event-driven (MutationObserver + DOMContentLoaded/load), NOT a setTimeout poll: // Safari throttles timers in background/unfocused tabs, and a fork opens via window.open into a // tab that is often not foregrounded, so a poll loop stalls there (works in a foreground file:// // download but hangs in a backgrounded blob: fork). MutationObserver fires on the parser's node // insertions regardless of timer throttling. The end-of-document sentinel stays as a redundant // fast-path; DOMContentLoaded/load clear the flag even if that inline script never runs. window.__lopeStreaming = true; function __endStreaming() { window.__lopeStreaming = false; } if (document.readyState === "loading") {Show 259 truncated lines
agent_orientation = `<!-- LOPECODE NOTEBOOK — orientation for AI agents. A self-contained Observable-runtime notebook: every JavaScript module, asset and config is a top-level <script type="text/plain" id="..."> block, resolved at runtime. No build step and no server — edit a block, reload the file. Do not read this file whole, it is megabytes, and do not grep it: block bodies contain source that looks like block headers, so grep over-reports. Unpack it with an HTML parser, which tracks script raw text correctly, and work from the extracted files: python3 -c " import sys, os, base64, gzip from html.parser import HTMLParser src, out = sys.argv[1], sys.argv[2] class P(HTMLParser): def __init__(self): super().__init__(convert_charrefs=False); self.a = None def handle_starttag(self, t, attrs): d = dict(attrs) self.a = d if t == 'script' and 'id' in d else None def handle_data(self, data):Show 23 truncated lines
lopebook = ƒ(…)
lopemodule = async ƒ(module)
escapeScriptTags = ƒ(str)
arrayBufferToBase64 = async ƒ(buffer)
Global Output
Utils
getCompactISODate = ƒ()
Additional Tests
diskDataUrl = "data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgd2lkdGg9IjUwcHgiIGhlaWdodD0iNTBweCIgdmlld0JveD0iMCAwIDY0IDY0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IGhlaWdodD0iNCIgd2lkdGg9IjQiIHg9IjIwIiB5PSI1MCI+PC9yZWN0PjxyZWN0IGhlaWdodD0iNCIgd2lkdGg9IjE2IiB4PSIyOCIgeT0iNTAiPjwvcmVjdD48cGF0aCBkPSJNMzIsMzhhOCw4LDAsMSwwLTgtOEE4LjAwOSw4LjAwOSwwLDAsMCwzMiwzOFptMC0xMmE0LDQsMCwxLDEtNCw0QTQsNCwwLDAsMSwzMiwyNloiPjwvcGF0aD48cGF0aCBkPSJNNiw2Mkg1OGEyLDIsMCwwLDAsMi0yVjE1YTIsMiwwLDAsMC0uNTg2LTEuNDE0bC0xMS0xMUEyLDIsMCwwLDAsNDcsMkg2QTIsMiwwLDAsMCw0LDRWNjBBMiwyLDAsMCwwLDYsNjJabTQyLTRIMTZWNDZINDhaTTE2LDZIMzF2NGg0VjZoNHY4SDE2Wk04LDZoNFYxNmEyLDIsMCwwLDAsMiwySDQxYTIsMiwwLDAsMCwyLTJWNmgzLjE3Mkw1NiwxNS44MjlWNThINTJWNDRhMiwyLDAsMCwwLTItMkgxNGEyLDIsMCwwLDAtMiwyVjU4SDhaIj48L3BhdGg+PC9zdmc+"
()
Module map
Figures out the import structure of a runtime, just pass a runtime to the function moduleMap to get a summary of the modules. Returns a map indexed by a Module object to a record.
module -> {
type: "notebook import" | "module variable",
name: <module name>,
module: <module object ref>
dependsOn: [<module name>*],
dependedBy: [<module name>*],
}
moduleMap = async ƒ(…)
currentModules
sync_modules = Map(52) {Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, …}
Visualization
tipTitle = ƒ(…)
visualizeModules = ƒ(…)
Random helpers
tag = Symbol()
forcePeek = ƒ(…)
observe = ƒ(module, variable_name, observer)
Implementation
()
We resolve what we can using variables named with prefix module that hold module values. We forcePeek the variables to make them resolve, which forces loading of the modules.
module_definition_variables = Array(129) [Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, Variable, …]
modules = Array(53) [Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, Module, …]
bootloaded_mains = Map(7) {"@tomlarkworthy/save-in-place" => Module, "@tomlarkworthy/lopepage-2" => Module, "@tomlarkworthy/module-map" => Module, "@tomlarkworthy/claude-code-browser" => Module, "@tomlarkworthy/claude-code-pairing" => Module, "@tomlarkworthy/exporter-3" => Module, "@tomlarkworthy/annotate" => Module}
resolve_modules = Object {module_definitions: Map(46), unresolved: Array(7)}
modules imported via notebook imports do not have module variables, so they are trickier to figure out. We can sniff the page DOM to find the import expressions, and try to map them to the modules we could to resolve earlier
pageImportMatch = async ƒ(notebookImportVariables, modules)
notebookImportMatches = Map(0) {}
moduleTitle = async ƒ(module)
titles = Map(53) {Module => null, Module => "Bootloader - Notebook 1.0 stdlib", Module => "Save in place", Module => "Lopepage-2: Multi-notebook layout", Module => "Module map", Module => "Caged Code", Module => null, Module => "Exporter 3", Module => "Annotate", Module => "Plugin Registry", Module => "Runtime SDK", Module => "@observablehq/inspector@5.0.1", Module => "Inline editable md", Module => "jest-expect-standalone@24.0.2", Module => "Themes", Module => "DOM view", Module => "Bidirectional Observable JS <=> Runtime Toolchain", Module => "localStorageView: Non-invasive local persistance", Module => "Reversible attachment", Module => "Observable Runtime (v6)", …}
summary = Map(52) {Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, …}
submit_summary = undefined
Map(52) {Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, Module => Object, …}