Skip to content
Conduit

skill

aws-axi

Agent-ergonomic wrapper over the aws CLI — mirrors AWS 1:1 with TOON output and model-driven full coverage. The AWS analogue of gh-axi.

bauti-defi/aws-axicommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/bauti-defi/aws-axi itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 25, 2026

AWS CLI for agents — designed with AXI (Agent eXperience Interface).

Wraps the official aws cli with token-efficient TOON output, capped pagination with honest totals, model-derived signatures instead of thousand-line help pages, structured errors, and next-step suggestions. Built for autonomous agents that interact with AWS via shell execution. The AWS analogue of gh-axi, built on axi-sdk-js.

aws-axi <service> <operation> [--flags]   # mirrors: aws <service> <operation> [--flags]

[!WARNING] aws-axi is young. Hand-polished overlays cover only the hot-path services; everything else runs through a generic engine that works but is less polished and may have bugs. Secret values are redacted by default on the ssm/secretsmanager overlays and on the Secrets Manager engine path, but every other engine-path response is unredacted — including SSM operations the ssm overlay does not cover, which fall through to the engine. Use it carefully, and if it ever blocks you, fall back to raw aws for that call. Found a bug or a gap? Please file an issue — see Reporting issues.

Why

The aws CLI is built for humans at a terminal. For an LLM deciding the next command it is hostile: verbose JSON, auto-pagination that dumps multi-MB blobs in one call, help pages thousands of lines long, and errors buried in stderr. aws-axi keeps AWS's exact interface but changes the output and ergonomics so an agent can act in one turn.

How

