npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

aws-axi

v0.7.1

Published

Agent-ergonomic wrapper around the AWS CLI. Prefer this over `aws` for AWS operations.

Readme

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):

| Source | Example | |---|---| | --profile <name> flag | aws-axi whoami --profile dev | | AWS_PROFILE env var | export AWS_PROFILE=dev | | AWS_DEFAULT_PROFILE env var | export AWS_DEFAULT_PROFILE=dev | | AWS_AXI_PROFILE env var | export 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:

| Flag | No URI (list-buckets) | With URI (list-objects-v2) | |---|---|---| | --recursive | USAGE_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-readable | USAGE_ERROR | USAGE_ERROR (named exception: display-only; silent absorb would mislead) | | --summarize | USAGE_ERROR | USAGE_ERROR (named exception: same reason) | | --page-size | forwarded | forwarded | | --request-payer | USAGE_ERROR (invalid for list-buckets) | forwarded | | --bucket-name-prefix | Translated to --prefix | USAGE_ERROR | | --bucket-region | forwarded | USAGE_ERROR | | --query | Cap bypassed (JMESPath projects NextToken away; botocore auto-pages complete result); curated projection skipped | Same: cap bypassed, curated projection skipped | | --starting-token | forwarded; 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.

| Form | Effect | |---|---| | --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/.

| Service | Command | Enriched overlay operations | Everything else | | ---------------- | ------------------ | -------------------------------------------------------------------------------------------- | ---------------------------------- | | STS | whoami | identity fused with profile, region, credential source | — | | EC2 | ec2 | describe-vpcs, describe-subnets, describe-security-groups, describe-instances | → generic engine | | S3 | s3 | ls, cp, rm, presign (GET-only), head-object, create-bucket (idempotent) | → generic engine | | IAM | iam | list-roles, get-role, list-policies, get-policy, list-attached-role-policies | → generic engine | | CloudWatch Logs | logs | tail, filter, describe-log-groups | → generic engine | | KMS | kms | list-keys, list-aliases, describe-key, get-key-policy | → generic engine | | Lambda | lambda | list-functions, get-function, get-function-configuration, invoke | → generic engine | | SSM | ssm | run (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 Manager | secretsmanager (alias secrets) | list-secrets, get-secret-value (redacted), describe-secret | → generic engine | | Waiters | wait | any 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.

awsaws-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 aws | With aws-axi | What changed | | ------------------------------------------------------ | ----------------------------------------------------- | --------------------------------------------------------------------------- | | aws ec2 describe-instances --output json | aws-axi ec2 describe-instances | Output 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-role | aws-axi iam get-role --role-name my-role or aws-axi iam get-role my-role | aws-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 r | aws-axi iam list-attached-role-policies --role-name r or aws-axi iam list-attached-role-policies r | Same dual-form support | | aws sts get-caller-identity | aws-axi whoami | Fused with profile, region, and credential source | | (no equivalent) | aws-axi | No-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/ --recursive | aws-axi s3 ls s3://bucket/ --recursive | --recursive translated: drops --delimiter / so all nested keys are returned | | aws s3 ls s3://bucket/ --page-size 5 | aws-axi s3 ls s3://bucket/ --page-size 5 | --page-size forwarded verbatim to s3api list-objects-v2 | | aws s3 ls s3://bucket/ --human-readable | aws-axi s3 ls s3://bucket/ (drop the flag) | --human-readable → clean USAGE_ERROR (named exception; silent absorb misleads) | | aws s3 ls --bucket-name-prefix foo | aws-axi s3 ls --bucket-name-prefix foo | --bucket-name-prefix translated to --prefix on list-buckets | | aws s3api list-buckets | aws-axi s3 ls | High-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 TOK | aws-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 3600 | aws-axi s3 presign s3://bucket/key --expires-in 3600 | GET-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 1h | aws-axi logs tail <group> --since 1h | Same flag; snapshot (no --follow), capped with --limit | | aws logs filter-log-events --log-group-name <g> --filter-pattern ERROR | aws-axi logs filter <g> ERROR | Positional 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-decryption | aws-axi ssm get-parameter <n> --reveal | Redacted by default; --reveal opts in (adds --with-decryption) | | aws secretsmanager get-secret-value --secret-id <id> | aws-axi secretsmanager get-secret-value <id> --reveal | Redacted by default; --reveal opts in | | aws secretsmanager get-secret-value --secret-id <id> --query SecretString --output text | aws-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/stdin | printf '{}' \| aws-axi secretsmanager put-secret-value --secret-id id --secret-string file:///dev/stdin | An explicit file:///dev/stdin parameter receives the closed pipe; ordinary commands do not consume stdin | | aws kms describe-key --key-id alias/foo | aws-axi kms describe-key alias/foo | Positional id; accepts id, ARN, or alias | | aws lambda invoke --function-name f --payload '<json>' --cli-binary-format raw-in-base64-out out.json | aws-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 cwd | installed aws-axi never reads .env from cwd | The 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:

    | Code | Exit | Meaning | |---|---|---| | USAGE_ERROR | 252 | Bad flag or argument | | NO_REGION | 252 | No AWS region configured — pass --region, set AWS_DEFAULT_REGION, or aws configure set region | | NO_CREDENTIALS | 253 | No AWS credentials found — run aws sso login | | NO_PROFILE_SELECTED | 253 | Named profiles exist but none was selected — pass --profile <name> or export AWS_PROFILE=<name>; not an auth failure | | AUTH_EXPIRED | 253 | SSO token missing, stale, or invalid — run aws sso login --profile <name> | | SERVICE_CLIENT_ERROR | 254 | AWS service or client error | | AWS_NOT_INSTALLED | 127 | aws binary not found in PATH | | DRY_RUN_SUCCESS | 0 | DryRunOperation success signal (not an error) | | UNKNOWN | 255 | General / 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.

  • Redactionssm 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