Caged Code

12 min read Original article ↗

/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.

VariableModuleValueUpdated
hashmain"#view=S100(@tomlarkworthy/claude-code-browser,@tomlarkworthy/claude-code-pairing,@tomlarkworthy/exporter-3,@tomlarkworthy/module-map)"10:21:32 PM
currentModulesmainMap(52) { Module {} => Object {name: "bootloader", title: "Bootloader", module: Module {}, dependsOn: Array(0) [], dependedBy: Array(0) []}, Module {} => Object {name: "builtin", title: "Standard l10:21:32 PM
historymainArray(2) [Object {t: 1786652491590, op: "del", source: "runtime", pid: "_59vo1b", module: "unknown", provenance: null, _name: null}, Object {t: 1786652491610, op: "del", source: "runtime", pid: "_59vo10:21:32 PM

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):

  1. UIcc_chat (main interface), cc_watch_table (variable inspector)
  2. Statecc_config, cc_notebook_id, cc_activity, cc_status, cc_messages, cc_watches, cc_module, voiceEnabled
  3. Module lookupcc_find_module resolves module names via runtime.mains
  4. Serializationcc_serialize_value (safe value→string for transport)
  5. Variable watchercc_watchers observes variables, debounces & sends updates
  6. Command handlerscc_handle_* (one per MCP tool)
  7. Command dispatchcc_command_handlers routes action→handler
  8. WebSocketcc_ws manages connect/pair/auto-reconnect and message dispatch
  9. Side effectscc_change_forwarder streams cell edits, cc_voice optional speech I/O
  10. ImportscurrentModules, 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) and markdown are 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 .js module source with export default function define(runtime, observer)
  • fileAttachmentsMap<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

@tomlarkworthy/jszip-3-10-1@tomlarkworthy/lightning-fs-4-6-0@tomlarkworthy/isomorphic-git-1-30-1@tomlarkworthy/local-change-history@tomlarkworthy/save-in-place@tomlarkworthy/robocoop-5-tools@tomlarkworthy/plugin-registry@tomlarkworthy/command-palette@tomlarkworthy/themes@tomlarkworthy/lopepage-2@tomlarkworthy/lopepage-urls@tomlarkworthy/visualizer@tomlarkworthy/summarizejs@tomlarkworthy/local-storage-view@mbostock/safe-local-storage@tomlarkworthy/inspector@tomlarkworthy/annotate@tomlarkworthy/exporter-3@tomlarkworthy/stream-operators@tomlarkworthy/reversible-attachment@tomlarkworthy/view@tomlarkworthy/dom-view@tomlarkworthy/editable-md@tomlarkworthy/prosemirror@tomlarkworthy/jest-expect-standalone@tomlarkworthy/observable-runtime@tomlarkworthy/acorn-8-11-3@tomlarkworthy/observablejs-toolchain@tomlarkworthy/robocoop-5-corebuiltinbootloader@tomlarkworthy/cell-map@tomlarkworthy/tests@tomlarkworthy/observable-runtime-v6@tomlarkworthy/modules@tomlarkworthy/observablehq-lezer@tomlarkworthy/cells-to-clipboard@tomlarkworthy/codemirror-6-v2@tomlarkworthy/editor-5d/57d79353bac56631@44@tomlarkworthy/dataflow-templating@tomlarkworthy/flow-queue@tomlarkworthy/spectral-layout@tomlarkworthy/module-map@tomlarkworthy/invoke-variable@tomlarkworthy/claude-code-browser@tomlarkworthy/fileattachments@tomlarkworthy/file-sync@tomlarkworthy/markdown-wiki@mootari/access-runtime@tomlarkworthy/runtime-sdk@tomlarkworthy/claude-code-pairing

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, …}

nametitlemoduledependsOndependedBytypevariable
bootloaderBootloader[object Object]
builtinStandard library[object Object]
@tomlarkworthy/save-in-placeSave in place[object Object]@tomlarkworthy/exporter-3,@tomlarkworthy/plugin-registry,@tomlarkworthy/runtime-sdk
@tomlarkworthy/lopepage-2Lopepage-2: Multi-notebook layout[object Object]@tomlarkworthy/plugin-registry,@tomlarkworthy/runtime-sdk,@tomlarkworthy/visualizer,@tomlarkworthy/modules,@tomlarkworthy/claude-code-pairing,@tomlarkworthy/command-palette,@tomlarkworthy/themes,@tomlarkworthy/local-change-history,@tomlarkworthy/lopepage-urls,@tomlarkworthy/editor-5,@tomlarkworthy/exporter-3
@tomlarkworthy/module-mapModule map[object Object]@tomlarkworthy/lopepage-urls,@tomlarkworthy/flow-queue,@tomlarkworthy/observablejs-toolchain,@tomlarkworthy/runtime-sdk,@tomlarkworthy/invoke-variable,@tomlarkworthy/spectral-layout@tomlarkworthy/claude-code-browser,@tomlarkworthy/claude-code-pairing,@tomlarkworthy/exporter-3,@tomlarkworthy/cell-map,@tomlarkworthy/file-sync,@tomlarkworthy/command-palette,@tomlarkworthy/spectral-layout,@tomlarkworthy/local-change-history,@tomlarkworthy/editor-5,@tomlarkworthy/testsmodule variablemodule @tomlarkworthy/module-map
@tomlarkworthy/claude-code-browserCaged Code[object Object]@tomlarkworthy/runtime-sdk,@tomlarkworthy/module-map,@tomlarkworthy/fileattachments,@tomlarkworthy/exporter-3,@tomlarkworthy/file-sync
@tomlarkworthy/claude-code-pairing[object Object]@tomlarkworthy/module-map,@tomlarkworthy/exporter-3,@tomlarkworthy/observablejs-toolchain,@tomlarkworthy/local-change-history,@tomlarkworthy/runtime-sdk,d/57d79353bac56631@44,@tomlarkworthy/summarizejs,@tomlarkworthy/file-sync@tomlarkworthy/lopepage-2module variablemodule @tomlarkworthy/claude-code-pairing
@tomlarkworthy/exporter-3Exporter 3[object Object]@tomlarkworthy/lopepage-urls,@tomlarkworthy/observable-runtime-v6,@tomlarkworthy/flow-queue,@tomlarkworthy/cell-map,@tomlarkworthy/observablejs-toolchain,@tomlarkworthy/view,@tomlarkworthy/reversible-attachment,@tomlarkworthy/local-storage-view,@tomlarkworthy/dom-view,@tomlarkworthy/module-map,@tomlarkworthy/runtime-sdk,@tomlarkworthy/jest-expect-standalone,@tomlarkworthy/themes@tomlarkworthy/save-in-place,@tomlarkworthy/lopepage-2,@tomlarkworthy/claude-code-browser,@tomlarkworthy/claude-code-pairing,@tomlarkworthy/editable-md,@tomlarkworthy/file-sync,@tomlarkworthy/local-change-historymodule variablemodule @tomlarkworthy/exporter-3
@tomlarkworthy/annotateAnnotate[object Object]@tomlarkworthy/plugin-registry,@tomlarkworthy/runtime-sdk,@tomlarkworthy/inspector,@tomlarkworthy/observablejs-toolchain,@tomlarkworthy/editable-md
@tomlarkworthy/plugin-registryPlugin Registry[object Object]@tomlarkworthy/save-in-place,@tomlarkworthy/lopepage-2,@tomlarkworthy/annotate,@tomlarkworthy/command-palette,@tomlarkworthy/robocoop-5-toolsmodule variablemodule @tomlarkworthy/plugin-registry
@tomlarkworthy/runtime-sdkRuntime SDK[object Object]@mootari/access-runtime@tomlarkworthy/save-in-place,@tomlarkworthy/lopepage-2,@tomlarkworthy/module-map,@tomlarkworthy/claude-code-browser,@tomlarkworthy/claude-code-pairing,@tomlarkworthy/exporter-3,@tomlarkworthy/annotate,@tomlarkworthy/editable-md,@tomlarkworthy/cell-map,@tomlarkworthy/fileattachments,@tomlarkworthy/lopepage-urls,@tomlarkworthy/file-sync,@tomlarkworthy/invoke-variable,@tomlarkworthy/visualizer,@tomlarkworthy/modules,@tomlarkworthy/local-change-history,@tomlarkworthy/editor-5,@tomlarkworthy/dataflow-templating,@tomlarkworthy/tests,@tomlarkworthy/markdown-wikimodule variablemodule @tomlarkworthy/runtime-sdk
@tomlarkworthy/inspector@observablehq/inspector@5.0.1[object Object]@tomlarkworthy/annotate,@tomlarkworthy/local-storage-view,@tomlarkworthy/summarizejs,@tomlarkworthy/visualizer,@tomlarkworthy/dataflow-templating,@tomlarkworthy/testsmodule variablemodule @tomlarkworthy/inspector
@tomlarkworthy/editable-mdInline editable md[object Object]@tomlarkworthy/exporter-3,@tomlarkworthy/runtime-sdk,@tomlarkworthy/observablejs-toolchain,@tomlarkworthy/prosemirror,@tomlarkworthy/jest-expect-standalone@tomlarkworthy/annotatemodule variablemodule @tomlarkworthy/editable-md
@tomlarkworthy/jest-expect-standalonejest-expect-standalone@24.0.2[object Object]@tomlarkworthy/exporter-3,@tomlarkworthy/editable-md,@tomlarkworthy/observablejs-toolchain,@tomlarkworthy/cell-mapmodule variablemodule @tomlarkworthy/jest-expect-standalone
@tomlarkworthy/themesThemes[object Object]@tomlarkworthy/lopepage-2,@tomlarkworthy/exporter-3,@tomlarkworthy/command-palettemodule variablemodule @tomlarkworthy/themes
@tomlarkworthy/dom-viewDOM view[object Object]@tomlarkworthy/exporter-3module variablemodule @tomlarkworthy/dom-view
@tomlarkworthy/observablejs-toolchainBidirectional Observable JS <=> Runtime Toolchain[object Object]@tomlarkworthy/tests,@tomlarkworthy/cell-map,@tomlarkworthy/acorn-8-11-3,@tomlarkworthy/jest-expect-standalone,@tomlarkworthy/observable-runtime@tomlarkworthy/module-map,@tomlarkworthy/claude-code-pairing,@tomlarkworthy/exporter-3,@tomlarkworthy/annotate,@tomlarkworthy/editable-md,@tomlarkworthy/cell-map,@tomlarkworthy/editor-5module variablemodule @tomlarkworthy/observablejs-toolchain
@tomlarkworthy/local-storage-viewlocalStorageView: Non-invasive local persistance[object Object]@mbostock/safe-local-storage,@tomlarkworthy/inspector@tomlarkworthy/exporter-3module variablemodule @tomlarkworthy/local-storage-view
@tomlarkworthy/reversible-attachmentReversible attachment[object Object]@tomlarkworthy/view@tomlarkworthy/exporter-3,@tomlarkworthy/editor-5module variablemodule @tomlarkworthy/reversible-attachment
@tomlarkworthy/observable-runtime-v6Observable Runtime (v6)[object Object]@tomlarkworthy/exporter-3,@tomlarkworthy/modulesmodule variablemodule @tomlarkworthy/observable-runtime-v6
@tomlarkworthy/flow-queueConvert cell computation to a Promise with cell flowQueue[object Object]@tomlarkworthy/module-map,@tomlarkworthy/exporter-3,@tomlarkworthy/editor-5module variablemodule @tomlarkworthy/flow-queue
@tomlarkworthy/summarizejsSummarizeJS[object Object]@tomlarkworthy/inspector@tomlarkworthy/claude-code-pairingmodule variablemodule @tomlarkworthy/summarizejs
@tomlarkworthy/cell-mapcellMap[object Object]@tomlarkworthy/lopepage-urls,@tomlarkworthy/module-map,@tomlarkworthy/runtime-sdk,@tomlarkworthy/jest-expect-standalone,@tomlarkworthy/tests,d/57d79353bac56631@44,@tomlarkworthy/observablejs-toolchain@tomlarkworthy/exporter-3,@tomlarkworthy/observablejs-toolchain,@tomlarkworthy/visualizer,@tomlarkworthy/command-palette,@tomlarkworthy/editor-5module variablemodule @tomlarkworthy/cell-map

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, …}