magus v0.3.0 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
8 min read

ts

The ts spell wires a TypeScript project's tooling into a magusfile, forking each tool through the project package manager (pnpm exec). It is an opaque spell: preflight composes the individual checks into one target.

Runtime name: ts (source spells/typescript/)

Version probe: node --version

Provides: dist/**

Opaque: yes (its outputs are not enumerable, so magus treats the whole workspace as the cache input).

Passing arguments to ops

Every op is invoked as ts["<op>"](ctx, opts?). The first argument is the target's context, which is what carries the execution environment; the optional options map shapes the command itself:

Key Type Description Source
args [str] Extra arguments appended to the resolved command. Omit it and a bare ts["<op>"]() forwards magus run <target> -- <extra> to the tool automatically; pass it to set the arguments explicitly, which replaces that passthrough. source
stdin str Data written to the command's standard input. source

Working directory and environment are NOT options: they ride the context, as ts["<op>"](ctx.withCwd("sub")) and ts["<op>"](ctx.withEnv({"CGO_ENABLED": "0"})). Only the context reaches the cache key, so an option-table cwd or env would change what the tool did while the key said otherwise - passing either as an option is an error.

Charms (the :charm suffix, e.g. magus run test:rw) are orthogonal: they patch the base argv, while these options add to it. See Charms.

biome-check

biome-check is biome's lint/analyze pass (eslint's role, if your project chose Biome over eslint+prettier - the magusfile decides which composes into lint, not this spell). --write and --reporter=github verified against the current Biome CLI docs (biomejs.dev/reference/cli).

Command: pnpm exec biome check .

gha

Inserts --reporter=github.

JSON Patch
[
  {
    "op": "add",
    "path": "/3",
    "value": "--reporter=github"
  }
]

rw

Inserts --write.

JSON Patch
[
  {
    "op": "add",
    "path": "/3",
    "value": "--write"
  }
]

Example

// biome-check lints the project through Biome (pnpm exec biome check), the
// spell's alternative to eslint - the magusfile picks one, not both.
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun lint(ctx: magus\Context, args: [str]) > void {
    ts["biome-check"](ctx);
}

biome-format

biome-format is biome's formatter (prettier's role). Unlike prettier/ruffFormat, biome format has no --check flag to drop: it is read-only by default (reports differences, writes nothing) and --write applies them, so rw ADDS a flag instead of removing one.

Command: pnpm exec biome format .

rw

Inserts --write.

JSON Patch
[
  {
    "op": "add",
    "path": "/3",
    "value": "--write"
  }
]

Example

// biome-format checks formatting through Biome (pnpm exec biome format); the
// rw charm (magus run format:rw) applies --write. The spell's alternative to
// prettier - the magusfile picks one, not both.
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun format(ctx: magus\Context, args: [str]) > void {
    ts["biome-format"](ctx);
}

dev-server

dev-server runs the project's package.json "dev" script via the package manager - framework-neutral (Vite, Next, webpack-dev-server, ...). No readiness probe is declared: the port and startup signal vary by framework, so guessing one would be wrong more often than right (readiness is optional - see services.md). A magusfile that needs to block on readiness for its specific dev server can declare its own service op instead.

Command: pnpm run dev

Example

// dev-server runs the project's package.json dev script (pnpm run dev) as a
// supervised background process when reached via magus.needs, or foreground
// when run directly.
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun serve(ctx: magus\Context, args: [str]) > void {
    ts["dev-server"](ctx);
}

eslint

eslint has no built-in "github" formatter (unlike ruff's --output-format=github); "unix" is the built-in, no-extra-devDependency formatter closest to a CI-friendly, one-line-per-problem shape for annotation/regex parsing.

Command: pnpm exec eslint .

gha

Inserts --format=unix.

JSON Patch
[
  {
    "op": "add",
    "path": "/2",
    "value": "--format=unix"
  }
]

rw

Inserts --fix.

JSON Patch
[
  {
    "op": "add",
    "path": "/2",
    "value": "--fix"
  }
]

Example

// eslint lints the project through the package manager (pnpm exec eslint).
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun lint(ctx: magus\Context, args: [str]) > void {
    ts["eslint"](ctx);
}

preflight

preflight is a no-op marker op (no command).

Command: none; this op composes the spell's other ops (see the intro).

Example

// preflight composes the tsc/eslint/prettier/vitest checks into one opaque target.
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun preflight(ctx: magus\Context, args: [str]) > void {
    ts["preflight"](ctx);
}

prettier

Command: pnpm exec prettier --check .

rw

Replaces --check with --write.

JSON Patch
[
  {
    "op": "replace",
    "path": "/2",
    "value": "--write"
  }
]

Example

// prettier checks formatting; the rw charm (magus run format:rw) rewrites in place.
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun format(ctx: magus\Context, args: [str]) > void {
    ts["prettier"](ctx);
}

scip

scip is the reserved op that runs the TypeScript SCIP indexer for the knowledge graph. The indexer is a PATH binary (install it with mise, not as a project dep), so the op forks it directly. magus injects MAGUS_SYMBOL_INDEX with the cache destination, so the index never lands in the tree; scip-typescript writes there via --output. Run through sh so the env var expands.

Command: sh -c scip-typescript index --output "$MAGUS_SYMBOL_INDEX"

tsc

Command: pnpm exec tsc

Example

// tsc is static analysis, so it composes into the canonical `lint` target
// (alongside eslint) rather than a bespoke `typecheck` target. `magus run lint`
// forks `pnpm exec tsc`.
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun lint(ctx: magus\Context, args: [str]) > void {
    ts["tsc"](ctx);
}

tsc-build

tsc-build uses TypeScript's project-references incremental build mode (works even without declared references, via its own .tsbuildinfo cache), emitting per tsconfig outDir - see mgs_listProvidedGlobs.

Command: pnpm exec tsc --build

Example

// tsc-build compiles the project via TypeScript's project-references
// incremental build mode (pnpm exec tsc --build).
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun build(ctx: magus\Context, args: [str]) > void {
    ts["tsc-build"](ctx);
}

tsc-clean

tsc-clean mirrors tsc-build's project-references mode: --clean removes the declared outputs and the incremental .tsbuildinfo cache.

Command: pnpm exec tsc --build --clean

Example

// tsc-clean removes tsc-build's declared outputs and its incremental
// .tsbuildinfo cache (pnpm exec tsc --build --clean).
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun clean(ctx: magus\Context, args: [str]) > void {
    ts["tsc-clean"](ctx);
}

vitest

Command: pnpm exec vitest run

gha

Appends --reporter=github-actions.

JSON Patch
[
  {
    "op": "add",
    "path": "/-",
    "value": "--reporter=github-actions"
  }
]

Example

// vitest runs the test suite; the gha charm annotates failures in GitHub Actions.
import "magus";
import "magus/spell/ts";

magus\project({ "spells": [ts] });

export fun test(ctx: magus\Context, args: [str]) > void {
    ts["vitest"](ctx);
}
auto-generatedtsspelltypescriptnodeeslintvitesttools
Last updated (15118091)
Earlier changes on this page (2)

Full history ↗ · Blame source ↗

Glossary

Workspace

The magus root directory that owns a set of projects and shared config; the unit magus operates over. See workspace.

Project

A directory magus recognizes as a unit of work (it has a magusfile); the unit of caching, scheduling, and dependency tracking. See workspace.

Magusfile

The magusfile.buzz that declares a project's targets (as export funs) and binds its spells. See targets.

Target

A named operation (build, test, ...) you invoke with magus run <target>; it may compose a spell's tool-native operations and depend on other targets. See targets.

Spell

A language/runtime adapter (e.g. go, md) that maps generic targets onto a toolchain's real commands. See spells.

Charm

An execution modifier attached with : (lint:rw) that changes how a target runs, not which one; the built-in rw flips a check-only target to mutate in place, and ci always strips it. See charms.

Ward

A coded diagnostic that inspects a resolved op and nudges or blocks an anti-pattern before it runs. See wards.

Buzz

The language magusfiles are written in (the .buzz engine). See engines.

Cache

The content-addressed store magus consults before running a target, so unchanged work is skipped. See cache.

Service

A long-running or shared process magus manages across runs, distinct from a one-shot target. See services.

CI

An ordinary magusfile-defined target you compose yourself with magus\needs - magus does not hardcode its stages. Magus.RunCI treats it specially only in that it strips the rw charm, it is the anchor magus affected ci keys off, and a selected scope with no project declaring it is a load error rather than a silent no-op. See targets.

Knowledge graph

The queryable graph of a workspace's spells, targets, docs, and code relationships; query it with magus query/explain/path. See knowledge.

Conventions

Placeholders

Angle brackets mark a value you replace with your own - never type the brackets:

magus run <target>
magus completion <shell>    # e.g. bash, zsh, fish

<target>, <path>, <shell>, <name> and the like are stand-ins, not literal text.