SourceLoom builds LoomPackaging the Loom CLI

Part VIII, Chapter 10

Part VIII, Chapter 10: Packaging the Loom CLI

Package: packages/loom/

Language: JSON

Raw source

Packaging the Loom CLI

The @athrio/loom package ships to npm as a single self-contained file. Vite bundles the CLI program, the language server, and Effect into dist/main.js and adds a Node shebang, so the file runs directly under Node and, since Bun is Node-compatible, under Bun as well. The published package is therefore pure JavaScript with no runtime dependencies — every library it needs is already inside the bundle. Any Node package manager installs it — npm, pnpm, yarn, or Bun.

The manifest

The files field restricts the published package to the dist directory, and the bin field maps the loom command to the bundle. The bundle inlines every dependency, so all dependencies belong in the devDependencies field. That holds for tree-sitter-loom as well: the build reads the grammar's sources into the bundle for loom helix and loom nvim to compile, so the package itself never ships. Loom Design is not among them. The two products carry different licences. The Quadrivium Academy foundation licenses this package under MIT, and Athrio Media OÜ licenses Design under terms of its own, so loom design runs Design's binary and this package neither imports nor builds it.

The typecheck script reads the source without writing anything — --noEmit, because the shared configuration sets an output directory that a check has no use for, and compiled copies of the tests left there are found twice by the test runner. It is the script this package went without, and the cost showed. Vite strips types rather than checking them, so main.ts shipped for months with an identifier that resolved to nothing — a failure message reaching for a variable that had gone out of scope, which would have thrown a ReferenceError on the one path it was written for. A type checker reads the whole file whether or not a path runs.

The compile script runs compile.ts, which turns the bundle into the standalone executable, build/loom, for the machine it runs on, with the grammar library and TypeScript inside it. It writes outside dist, so the executable never lands in the npm package. TypeScript is a development dependency for that reason: the compile packs the workspace's TypeScript 6 into the executable. The release compiles one executable on each platform from the same bundle.

The build script bundles the tangled source files committed to the repository. Tangling the corpus is a separate step, performed with the published loom CLI rather than the in-progress source — using an unverified tangler to tangle the corpus that produces it would be circular. The prepack script re-bundles automatically before each publish. The bun publish command rewrites the workspace:* specifier for @athrio/loom-lang — Bun's protocol for local package references — into the real published version number.

{{ version = ${version} }} {{ effect = ${effect} }}

JSON
{
  "name": "@athrio/loom",
  "version": "::[version]",
  "description": "Tangle Loom literate sources into real source files.",
  "license": "MIT",
  "type": "module",
  "bin": {
    "loom": "dist/main.js"
  },
  "files": [
    "dist"
  ],
  "engines": {
    "node": ">=20",
    "bun": ">=1.2"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/athrio-com/loom.git",
    "directory": "packages/loom"
  },
  "publishConfig": {
    "access": "public"
  },
  "scripts": {
    "build": "vite build",
    "compile": "bun compile.ts",
    "typecheck": "tsc -p tsconfig.json --noEmit",
    "test": "bun test",
    "prepack": "bun run build"
  },
  "devDependencies": {
    "@athrio/loom-config": "workspace:*",
    "@athrio/loom-lang": "workspace:*",
    "@athrio/loom-lang-services": "workspace:*",
    "@effect/platform-node": "::[effect]",
    "effect": "::[effect]",
    "tree-sitter-loom": "workspace:*",
    "typescript": "^6.0.3",
    "vite": "^8.0.12"
  }
}

The TypeScript config

The tsconfig.json extends the workspace-root tsconfig.base.json and covers the src directory. Vite produces the dist bundle, so the configuration file is a development tool only and never ships with the published package.

JSON
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "out",
    "rootDir": "src"
  },
  "include": ["src"]
}

The licence

npm ships a package's LICENSE whatever the files field says, and until now this package shipped none — an installer had the SPDX expression in the manifest and no text to read. The file below is that text.

It carries the MIT licence in full. Loom was dual-licensed under MIT and Apache-2.0 for a while, inheriting a Rust convention rather than a decision; the Apache branch bought a patent grant nobody was obliged to take, and dropping it left one licence to read and one string to keep consistent.

It also says what is not here. Athrio sells Loom Design under a licence of its own, and a reader who finds a permissive text here should not conclude it reaches that product too.

license
MIT License

Copyright (c) 2026 Quadrivium Academy Sihtasutus and Loom contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Loom