Guide / Scripts and agents
Scripts and agents
Subcommands run once and print instead of opening the TUI. They make the same
read-only calls, so they’re safe to hand to a script or an AI agent: nothing
neboto can call changes an account. With no subcommand, neboto is the TUI
as before.
neboto services # every @prefix it knows
neboto ls @ec2 -t volume --state available # unattached EBS volumes
neboto ls @iam -t role -f 'deploy' # IAM roles, fuzzy-matched
neboto ls @ec2 -t instance --regions # across your config `regions`
neboto get @lambda orders-api # every detail-pane section
neboto get @iam deploy-role --section policies -o json
neboto audit # security findings; exit 3 if any
Try any of them with --demo, which answers from a built-in fake account
and needs no credentials.
ls: list and filter
ls <@service> lists a service’s resources, filtered the way the TUI’s
search filters them.
| Flag | Effect |
|---|---|
-t, --type <TYPE> | Only this resource type, by its name or last word(s): "Security Group", role, role|policy |
-f, --filter <QUERY> | Fuzzy text plus exact tag:key[=value] terms |
--state <STATE> | Only rows in this state (running, available, …) |
--hide-noise | Drop AWS-managed defaults and other noise rows (the TUI’s a) |
--limit <N> | At most N rows, across every region with --regions |
--regions[=LIST] | List across several regions, with a region column (see below) |
Across regions
--regions lists a regional service in several regions at once. Bare, it
uses your config regions plus the current region;
--regions=us-east-1,eu-west-1 names them for one run (the = is
required).
neboto ls @ec2 -t instance --regions
neboto ls @rds --regions=us-east-1,eu-west-1 -o json
Tables, Markdown and CSV gain a REGION column. In JSON, "region"
becomes "regions": [{"region", "status", "count", "message"}] and every
row carries its own "region". A region an SCP denies is denied: a line
on stderr, then the next region. The command fails only when no region
could be listed. Global services such as IAM have nothing to list per
region, so they’re a usage error.
get: everything the detail pane shows
get <@service> <ID|NAME>... prints every section of a resource’s detail
pane, including the ones the TUI loads when you open them: IAM policy
documents, CloudFormation events, template and drift, ECS deployments, and
so on. It takes up to 50 resources, matched by exact id (or ARN, where
that’s the id), then exact name.
| Flag | Effect |
|---|---|
-t, --type <TYPE> | Pick between resources that share a name (an ECS service and its task definition) |
--section <NAME> | Only this section, any case; repeatable. Section 1 is overview (details on a pane with only one section). The other sections’ data isn’t fetched |
--wait <SECS> | How long to wait for slow sections (default 60); anything still loading prints as not loaded |
audit: security findings
audit loads EC2, RDS, S3, EKS, IAM and KMS, reads the account settings and
per-resource settings the lists don’t carry, runs the same checks as the
TUI’s @audit, and prints the findings. Each
resource finding names its service and resource_id, so neboto get on
that pair gives the full detail. Account-level findings, such as GuardDuty
being off or no multi-region trail, have service: null and an empty
resource_id.
neboto audit # every finding
neboto audit --fail-on high -o json # gate CI on high severity only
| Flag | Effect |
|---|---|
--fail-on <SEVERITY> | high, medium, low (the default) or never: exit 3 when a finding is at or above it |
A check that couldn’t run, usually because a call was denied, is printed
too, with the IAM action it needed, and -o json puts it under
not_checked. An empty findings
with a non-empty not_checked is not a clean account.
Compare two resources
Diff two gets. Both print the same sections in the same order, so the
diff lines up:
diff <(neboto get @lambda orders-api-prod -o md) <(neboto get @lambda orders-api-staging -o md)
--section narrows it to what you care about, and any diff tool works
(delta, vimdiff, git diff --no-index).
Across accounts or regions, give each side its own -p / -r, and swap out
the account id and region first, or every ARN row differs:
norm() { sed -e "s/$1/ACCOUNT/g" -e "s/$2/REGION/g"; }
neboto get @lambda orders-api -p prod -o md | norm 111111111111 ap-southeast-2 > prod.md
neboto get @lambda orders-api -p staging -o md | norm 222222222222 ap-southeast-2 > staging.md
diff prod.md staging.md
These run one after the other, so two profiles with a prompting
credential_process don’t both ask at once. For an Organizations member
account, use a profile that assumes into it (role_arn +
source_profile); the CLI doesn’t assume org roles itself.
Output
-o table is the default on a terminal and -o json the default when
piped; -o md and -o csv work too. JSON is one document carrying
"schema": "neboto/v1". Section rows are the pane’s readable key: value
rows, not raw API fields, and a section that didn’t load is null. Warnings
go to stderr, so | jq keeps working.
| Exit code | Meaning |
|---|---|
0 | Success, including an empty list |
1 | AWS error (permissions, throttling, network) |
2 | A bad service, region or section, or a resource that isn’t there or matches more than one. The message says what to pass instead |
3 | audit only: it ran and found something at or above --fail-on. stdout still has the full result |
-p, -r, --endpoint-url and --demo work on every subcommand. Unlike
the TUI, an unknown profile or region is an error rather than a fallback, so
a script never gets another account’s answer. Secret values are never
fetched: the TUI’s x / Y have no CLI equivalent.
What scripts can rely on
- Stable: the flags; the JSON envelopes; each
lsrow’stype,id,name,stateandtags;get’sresourceobject andtags; section names (.sections.Permissions); resource type names; service prefixes; the first four CSV columns; the exit codes. Removing or renaming any of these is a breaking change: the schema moves toneboto/v2and the release notes say so. New sections, types, services and flags can arrive in any release. A test holds this, so it can’t change by accident. - Descriptive: everything inside a section, and the extra per-type
columns on an
lsrow ("Runtime","Memory", …). These are the detail pane, serialized: labels, units and grouping follow the TUI and can change in any release. Read them; don’t hard-code paths into them. When a script needs one field to stay put, the AWS API is that contract (aws …). - For people only:
-o tableand-o md. Don’t parse them.
For AI agents
skills/neboto/SKILL.md
teaches an agent the commands, the output shapes and the exit codes. For
Claude Code:
mkdir -p ~/.claude/skills/neboto
curl -fsSL https://raw.githubusercontent.com/neboto/neboto-tui/main/skills/neboto/SKILL.md \
-o ~/.claude/skills/neboto/SKILL.md