ArcMoon 1.1.0

Start

Language

Reference

Nothing matches “”.

↑↓ move Enter open Esc close

Reference

CLI

arcm commands, build flags, what the build writes, and messages.

Commands

arcm and arcmoon are the same command. In a project install, put npx in front: npx arcm build pages. See Installation.

arcm build

Builds .arcm files into HTML. Give it a folder or one file:

arcm build pages              # every .arcm file directly inside pages/
arcm build pages/index.arcm   # one file
✓ pages/about.arcm → dist/about.html  13 B
✓ pages/index.arcm → dist/index.html  5.0 kB  (script 4.8 kB)
  203 ms
  • Each line shows the file, the HTML it wrote, its size, and its script size when it has runtime code.
  • A folder builds only the files directly inside it, not the folders below.
  • HTML goes to outDir from the config (./dist by default).

-o: another output folder. Use it for subfolders, so their pages keep their place:

arcm build pages/blog -o dist/blog   # pages/blog/post.arcm → dist/blog/post.html

For a whole site, keep the commands in package.json and run npm run build:

package.json
{
  "scripts": {
    "build": "arcm build pages && arcm build pages/blog -o dist/blog"
  }
}

-p: print instead of writing. A quick look at one page's HTML; no file is written:

arcm build pages/about.arcm -p
<p>About</p>

--dev: for debugging. The JavaScript stays readable, with a source map, so browser errors point at your .arcm lines:

arcm build pages --dev

arcm init

Creates arcmoon.config.js in the current folder, with the common options:

arcm init
✓ Created /my-site/arcmoon.config.js

arcm show config

Prints the config ArcMoon loaded, or where it loaded it from. Use it when an option seems to be ignored:

arcm show config
{
  "importAliases": { "@": "./src" },
  "removeComments": true,
  "timeout": 5000,
  "bundle": [],
  "outDir": "./dist"
}

arcm show --path-config
/my-site/arcmoon.config.js

Run from another folder, it says no arcmoon.config.js in …: the config is only read from where you run arcm.

arcm audit

Shows what the code in a page would do, for your files and for each template it uses, without running anything. Here a page uses a header from a folder outside the project:

arcm audit pages/index.arcm
pages/index.arcm
  Your files (1):
    (no code)

  Template "../theme" (⚠ not trusted):
    fetch      api.example.com
    env        API_KEY

The template calls api.example.com and reads the API_KEY environment variable while building. See Templates and trust.

arcm trust

Trusts the templates a page or folder uses, after you have reviewed them. Until then, arcm build stops with the report and runs nothing:

arcm trust pages/index.arcm
✓ Trusted "../theme" (sha256-27197bd1888d…)
    fetch      api.example.com
    env        API_KEY

Saved to arcmoon.trust.json. If a template changes, ArcMoon asks again.

--list shows what you trust, and when:

arcm trust --list
../theme  (trusted 2026-10-14T08:56:36.358Z)

arcm untrust

Stops trusting templates, by the names trust --list shows:

arcm untrust ../theme
✓ Untrusted "../theme"

arcm --lex and --parse

For debugging ArcMoon itself, or a file that won't build: --lex prints the tokens, --parse the syntax tree, as JSON. For this file:

[p = class: "x"]Hi[end]
arcm --lex tiny.arcm (types and values)
OPEN_BRACKET "["   IDENTIFIER "p"   EQUAL "="   KEY "class"   COLON ":"   STRING "x"   CLOSE_BRACKET "]"
TEXT "Hi"   OPEN_BRACKET "["   END_KEYWORD "end"   CLOSE_BRACKET "]"   EOF ""
arcm --parse tiny.arcm (shortened)
[
  {
    "type": "Block",
    "id": "p",
    "props": { "class": "x" },
    "isSelfClosing": false,
    "body": [{ "type": "Text", "text": "Hi" }]
  }
]

The full output also has each token's and block's place in the file.

arcm -v and -h

arcm -v      # 1.0.0
arcm -h      # every command, with short examples

arcmoon.config.js

arcm init creates the config in the current folder. ArcMoon reads it only from the folder you run arcm in, never from a parent folder. arcm show config prints what it found.

arcmoon.config.js
export default {
  importAliases: { "@": "./src" },
  bundle: ["canvas-confetti"],
  outDir: "./dist"
};

Every option, with its default, an example and when to use it, is on Configuration.

What the build writes

By default each page is one HTML file, with its JavaScript and CSS inside. With externalScripts and externalStyles, they move to files:

dist/
index.html              <link rel="stylesheet" href="./assets/index-ECRIFUJ2.css">
                        <script type="module" src="./assets/index-QZCVOMHP.js">
about.html
assets/
  index-ECRIFUJ2.css    the page's CSS
  index-QZCVOMHP.js     the page's own JavaScript
  about-2BJV5KWY.js
  chunks/
    chunk-E7XXX4QS.js   code shared by pages, downloaded once
  • The letters in a file name change when its content changes, so browsers can cache files safely.
  • Code used by several pages, like arcmoon/reactive, goes to chunks/ once.
  • Each page's CSS file holds all of that page's CSS.
  • Pages with no JavaScript get no script.
  • Files the last build wrote and this one doesn't need are removed (ArcMoon keeps a list in .arcmoon-files.json). Your own files in assets/ are left alone.

Templates and trust

${ }$ code runs on your computer with full access. So .arcm files you didn't write, from an npm package or a folder outside your project, are never run until you trust them. ArcMoon shows what they would do instead, and runs nothing:

⚠ Template "../external/blog" is not trusted. It would:
    import     node:fs (read/write)
    fetch      api.example.com
    env        API_KEY
  Review it, then run "arcmoon trust ../external/blog".
  Nothing was run.
  • arcm audit pages prints the same report for your files and every template, without building.
  • arcm trust pages trusts the templates those pages use. Trust is saved in arcmoon.trust.json, with a hash of each template.
  • If a trusted template changes, ArcMoon asks again.
  • Trust means you looked; it doesn't make code safe. Only trust what you have read.

Messages

Errors show the message, the place, and the line with a ^ under the spot. Warnings take one line:

⚠ ok.arcm:2:7  ${ title }$ is undefined (prop "title" wasn't passed)
✗ unquoted value AKZB for prop "id"; write "AKZB" (only true / false and numbers may be unquoted)
page.arcm:2:15

  1 | [main]
> 2 |   [User = id: AKZB !]
    |                ^
  3 | [end]

Colors turn off by themselves in CI, pipes and files, or with NO_COLOR.