Global Scripts

A file ending .axon.ts is a global script. It is an ordinary TypeScript program that happens to know how to boot agents, and it lives wherever you put it — a repo root, a scratch directory, ~/bin.

// ~/scripts/standup.axon.ts
import { Fleet } from "@axon/core"

const { barry } = await Fleet({ barry: "~/agents/barry" })

const summary = await barry.request("summarise yesterday's commits")
console.log(summary.text)
axon run standup.axon.ts

No agent folder, no axon.config.ts, no project. The script names what it needs.

Imports, not globals

A script inside an agent gets axon, args, and its tools as globals, because the runtime that injected them was already running when the script started. A global script has no such runtime — it is the thing that starts one — so it imports what it uses:

import { Axon, Fleet } from "@axon/core"

That one line is the whole ceremony, and it buys real things: your editor types it with no generation step, no tsconfig has to be in the right place, and the file works when you move it. Magic globals need a project to hang off. A global script has no project by design.

The two script kinds

Both are first-class. They differ on who owns the agent's lifetime:

// src/scripts/review.ts — inside an agent
const content = await axon.tools.fs.readFile(file)
const prompt  = await axon.prompt("review", { file, content })

const { stream } = axon.stream({ prompt })

for await (const entry of stream) {
    if (entry.type === "text") process.stdout.write(entry.content)
}
// review.axon.ts — a global script
import { Axon } from "@axon/core"

const { axon: barry } = await Axon("../barry")

const content = await barry.tools.fs.readFile(file)
const prompt  = await barry.prompt("review", { file, content })

const { stream } = barry.stream({ prompt })

for await (const entry of stream) {
    if (entry.type === "text") process.stdout.write(entry.content)
}

The bodies are identical. The only difference is where the handle came from — ambient in one, constructed in the other. Everything you know about axon transfers directly; barry is the same handle with a name you chose.

Arguments

Global scripts take arguments from the command line like any program:

axon run review.axon.ts --file src/index.ts
const file = process.argv[...]

There is no defineArgs here. That global belongs to agent-scoped scripts, where the runtime parses arguments before invoking the script and the TUI palette builds a form from the declaration. A global script is started by a shell, so it reads process.argv like a shell program does.

Running one

axon run standup.axon.ts              # by path
axon run ./deploy/nightly.axon.ts     # anywhere on disk

The CLI runs the file, waits for it, and shuts down every agent the script booted before exiting — including when the script throws. See Lifecycle.

What runs it, and under what policy

A global script runs in your shell, as you, with your permissions. It is not sandboxed and it is not policy-checked — the same trust model as any node or bun script you run on your own machine.

The agents it boots are a different matter. Each one enforces its own declared policy on its own tool calls, in its own capsule. Booting an agent does not widen what that agent may do, and a script cannot grant an agent a permission its policy withholds.

So the rule is the ordinary one: run a global script you would run any script. The agents inside it stay bounded regardless.

When a script should become an agent

A global script is deliberately disposable. It has no identity, no version, no address, and nowhere to live but the path you saved it at — which is right for a tool you wrote this afternoon.

When it earns its keep — when a teammate wants it, or it should run nightly, or it needs to be reachable over HTTP — it becomes a manager agent. The script body moves into src/scripts/ mostly unchanged.


Next: Composing a Fleet — booting several at once.