cheat sheet
AWS CLI
Drive every AWS service from a terminal. Covers install (pip vs v2 installer), aws configure, profiles, SSO, day-to-day commands across S3 / EC2 / Lambda / IAM / STS, common scenarios, and credential precedence.
AWS CLI — Command-Line Interface for Amazon Web Services
What it is
The AWS CLI (aws) is Amazon's official command-line interface for managing AWS resources from a terminal or shell script. It wraps the same botocore library that powers the Python boto3 SDK, exposing every AWS service operation as a subcommand. Wherever the AWS Console gives you a button, the AWS CLI gives you a command.
There are two product lines:
- AWS CLI v1 — pip-installed, written entirely in Python. Still maintained for security fixes; new feature development stopped years ago.
- AWS CLI v2 — the current default. Ships as a self-contained binary (no Python install required), adds first-class SSO, a redesigned
aws configureflow, and a few syntax improvements. Available on macOS, Linux, Windows, and Docker.
Reach for the AWS CLI whenever you need to inspect or drive AWS from a shell. For application code, boto3 (the Python SDK) is the right layer; for repeatable infrastructure changes, IaC (CDK, Terraform) is better than a script of aws calls. The CLI is best for: one-off operations, support tickets, CI/CD glue, and exploratory work.
Install
v2 via the official installer (recommended)
macOS (universal .pkg):
curl -O https://awscli.amazonaws.com/AWSCLIV2.pkg
sudo installer -pkg AWSCLIV2.pkg -target /
aws --version
Output:
aws-cli/2.17.42 Python/3.12.x Darwin/24.0.0 source/arm64
Linux (x86_64):
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws --version
Output:
aws-cli/2.17.42 Python/3.12.x Linux/6.x source/x86_64.ubuntu
Windows (PowerShell):
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi
aws --version
Output: aws-cli/2.17.42 Python/3.12.x Windows/10
v1 via pip (legacy)
pip install awscli
aws --version
Output:
aws-cli/1.34.0 Python/3.12.x Darwin/24.0.0 botocore/1.34.0
Prefer v2 for any new install. v1 is in security-fix-only mode and lacks SSO support, the modern
aws configure ssoflow, and several newer service operations.
v2 via pip (not officially supported)
pip install awscliv2 # community-packaged wrapper
Output: installs a Python wrapper that downloads and shells out to the official v2 binary. Functional, but the official installer is preferred.
Verify your install
aws --version
aws configure list
which aws # macOS / Linux
where aws # Windows
Output: version line, the current credentials/profile/region settings, and the binary's location. If aws --version says aws-cli/1.x, you have v1.
Configuration
The AWS CLI reads credentials, region, and output settings from (in order): command-line flags → environment variables → the active profile in ~/.aws/credentials / ~/.aws/config → an EC2/ECS/Lambda IAM role.
Initial setup with aws configure
aws configure
Output:
AWS Access Key ID [None]: AKIAEXAMPLE...
AWS Secret Access Key [None]: ...
Default region name [None]: us-east-1
Default output format [None]: json
Writes to ~/.aws/credentials (the keys) and ~/.aws/config (region + output). Subsequent aws calls use the default profile unless overridden.
Named profiles
aws configure --profile prod
aws configure --profile dev
aws s3 ls --profile prod
Output: profile-specific configuration; --profile prod switches credentials for that one call. Set AWS_PROFILE=prod to make it sticky for the shell session.
Environment variables (CI and Docker)
export AWS_ACCESS_KEY_ID=AKIAEXAMPLE...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=... # only when using STS / SSO
export AWS_REGION=us-east-1
export AWS_PROFILE=prod # alternative to keys
aws sts get-caller-identity
Output: JSON identity payload — UserId, Account, Arn. The most useful sanity check after configuring anything.
Files involved
~/.aws/credentials—aws_access_key_id/aws_secret_access_keyper profile~/.aws/config—region,output,role_arn,source_profile,sso_*settings per profile (profiles use[profile prod]header except for[default])~/.aws/sso/cache/— SSO token cache
Day-to-day commands
The table below covers the operations you'll reach for most often. Every command supports --region, --profile, --output, --query, and --no-paginate.
| Command | What it does |
|---|---|
aws sts get-caller-identity | Print the current identity (account, ARN). Best smoke test. |
aws configure list | Show resolved configuration (which keys/region come from where). |
aws s3 ls | List buckets. |
aws s3 ls s3://my-bucket/prefix/ | List objects under a prefix. |
aws s3 cp local.txt s3://my-bucket/key.txt | Upload a file. |
aws s3 cp s3://my-bucket/key.txt ./ | Download a file. |
aws s3 sync ./build s3://my-site/ | Recursive sync (idempotent). |
aws s3 rm s3://my-bucket/key.txt | Delete an object. |
aws s3 presign s3://my-bucket/key --expires-in 3600 | Generate a time-limited URL. |
aws ec2 describe-instances | List EC2 instances (paginated). |
aws ec2 start-instances --instance-ids i-abc123 | Start an instance. |
aws ec2 stop-instances --instance-ids i-abc123 | Stop an instance. |
aws lambda invoke --function-name my-fn out.json | Synchronous Lambda invoke. |
aws lambda list-functions | List functions in the current region. |
aws logs tail /aws/lambda/my-fn --follow | Tail CloudWatch logs (v2 only). |
aws iam list-users | List IAM users. |
aws iam get-user --user-name alicedev | Get one user. |
aws iam list-attached-user-policies --user-name alicedev | List attached managed policies. |
aws ssm get-parameter --name /app/db_url --with-decryption | Read a parameter (decrypts SecureString). |
aws secretsmanager get-secret-value --secret-id app/db | Read a secret. |
aws cloudformation deploy --template-file t.yaml --stack-name s | Deploy a stack. |
aws dynamodb scan --table-name users | Scan a table (avoid in prod). |
aws sqs receive-message --queue-url $URL --wait-time-seconds 20 | Long-poll a queue. |
Common scenarios
The recipes below show end-to-end patterns you'll repeat across many environments.
Verify your identity and region
aws sts get-caller-identity
aws configure list
echo "Region: ${AWS_REGION:-$(aws configure get region)}"
Output:
{
"UserId": "AIDAEXAMPLEUSERID",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/alicedev"
}
Name Value Type Location
---- ----- ---- --------
profile prod env-var AWS_PROFILE
access_key ****************XYZA shared-credentials-file
secret_key ****************wxyz shared-credentials-file
region us-east-1 config-file
Region: us-east-1
The single best diagnostic when "AWS isn't working" — confirms which credentials and region are in effect.
Copy a bucket between accounts
aws s3 sync s3://source-bucket s3://dest-bucket \
--source-region us-east-1 --region us-west-2 \
--acl bucket-owner-full-control
Output: progress lines per object (copy: s3://source-bucket/key to s3://dest-bucket/key). --acl bucket-owner-full-control ensures the destination account owns the copies — critical for cross-account scenarios.
List EC2 instances with custom output
aws ec2 describe-instances \
--query 'Reservations[].Instances[].[InstanceId, State.Name, Tags[?Key==`Name`].Value | [0]]' \
--output table
Output:
----------------------------------------------------
| DescribeInstances |
+-----------------+----------+---------------------+
| i-0abc123 | running | web-1 |
| i-0def456 | stopped | worker-2 |
+-----------------+----------+---------------------+
--query is JMESPath — same engine boto3's Paginator.search() uses. Faster than piping through jq for simple filtering.
Invoke a Lambda synchronously
aws lambda invoke \
--function-name my-fn \
--cli-binary-format raw-in-base64-out \
--payload '{"name": "alice-dev"}' \
/tmp/response.json
cat /tmp/response.json
Output:
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
{"greeting":"Hello, alice-dev!"}
--cli-binary-format raw-in-base64-out is the v2 default that lets you pass JSON directly. Without it v2 expects base64-encoded payloads.
Assume a cross-account role
CREDS=$(aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/CrossAccount \
--role-session-name myhost-$(date +%Y%m%d-%H%M))
export AWS_ACCESS_KEY_ID=$(echo "$CREDS" | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo "$CREDS" | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo "$CREDS" | jq -r '.Credentials.SessionToken')
aws sts get-caller-identity # now reports the assumed role
Output: the second get-caller-identity shows the assumed-role ARN. Cleaner alternative: configure a profile with role_arn + source_profile in ~/.aws/config and use --profile.
List IAM users with the account they belong to
aws iam list-users \
--query 'Users[*].[UserName, Arn, CreateDate]' \
--output table
Output:
-----------------------------------------------------------------
| ListUsers |
+-----------+--------------------------------------+------------+
| alicedev | arn:aws:iam::123456789012:user/alic… | 2024-01-15 |
| bobops | arn:aws:iam::123456789012:user/bobo… | 2025-03-22 |
+-----------+--------------------------------------+------------+
Read CloudWatch Logs from the last hour
aws logs tail /aws/lambda/my-fn --since 1h --format short
Output:
2026-05-31T13:32:01 START RequestId: a1b2c3d4-…
2026-05-31T13:32:01 INFO Processing payload
2026-05-31T13:32:02 END RequestId: a1b2c3d4-…
Add --follow to stream live. v1 doesn't have aws logs tail — use aws logs filter-log-events instead.
Useful flags
The flags below apply to nearly every command.
| Flag | Purpose |
|---|---|
--profile <name> | Use the named profile from ~/.aws/config. |
--region <region> | Override the resolved region. |
--output json|text|table|yaml | Response format. json is the default; table is nicer for ad-hoc reading. |
--query '<jmespath>' | Filter/reshape the response with JMESPath. |
--no-paginate | Get one page only; useful when piping to head. |
--max-items N | Cap items returned across pages. |
--page-size N | Per-page request size (lower CPU on big lists). |
--debug | Print full HTTP request/response. Verbose; never use in CI logs (leaks signatures). |
--cli-auto-prompt | Interactive prompt — useful when exploring an unfamiliar service (v2 only). |
--cli-binary-format raw-in-base64-out | v2 default for raw JSON --payload arguments. |
--endpoint-url <url> | Override the endpoint (LocalStack, VPC endpoints). |
--no-cli-pager | Disable the auto-pager (less). |
--no-verify-ssl | Disable TLS verification. Don't. |
Profile management
Profiles are the main mechanism for switching between AWS accounts and roles. They live in ~/.aws/config and ~/.aws/credentials.
Static keys
# ~/.aws/credentials
[default]
aws_access_key_id = AKIA...
aws_secret_access_key = ...
[dev]
aws_access_key_id = AKIA...
aws_secret_access_key = ...
# ~/.aws/config
[default]
region = us-east-1
output = json
[profile dev]
region = us-west-2
output = yaml
Output: aws sts get-caller-identity --profile dev runs against the dev account.
Role assumption profiles
# ~/.aws/config
[profile prod-admin]
role_arn = arn:aws:iam::555555555555:role/Admin
source_profile = default
region = us-east-1
duration_seconds = 3600
Output: aws sts get-caller-identity --profile prod-admin returns the assumed role. The CLI auto-renews the STS credentials as needed.
SSO (recommended for organizations)
aws configure sso
Output (interactive):
SSO session name (Recommended): jay-sso
SSO start URL: https://my-org.awsapps.com/start
SSO region: us-east-1
SSO registration scopes: sso:account:access
Then opens a browser for the SSO login. Subsequent commands use the SSO token:
# ~/.aws/config (generated)
[profile prod]
sso_session = jay-sso
sso_account_id = 123456789012
sso_role_name = AdminAccess
region = us-east-1
aws sso login --profile prod
aws s3 ls --profile prod
Output: SSO token cached for ~8 hours (varies by config); aws s3 ls works until token expires.
Inspect resolved profile
aws configure list --profile prod
aws configure get region --profile prod
Output: shows where each setting came from (env var, profile file, default). The single most useful command when "wrong region" / "wrong account" surprises you.
Common pitfalls
The list below collects the failures I see in support tickets month after month.
- Region defaults silently. If neither
AWS_REGIONnor a profileregionis set, calls default tous-east-1for global services (IAM, STS) but FAIL for regional ones (EC2, Lambda). Always set a region explicitly —aws configure set region us-east-1indefault, orAWS_REGIONin CI. - Credential precedence surprises. The CLI walks: CLI flags → env vars → profile → IAM role. A stray
AWS_PROFILEenv var beats your--profileflag in some shells (shell-specific behavior); a strayAWS_ACCESS_KEY_IDenv var beats every profile.aws configure listreveals which wins. - v1 vs v2 syntax differences. v2 changed
--cli-binary-formatdefault; v2 addedaws logs tail; v2 removed some long-deprecated aliases. Scripts that "worked before" may need a small refactor when moving from v1 to v2. - Pagination by default.
aws ec2 describe-instancesreturns all instances by paginating in the background — slow for big accounts. Use--page-size 100and--max-items 50for exploration;--no-paginateto see one raw page. --output tabletruncates. Long ARNs and tags get cut. Use--output json(oryaml) when feeding to other tools.- Auto-pager (
less) swallows stdout in scripts. SetAWS_PAGER=""or pass--no-cli-pagerin non-interactive contexts. aws s3vsaws s3api.aws s3is the high-level wrapper (cp, sync, ls);aws s3apiis the raw 1:1 API. Some operations only exist unders3api(s3api put-bucket-cors, etc.).--queryJMESPath is finicky with mixed types and missing keys.Tags[?Key==``Name``].Value | [0]returnsnullwhen the tag is missing — wrap with--output textfilters in shell scripts cautiously.- SSO tokens expire. A long-running CI job that runs over an SSO session boundary will fail. Switch to a long-lived IAM role for CI.
--debugleaks credentials. Request signatures, headers, and sometimes payloads land in the log. Never run--debugin a pipeline that uploads logs.- Empty output ≠ error.
aws s3 ls s3://my-bucket/missing/exits 0 with no output. Check exit codes carefully; many list commands succeed even when zero items match. aws configureoverwrites silently — it does not back up the existing profile. Keep~/.aws/underchezmoior a personal dotfiles repo.
See also
- Packages: pip-boto3 — Python SDK for application code
- Concept: API — REST + signing fundamentals
- Python: installation — getting Python ready for
pip install awscli - Official AWS CLI documentation
- Full v2 command reference
- JMESPath query language (used by
--query)