Two layers over the real aws binary (we shell out to it — never reimplement AWS APIs):

  • A model-driven generic engine. aws-axi reads the same botocore service models the AWS CLI is generated from, so every AWS operation works on day one — with distilled signatures, required-param detection, capped pagination, and structured errors, auto-tracking each aws release.
  • Hand-polished overlays for the highest-value services — curated schemas, idempotent mutations, secret redaction, and reference-resolution (show a security group's name, not sg-…). When an overlay doesn't implement an operation, it falls through to the generic engine automatically.

Quick Start

No install needed — invoke on demand with npx:

npx -y aws-axi whoami

Requirements:

  • The aws CLI installed and configured (aws sso login or aws configure). aws-axi shells out to it.
  • Bun (the CLI runs on the Bun runtime).

Profile required on SSO-only setups. aws sso login --profile dev never creates a [default] section, so ~/.aws/config may contain only named profiles with no default fallback. aws-axi needs a profile, exactly as the raw aws CLI does. Three ways to supply it:

# 1. Per-command flag
npx -y aws-axi whoami --profile dev

# 2. Shell environment (standard; affects all AWS tools)
export AWS_PROFILE=dev && npx -y aws-axi whoami

# 3. aws-axi-specific env var (lowest precedence; pins a session without clobbering AWS_PROFILE)
export AWS_AXI_PROFILE=dev && npx -y aws-axi whoami

If aws-axi reports NO_PROFILE_SELECTED, it will list the available profiles — pick one from that list and re-invoke.

For a global install and ambient session context:

bun add -g aws-axi        # or: npm install -g aws-axi
aws-axi setup hooks       # optional SessionStart hooks for Claude Code / Codex / OpenCode
aws-axi update --check    # check for a newer release; `aws-axi update` to upgrade

Usage

aws-axi                         # dashboard — current identity + region, no args needed
aws-axi whoami                  # full identity: account, ARN, region, credential source
aws-axi ec2 describe-instances  # enriched overlay — instances with resolved names
aws-axi ec2 describe-regions    # not an overlay op → falls through to the generic engine
aws-axi s3 ls s3://my-bucket/prefix/
aws-axi logs tail /aws/lambda/my-fn --since 1h
aws-axi ssm get-parameter /my/app/db-password           # value redacted by default
aws-axi ssm get-parameter /my/app/db-password --reveal  # opt in to the plaintext value
aws-axi lambda invoke --function-name my-fn --payload '{"k":"v"}'
aws-axi wait ec2 instance-running --instance-ids i-0123456789abcdef0
aws-axi sqs list-queues         # no overlay → served entirely by the generic engine
aws-axi <service> <op> --help   # per-command signature + examples

Global flags --profile <name> and --region <region> are accepted before any command. Every response ends with contextual help: next-step hints.

Profile precedence (highest to lowest):

SourceExample
--profile <name> flagaws-axi whoami --profile dev
AWS_PROFILE env varexport AWS_PROFILE=dev
AWS_DEFAULT_PROFILE env varexport AWS_DEFAULT_PROFILE=dev
AWS_AXI_PROFILE env varexport AWS_AXI_PROFILE=dev

AWS_AXI_PROFILE is aws-axi-specific and has the lowest precedence. Use it to pin a repository or agent session to a profile without clobbering the system-wide AWS_PROFILE used by other tools.

Capabilities

What is implemented today. Anything not listed as an enriched overlay still works through the generic engine (correct, structured, capped) — it just isn't curated.

Overlay superset invariant. Every enriched overlay's input contract is a strict superset of the real aws CLI's. Any flag the underlying aws operation accepts is forwarded verbatim to the child aws invocation. The overlay changes the output, never restricts the input. Two flags are handled specially: --output is stripped (the exec seam always appends --output json); --query is forwarded verbatim, bypasses the overlay's curated projection (result shape is unknown), and suppresses the overlay's default --max-items cap (JMESPath projects NextToken away, so botocore auto-pages to the complete result without a cap). An explicit --max-items you supply yourself is still honored. These two bypass behaviors apply to all enriched overlays and the generic engine. Two deliberate named exceptions exist for s3 ls (see below).

S3 ls flag handling. s3 ls rewrites to s3api internally. Dispositions per flag × path:

FlagNo URI (list-buckets)With URI (list-objects-v2)
--recursiveUSAGE_ERROR (any form, including =false — bucket listing has no recursion concept; real aws rejects --recursive=false outright)Translated: drops --delimiter /, returning all nested keys
--human-readableUSAGE_ERRORUSAGE_ERROR (named exception: display-only; silent absorb would mislead)
--summarizeUSAGE_ERRORUSAGE_ERROR (named exception: same reason)
--page-sizeforwardedforwarded
--request-payerUSAGE_ERROR (invalid for list-buckets)forwarded
--bucket-name-prefixTranslated to --prefixUSAGE_ERROR
--bucket-regionforwardedUSAGE_ERROR
--queryCap bypassed (JMESPath projects NextToken away; botocore auto-pages complete result); curated projection skippedSame: cap bypassed, curated projection skipped
--starting-tokenforwarded; list-buckets capped at S3_PAGE_SIZE — truncation reported via synthesized NextToken (not native ContinuationToken, which botocore strips)forwarded

Default: s3 ls s3://b/ adds --delimiter / (matching real aws s3 ls behavior) and surfaces CommonPrefixes as prefixes[]. Folder-only buckets are never reported as empty.

s3 cp and s3 rm use the high-level aws s3 commands, so --recursive, --quiet, --only-show-errors, --no-progress, --follow-symlinks, --exclude, --include, --sse, and --storage-class are valid passthrough for those.

Value-aware boolean flags (cp/rm): --dryrun, --recursive, --quiet, --only-show-errors, --no-progress, and --follow-symlinks accept an optional boolean value token. The literal value is never forwarded to the child aws process.

FormEffect
--flag (bare)enabled
--flag true / --flag=true / --flag=1 / --flag=yes (case-insensitive)enabled
--flag false / --flag=false / --flag=0 / --flag=no (case-insensitive)disabled — aws-axi superset extension; real aws hard-errors on --flag=false
--flag=<anything else> (e.g. --dryrun=off)USAGE_ERROR — unrecognised value hard-errors to prevent silent no-ops

The =false/=0/=no extension exists because LLM agents commonly emit these forms from boolean-typed schemas. Without it, --dryrun=false was inverted to dry-run-on (exit 0, no bytes transferred). The hard-error on unrecognised values (e.g. --dryrun=off) prevents a different silent no-op: the user intended to disable dry-run but got a dry run.

The same vocabulary applies to --recursive on s3 ls s3://bucket/.

Model boolean parameters (generic engine): the same explicit values apply to every botocore boolean, including logs get-log-events --start-from-head. --flag false / --flag=false becomes --no-flag (parameter false) before the AWS CLI call, so the literal false is not an unknown option. Bare --flag and --flag true stay --flag (true). --no-flag is unchanged. Last occurrence wins. An unrecognised = value is USAGE_ERROR and names the token.

ServiceCommandEnriched overlay operationsEverything else
STSwhoamiidentity fused with profile, region, credential source—
EC2ec2describe-vpcs, describe-subnets, describe-security-groups, describe-instances→ generic engine
S3s3ls, cp, rm, presign (GET-only), head-object, create-bucket (idempotent)→ generic engine
IAMiamlist-roles, get-role, list-policies, get-policy, list-attached-role-policies→ generic engine
CloudWatch Logslogstail, filter, describe-log-groups→ generic engine
KMSkmslist-keys, list-aliases, describe-key, get-key-policy→ generic engine
Lambdalambdalist-functions, get-function, get-function-configuration, invoke→ generic engine
SSMssmrun (send+wait+unescaped output in one call), get-command-invocation (unescaped, --wait), describe-parameters, get-parameter, get-parameters, get-parameters-by-path (redacted)→ generic engine
Secrets Managersecretsmanager (alias secrets)list-secrets, get-secret-value (redacted), describe-secret→ generic engine
Waiterswaitany botocore waiter, e.g. wait ec2 instance-running, wait s3 bucket-exists—
Any other service(service name)—fully served by the generic engine

Plus: setup hooks (ambient SessionStart context) and the SDK built-in update / update --check.

Generic engine coverage. aws-axi <service> <operation> works for any service/operation in your installed aws CLI's botocore models — required-param validation, capped pagination, and structured errors, but a generic projection (no reference-name enrichment, no idempotency niceties, and — outside Secrets Manager — no secret redaction).

Not implemented yet / known limitations:

  • Engine-path redaction is Secrets Manager-only. The ssm and secretsmanager overlays redact, and the engine recursively redacts SecretString / SecretBinary on secretsmanager responses. Everything else on the engine path still prints in the clear — another service's secret-bearing field (e.g. an RDS or Cognito response), and also SSM parameter operations outside the overlay's curated set (e.g. ssm get-parameter-history), which fall through to the engine.
  • Mutations are mostly raw. Idempotency / --dryrun niceties exist only for the S3 overlay (cp, rm, create-bucket); other writes go through the engine unguarded.
  • logs tail is a snapshot, not a live follow (aws logs tail --follow has no equivalent).
  • Overlays are read-heavy. Most curated commands are describes/gets; write-path overlays are minimal.
  • Runtime is Bun (not Node) and there is no Windows build.

aws ↔ aws-axi

The interface mirrors the AWS CLI 1:1 — same service and operation names — so most commands are identical apart from the aws-axi prefix. aws-axi needs a profile for exactly the same reason raw aws does. If you habitually export AWS_PROFILE=dev and never notice, raw aws works fine for the same reason aws-axi works fine — both see the env var. (This was the source of #70's confusion: "the raw CLI works fine for me" was really "I export AWS_PROFILE and never noticed.")

Where the ergonomics differ, here is the map both ways:

You'd run with awsWith aws-axiWhat changed
aws ec2 describe-instances --output jsonaws-axi ec2 describe-instancesOutput is always TOON; --output is ignored (stripped)
aws ec2 describe-instances --filters Name=...,Values=...aws-axi ec2 describe-instances --filters Name=...,Values=...--filters (and any other aws flag) forwarded verbatim; output is still enriched TOON
aws iam list-roles --query 'Roles[].RoleName'aws-axi iam list-roles --query 'Roles[].RoleName'--query forwarded; JMESPath applied by aws CLI; overlay projection bypassed
aws iam get-role --role-name my-roleaws-axi iam get-role --role-name my-role or aws-axi iam get-role my-roleaws-axi also accepts the positional form (aws-axi extension); flag form follows real aws
aws iam get-policy --policy-arn arn:…aws-axi iam get-policy --policy-arn arn:… or aws-axi iam get-policy arn:…Same dual-form support
aws iam list-attached-role-policies --role-name raws-axi iam list-attached-role-policies --role-name r or aws-axi iam list-attached-role-policies rSame dual-form support
aws sts get-caller-identityaws-axi whoamiFused with profile, region, and credential source
(no equivalent)aws-axiNo-arg dashboard: current identity + region
aws s3 ls s3://bucket/aws-axi s3 ls s3://bucket/Same; --delimiter / added (matches real non-recursive behavior); output capped + TOON (use --starting-token to page; --query bypasses cap)
aws s3 ls s3://bucket/ --recursiveaws-axi s3 ls s3://bucket/ --recursive--recursive translated: drops --delimiter / so all nested keys are returned
aws s3 ls s3://bucket/ --page-size 5aws-axi s3 ls s3://bucket/ --page-size 5--page-size forwarded verbatim to s3api list-objects-v2
aws s3 ls s3://bucket/ --human-readableaws-axi s3 ls s3://bucket/ (drop the flag)--human-readable → clean USAGE_ERROR (named exception; silent absorb misleads)
aws s3 ls --bucket-name-prefix fooaws-axi s3 ls --bucket-name-prefix foo--bucket-name-prefix translated to --prefix on list-buckets
aws s3api list-bucketsaws-axi s3 lsHigh-level s3 ls with no target lists buckets; output capped at 20 + TOON (use --starting-token to page; --query bypasses cap)
aws s3api list-buckets --starting-token TOKaws-axi s3 ls --starting-token TOK--starting-token forwarded on both paths (list-buckets is genuinely paginated); output capped + TOON
aws s3 presign s3://bucket/key --expires-in 3600aws-axi s3 presign s3://bucket/key --expires-in 3600GET-only presigned URL; --expires-in defaults to 3600 and is bounded to 1–604800 seconds; extra positionals are a USAGE_ERROR
aws logs tail <group> --since 1haws-axi logs tail <group> --since 1hSame flag; snapshot (no --follow), capped with --limit
aws logs filter-log-events --log-group-name <g> --filter-pattern ERRORaws-axi logs filter <g> ERRORPositional group + pattern
aws ssm send-command … && sleep 12 && aws ssm get-command-invocation …aws-axi ssm run --instance-ids i-… --commands "docker ps"One call: sends, polls, returns unescaped stdout/stderr/remoteExitCode. Exit codes: remote shell exit propagated verbatim (1..249); delivery failure (TimedOut/Undeliverable/Cancelled) → 254; InProgress → 0 (no false failure for polling loops); --query → USAGE_ERROR (no single underlying response to target — use get-command-invocation --query instead)
aws ssm get-command-invocation --command-id … --instance-id … (output has \n-escaped blobs)aws-axi ssm get-command-invocation --command-id … --instance-id … [--wait]--wait polls until terminal; stdout/stderr rendered as line arrays (unescaped)
aws ssm get-parameter --name <n> --with-decryptionaws-axi ssm get-parameter <n> --revealRedacted by default; --reveal opts in (adds --with-decryption)
aws secretsmanager get-secret-value --secret-id <id>aws-axi secretsmanager get-secret-value <id> --revealRedacted by default; --reveal opts in
aws secretsmanager get-secret-value --secret-id <id> --query SecretString --output textaws-axi secretsmanager get-secret-value <id> --reveal --raw--raw writes the byte-exact SecretString to stdout with no wrapper and no trailing newline (for command substitution). Requires --reveal; rejects --query; SecretBinary is a USAGE_ERROR
printf '{}' | aws secretsmanager put-secret-value --secret-id id --secret-string file:///dev/stdinprintf '{}' | aws-axi secretsmanager put-secret-value --secret-id id --secret-string file:///dev/stdinAn explicit file:///dev/stdin parameter receives the closed pipe; ordinary commands do not consume stdin
aws kms describe-key --key-id alias/fooaws-axi kms describe-key alias/fooPositional id; accepts id, ARN, or alias
aws lambda invoke --function-name f --payload '<json>' --cli-binary-format raw-in-base64-out out.jsonaws-axi lambda invoke --function-name f --payload '<json>'--cli-binary-format handled automatically; result returned inline
aws ec2 wait instance-running --instance-ids i-…aws-axi wait ec2 instance-running --instance-ids i-…wait is a top-level verb; waiter names stay kebab-case; adds a polling budget
aws <svc> <op> ... (auto-paginates everything)aws-axi <svc> <op> --max-items N --next-token <tok>Capped by default with an honest count; resume with the emitted token
aws never reads .env from cwdinstalled aws-axi never reads .env from cwdThe distributed launcher honors only exported shell env vars and ~/.aws/*; a repo's .env (e.g. AWS_ENDPOINT_URL=http://localhost:4566 for LocalStack) is ignored

Conventions that apply everywhere:

  • Output — TOON, not JSON. Tabular result sets render as key[N]{col,col} blocks with a count.

  • Pagination — capped by default (--max-items / --limit, service-specific defaults). When more exists, the result carries a NextToken; resume with --next-token (or --starting-token for s3 ls).

  • Errors — structured TOON on stderr (error, code, help[]) with exit codes:

    CodeExitMeaning
    USAGE_ERROR252Bad flag or argument
    NO_REGION252No AWS region configured — pass --region, set AWS_DEFAULT_REGION, or aws configure set region
    NO_CREDENTIALS253No AWS credentials found — run aws sso login
    NO_PROFILE_SELECTED253Named profiles exist but none was selected — pass --profile <name> or export AWS_PROFILE=<name>; not an auth failure
    AUTH_EXPIRED253SSO token missing, stale, or invalid — run aws sso login --profile <name>
    SERVICE_CLIENT_ERROR254AWS service or client error
    AWS_NOT_INSTALLED127aws binary not found in PATH
    DRY_RUN_SUCCESS0DryRunOperation success signal (not an error)
    UNKNOWN255General / unrecognized error

    Write operations that return HTTP 200 with an empty body (e.g. sqs purge-queue, iam put-role-policy, iam delete-role-policy) emit ok: true — confirming success without an ambiguous blank output.

  • Redaction — ssm and secretsmanager overlays redact values unless --reveal is passed. The generic engine also redacts SecretString / SecretBinary recursively on secretsmanager responses. On secret-bearing Secrets Manager operations (get-secret-value, batch-get-secret-value), --query without --reveal is a hard USAGE_ERROR — JMESPath is applied by the aws CLI before aws-axi sees the response, so allowing it would silently bypass redaction. Pass --reveal to opt in, then --query applies normally.

  • Idempotency — overlay mutations (e.g. s3 create-bucket) report what changed and are safe to re-run.

  • No .env loading (installed CLI) — the distributed launcher never reads .env from the current directory. Only genuinely-exported shell environment variables and ~/.aws/* config are honored, matching the aws CLI exactly. (If you run bun run bin/aws-axi.ts directly in a repo that has a .env, use bun --no-env-file bin/aws-axi.ts to get the same isolation.)

  • Overlay superset — any flag the underlying aws operation accepts is forwarded verbatim. Overlays change the output, never restrict the input. Exception: --output is stripped (always json internally); --query is forwarded verbatim, bypasses the overlay's curated projection, and suppresses the default --max-items cap (botocore auto-pages to completion; explicit --max-items still wins). Exception: redaction wins over --query on secret-bearing Secrets Manager operations (see Redaction above).

  • Two-arg flag form — --flag <value> is the normal form. If the value token starts with --, aws-axi throws USAGE_ERROR immediately rather than silently treating another flag as a value. Fix: use the equals form (--flag=<value>) or reorder so the value precedes the next flag.

  • Duplicate owned flags — if the same value-taking flag appears more than once (e.g. --role-name old --role-name new), the last value wins — matching real aws CLI behaviour. Every occurrence is still validated, so a malformed one anywhere in the argv is a USAGE_ERROR even if a later occurrence would have won. Exception: repeated boolean toggles (--dryrun, --recursive, --reveal) resolve on their first occurrence so a trailing duplicate cannot undo the fail-safe direction — --dryrun --dryrun=false stays a dry run, --reveal=false --reveal stays redacted.

  • Standard-input file references — when an AWS argument explicitly uses file:///dev/stdin, aws-axi pipes its stdin to the underlying AWS CLI. This supports streamed values such as printf '{}' | aws-axi secretsmanager put-secret-value --secret-id id --secret-string file:///dev/stdin; ordinary commands do not read or drain stdin.

Reporting issues

aws-axi is early and improving. If you hit a bug, wrong output, or a missing capability, please file an issue at bauti-defi/aws-axi — include the aws-axi command you ran, what you expected, what you got, and the equivalent raw aws command. If you use gh-axi:

gh-axi issue create --title "..." --label bug --body "..."

Development

bun install
bun run dev          # run the CLI directly (bun run bin/aws-axi.ts …)
bun test             # run the test suite
bun run typecheck    # tsc --noEmit
bun run check:pins   # enforce exact-pinned dependencies
bun run build        # bundle to dist/bin/aws-axi.js
bun run build:skill  # regenerate skills/aws-axi/SKILL.md (CI fails if it drifts)
bun run verify:dist  # pre-publish guard
bun run release      # build → verify:dist → test → npm publish (bump version first)

The committed skills/aws-axi/SKILL.md is generated by bun run build:skill; CI fails if it drifts. The npm package ships skills/aws-axi/, so published releases include the installable Agent Skill.

License

MIT

↑↓ navigate openesc close