@bellem/agent-native-cli
v0.1.0
Published
Non-interactive JSON-first CLI (anc) for AI agents and automation — HTTP, filesystem, git, env, and argv-only process execution
Maintainers
Readme
agent-native-cli (anc)
Non-interactive, JSON-first CLI for AI agents and automation.
Agents and scripts need tools that never prompt, never write progress bars to stdout, and always return a single parseable result. anc wraps HTTP, filesystem, git, environment, and process execution behind a stable JSON envelope so your agent can JSON.parse stdout and check ok / exit code.
anc env get PATH
# {"ok":true,"data":{"name":"PATH","value":"/usr/bin:...","set":true}}Why agents need this
Interactive CLIs assume a human at a TTY: they prompt, colorize, paginate, and mix status text with data. That breaks agent loops.
| Interactive CLIs | anc |
|------------------|-------|
| Prompts / confirmations | Never prompts |
| Human-oriented text on stdout | One JSON object on stdout (default) |
| Ambiguous exit meanings | 0 = success, 1 = failure; JSON still emitted |
| Shell-string exec hazards | anc run is argv-only (no shell) |
| Env dumps of secrets | env list returns names only, requires --pattern |
Use --human when you want readable text (debugging); leave it off for agents.
Requirements
- Node.js ≥ 20
gitonPATHforanc git …
Install
Once published to npm (intended)
npm install -g @bellem/agent-native-cli
anc --helpOr as a project dependency:
npm install @bellem/agent-native-cli
npx anc --helpNote: Intended npm name is
@bellem/agent-native-cli(scoped; usenpm publish --access public). Publish only after the npm account is OKed. Until then, use the local build below.
Local build (this repo / tarball)
cd agent-native-cli # or extract the release tarball
npm install
npm test
npm run build
node dist/cli.js --help
# optional: npm link → puts `anc` on your PATHLocal script alias:
npm run anc -- --helpQuickstart
All examples assume the binary is available as anc (or node dist/cli.js).
# Environment
anc env get HOME
# {"ok":true,"data":{"name":"HOME","value":"/home/...","set":true}}
anc env list --pattern 'NODE*'
# {"ok":true,"data":{"pattern":"NODE*","names":["NODE_ENV",...],"count":N}}
# Filesystem
anc fs list .
# {"ok":true,"data":{"path":".","absolutePath":"...","entries":[...]}}
anc fs write /tmp/anc-demo.txt --content 'hello' --mkdir
anc fs read /tmp/anc-demo.txt
# Run a process (argv after --; no shell)
anc run -- echo 'hello from anc'
# {"ok":true,"data":{"cmd":"echo","args":["hello from anc"],"code":0,"stdout":"hello from anc\n",...}}
# HTTP
anc http get https://example.com --max-body 2048
# {"ok":true,"data":{"status":200,"statusText":"OK","headers":{...},"body":"...","truncated":false,...}}
# Human-readable (stderr for errors)
anc --human env get USERMore copy-paste snippets: examples/.
Output contract
Success (exit 0):
{ "ok": true, "data": { } }Failure (exit 1) — still a single JSON line on stdout in JSON mode:
{ "ok": false, "error": { "code": "NOT_FOUND", "message": "Path not found: /nonexistent" } }Optional error.details may carry structured context (e.g. run result on non-zero exit).
With --human: success text on stdout; errors on stderr as Error [CODE]: message.
Exit codes
| Code | Meaning |
|------|---------|
| 0 | ok: true |
| 1 | ok: false (or unexpected internal failure) |
Error codes
INVALID_ARGS · NOT_FOUND · TIMEOUT · SIZE_LIMIT · PERMISSION · NETWORK · GIT_ERROR · NO_GIT · NO_REPO · ENV_DENIED · RUN_ERROR · INTERNAL
Global options
| Flag | Meaning |
|------|---------|
| --human | Human-readable text instead of JSON (before or after the subcommand) |
| -V, --version | Print version |
| -h, --help | Help |
Command reference
http
anc http get <url> [-H "Name: Value"] [-t <ms>] [--max-body <bytes>]
anc http post <url> [-d <body>] [-H "Name: Value"] [-t <ms>] [--max-body <bytes>]| Option | Default |
|--------|---------|
| -t, --timeout | 30000 ms |
| --max-body | 65536 bytes (64KB); oversized bodies set truncated: true |
| -H, --header | Repeatable Name: Value |
| -d, --data | POST body (POST defaults content-type: application/json if unset) |
data includes: status, statusText, headers, body, bodyBytes, truncated, url, redirected.
fs
anc fs list [path] [-a|--all]
anc fs stat <path>
anc fs read <path> [--max-bytes <n>]
anc fs write <path> --content <text> [--dry-run] [--mkdir]
anc fs write <path> --stdin [--dry-run] [--mkdir]| Command | Notes |
|---------|--------|
| list | Default path .; -a includes dot entries |
| read | Default --max-bytes = 256KB |
| write | Requires --content or --stdin; --mkdir creates parents; --dry-run reports without writing |
git
Requires git on PATH. Never interactive (GIT_TERMINAL_PROMPT=0).
anc git status [-C <path>]
anc git branch [-C <path>]
anc git log [-n <limit>] [-C <path>]| Option | Default |
|--------|---------|
| -n, --limit | 10 (log only) |
| -C, --cwd | Current working directory |
env
anc env get <NAME>
anc env list --pattern <glob|'/regex/'>getreturns{ name, value, set }(valueisnullwhen unset; still exit0).listrequires--pattern(glob likeNODE_*or/regex/) and returns names only — never dumps all env values.
run
Argv-only (no shell). Put the executable after --:
anc run -- echo hello
anc run -t 5000 -- node -e "console.log(1)"
anc run -C /tmp --max-output 8192 -- ls -la| Option | Default |
|--------|---------|
| -t, --timeout | 60000 ms |
| -C, --cwd | process cwd |
| --max-output | 65536 bytes each for stdout/stderr |
On timeout: exit 1, code TIMEOUT, details include the partial result. On non-zero child exit: exit 1, code RUN_ERROR, details include the full run result.
Library import
Programmatic API (ESM):
import {
httpRequest,
fsList,
fsStat,
fsRead,
fsWrite,
gitStatus,
gitBranch,
gitLog,
envGet,
envList,
runCommand,
} from '@bellem/agent-native-cli';
const home = envGet('HOME');
const listing = await fsList('.');Types ship with the package (dist/index.d.ts).
Examples
| File | Purpose |
|------|---------|
| examples/basic.sh | Smoke script: help, env, fs, run, --human |
| examples/http-get.jsonl | Documented http get invocation + expected envelope |
chmod +x examples/basic.sh
./examples/basic.shLicense
MIT — see LICENSE.
