
Security News
Agent Baseline Publishes Security Reference Architecture for Software Factories
Agent Baseline’s new reference architecture shows how to secure software factories with four boundaries enforced outside the AI agent.
Filesystem-routed commands for local projects and user-global tools.
@async/cli turns directories into a CLI. A command like:
cli gh pull 123 --rebase
is routed to a directory, and the words that did not match become the script's arguments:
.cli/gh/pull/script.ts argv: ["123", "--rebase"]
No registry, no config file, no argument framework. One lookup rule covers
two trees: a repo-local .cli/ overlay that travels with the project, and a
user-global ~/.cli for your personal tools. Proven commands get promoted
from one to the other with a single command.
Docs map: this README is the guided tour. ROUTING.md is the
normative routing rules. API_SURFACE.md is the complete API
reference. SPEC.md is the design contract.
pnpm add -D @async/cli # per project
pnpm add -g @async/cli # or globally
Requires Node 24+. The package ships two identical binaries, cli and
async-cli, for setups where cli is taken.
# scaffold .cli/gh/pull/script.ts in this repo
cli --new gh pull
# it is immediately runnable (scaffolded overlays are auto-trusted)
cli gh pull 123 --rebase # script.ts gets ["123", "--rebase"]
# see what exists, and what would run
cli --list
cli --which gh pull
# promote it to your personal ~/.cli once it earns it
cli --mv gh pull --to root
Cloned a repo that ships its own .cli/? Commands are visible immediately
but refuse to run until you approve them once:
cli --list # inspection never needs trust
cli --trust # approve this repo's overlay, then run normally
The full rules with worked examples live in ROUTING.md. The short version:
.cli/
directory, nearest first, stopping at the Git root. Append ~/.cli last.script.*
wins; leftover words become the script's argv. -- stops word matching
early.help, lib, node_modules, hidden (.x), and underscore-prefixed
(_x) names never route, so helper code can sit next to scripts.Rule 2 is what makes overlays powerful: a repo can define .cli/gh/script.ts
and take over the whole gh ... namespace while you work in that repo, even
though your ~/.cli/gh/clone exists. That is deliberate — and it is exactly
why local overlays are trust-gated. cli --list marks anything shadowed,
cli --which shows what was hidden.
A command script is a plain Node ESM program — no SDK, no wrapper:
// cli: Open a pull request against main
// cli-cwd: project-root
const [id, ...rest] = process.argv.slice(2);
console.log(`pulling ${id} in ${process.cwd()}`);
| Contract | Detail |
|---|---|
| Arguments | process.argv.slice(2), exactly as typed after the command |
| Description | First line // cli: ... shows in --list, help, MCP |
| Working dir | Caller's cwd; // cli-cwd: project-root or script-dir to change |
| Stdio / exit | Inherited; your exit code is the command's exit code |
| Languages | .js/.mjs run directly; .ts/.mts via Node 24 type stripping |
| Helpers | Put shared code in lib/ or _anything/ — never routed |
| Environment | CLI_SCRIPT, CLI_ROOT, CLI_SCOPE, CLI_PROJECT_ROOT, CLI_COMMAND, CLI_CALLER_CWD |
Templates: keep reusable starting points in _templates/<name>/ in any
command tree and scaffold from them with cli --new api users --template worker.
cli --new gh pr # scaffold (nearest local overlay, or --root)
cli --edit gh pr # open the script in $VISUAL / $EDITOR
cli --rm gh pr # delete (nested commands require --force)
cli --cp gh pr --to root # copy local -> user-global
cli --mv gh pr --to local # move user-global -> this repo
Transfers move whole command directories, preserve the command path, refuse
to overwrite, and warn when a script imports through ../ (such imports may
break outside their original tree).
Local overlays are arbitrary code that arrives with a git clone, and
shadowing means they can capture commands you type from muscle memory. So
execution is gated, direnv-style:
cli --trust # approve the overlays discovered from here
cli --trust --status # trusted | changed | untrusted, per overlay
cli --untrust # revoke
Trust records a content hash of the whole overlay; any change flips it to
changed and blocks execution (exit 3) until you re-approve. Your own
actions count as consent: --new, --cp/--mv --to local, and
--add --to local keep the target overlay trusted without ceremony.
~/.cli is always trusted. Set ASYNC_CLI_TRUST=off to disable the gate in
controlled environments (such as CI).
Any Git repository with a .cli/ tree is a command pack:
cli --add https://github.com/org/pack.git # into ~/.cli
cli --add https://github.com/org/pack.git --prefix vendor # namespaced: cli vendor <cmd>
cli --add https://github.com/org/pack.git --to local # into this repo
Installs are all-or-nothing: conflicts are listed and nothing is written
unless you pass --force.
The same command tree is discoverable by machines:
cli --agents --write # pin a pointer block into AGENTS.md (--claude for CLAUDE.md)
cli --list --json # stable inventory: commands, descriptions, scripts, shadows
cli --mcp # MCP stdio server: commands become callable tools
--mcp needs zero dependencies and exposes each non-shadowed command as a
tool (gh pull becomes gh__pull) taking { "args": [...] }. Untrusted
overlays are excluded.
eval "$(cli --completions bash)" # bash
eval "$(cli --completions zsh)" # zsh
cli --completions fish | source # fish
Tab-completion covers command segments (shadow-aware) and built-in flags.
cli --doctor # human report, exit 1 on errors
cli --doctor --json # { problems, summary } for tooling
Finds ambiguous script directories, ../ imports that break transfers,
empty command directories, untrusted or drifted overlays, stale --agents
blocks, missing descriptions, and shadowed commands.
| Command | Does |
|---|---|
cli <words...> [args...] | Route and run a command |
cli help [prefix] | Usage, or commands below a prefix |
cli --list [--json] | Inventory, including shadowed entries |
cli --which <words...> | Selected script and what it shadows |
cli --new <words...> [--root] [--template <name>] | Scaffold a command |
cli --edit <words...> | Open the script in $VISUAL/$EDITOR |
cli --rm <words...> [--root] [--force] | Remove a command directory |
cli --cp <words...> [--to root|local] | Copy between trees |
cli --mv <words...> [--to root|local] | Move between trees |
cli --add <git-url> [--to root|local] [--prefix <name>] [--force] | Install a command pack |
cli --trust [--status] / cli --untrust | Manage overlay trust |
cli --doctor [--json] | Audit the command trees |
cli --completions <bash|zsh|fish> | Emit shell completions |
cli --mcp | Serve commands over MCP stdio |
cli --agents [--write|--check] [--claude] | Manage the context pointer block |
cli --version | Print the package version |
Exit codes: the script's own for command runs; 2 for usage and routing
errors; 3 for trust refusals; 1 for --doctor with errors and
--agents --check drift.
pnpm run build
pnpm test
pnpm run pack:check
pnpm run release:check
This repo's CI, Pages, previews, and release lifecycle are generated by
@async/pipeline from
pipeline.ts. Do not hand-edit
.github/workflows/async-pipeline.yml or the locks under .locks/pipeline/.
Edit pipeline.ts, then regenerate and check:
pnpm run pipeline:sync:generate
pnpm run pipeline:sync:check
pnpm run pipeline:github:check
Common pipeline commands:
pnpm run pipeline:verify # local run of the verify job
pnpm run pipeline:pages # build the docs site task
pnpm run release:check # forced full verify used before releases
Releases ride the pipeline update train: when @async/pipeline publishes a
release, it dispatches an async-dep-bump event to this repo, and the
generated dependency-bump job bumps the pinned dependency, regenerates the
synced surfaces, verifies with release:check, and lands on main when green
or opens a pull request when not.
Maintainers who want the shell to prefer this checkout over an npm-installed copy can link the local binaries:
pnpm run local:link
pnpm run local:status
pnpm run local:unlink
FAQs
Filesystem-routed project and user-global commands for Async workspaces.
The npm package @async/cli receives a total of 10 weekly downloads. As such, @async/cli popularity was classified as not popular.
We found that @async/cli demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.

Security News
Agent Baseline’s new reference architecture shows how to secure software factories with four boundaries enforced outside the AI agent.

Security News
arXiv now limits authors to two submissions a month as AI slop overwhelms moderators, delays good papers, and sparks debate over applying the limit to everyone.

Research
/Security News
A new GhostAction wave hits hundreds of GitHub repos, expanding CI/CD secret theft to cloud and AI credentials in source code and git history.