COMPILER

amo eject

The exit is part of the design. One command compiles your app a final time, copies the runtime into your project as readable source files, and rewrites every @amojs.dev/core import to a relative path. What remains is a vanilla JavaScript project you own completely — the framework you can uninstall.

Run it

terminal
$ npx amo eject src dist
amo eject — 2 compiled, 10 copied, 9 runtime files → dist (runtime: amo-runtime/)
runtime taken from node_modules/@amojs.dev/core/src
no bare "@amojs.dev/core" imports remain — deleting amo changes nothing.

The last line is a guarantee the repository's test suite enforces: it executes ejected output and asserts zero bare-specifier imports, so module resolution never touches node_modules again.

What changes in your code

Only the import lines. Templates are already compiled to direct DOM code — the same output amo build produces — so the rest of the file is untouched.

before
import { signal, html, mount } from '@amojs.dev/core';
after
import { signal, mount } from '../amo-runtime/runtime.js';
import { tpl as _$t, bindChild as _$child, bindEvent as _$event } from "../amo-runtime/compiled.js";

The runtime you receive

Core's own source files, verbatim — a few hundred lines of plain JavaScript with JSDoc: the signal graph, the bindings, mount, each, and the parser only if something still uses html`` at runtime. Readable is the point; it is the code you would have written, so you can keep writing it. The runtime is resolved from the ejected project's own installed @amojs.dev/core when there is one, so the output keeps the exact version the code was written against; the CLI prints where it came from.

The router comes along

If the app imports @amojs.dev/router, eject copies it into amo-runtime/router/ and rewrites those imports too. An ejected app keeps routing with both packages deleted.

Why it can exist

Most frameworks cannot offer this because their compiled output calls into a runtime that is itself the framework — a virtual DOM, a scheduler, a component system. AmoJS compiles to the DOM operations a person would write by hand, within 10% of hand-written bytes, so handing over the small runtime beneath them is the whole job. Every design decision that keeps that true — no component API, no Proxy, no file format, no global delegation — is also what keeps eject honest.