AWS Updated 2026-07-05 119+ commands Verified against official docs

AWS CLI Cheat Sheet

110+ AWS CLI commands for S3, EC2, IAM, Lambda, CloudWatch, SSM and more. Searchable, filterable, copy with one click. Includes the Credential Chain Debugger.

Ctrl+K

Everything runs in your browser. No commands or data are sent to any server.

New to AWS CLI? Start with these

5 essential commands to get you started. The full reference is right below.

Configure AWS CLI credentials

aws configure

First command to run on a new machine to set up your access key, secret key, default region, and output format.

Check the currently assumed identity

aws sts get-caller-identity

The single most important debugging command in the entire AWS CLI, run this whenever something is failing with auth or permission errors.

List S3 buckets or objects

aws s3 ls

List all buckets or list objects inside a bucket.

List all EC2 instances

aws ec2 describe-instances --query "Reservations[].Instances[].{ID:InstanceId,State:State.Name,Type:InstanceType}" --output table

List all EC2 instances and their current state in your account and region.

Copy a local file to S3

aws s3 cp ./file.txt s3://my-bucket/folder/file.txt

Upload a single local file to a specific key in an S3 bucket.

119 commands

Configure AWS CLI credentials

Beginner
aws configure

↓ Click command to explain

When to use this

First command to run on a new machine to set up your access key, secret key, default region, and output format.

Gotcha

This stores credentials in plaintext at ~/.aws/credentials, never commit that file to git.

Configure a named profile

Beginner
aws configure --profile myprofile

↓ Click command to explain

When to use this

Set up a named profile for a second AWS account without overwriting your default.

Gotcha

The profile name you use here must be used exactly with --profile on every command or with export AWS_PROFILE.

Show active configuration and credential sources

Beginner
aws configure list

↓ Click command to explain

When to use this

Debug which credentials and region are actually active right now. The source column shows whether each value comes from an env variable, config file, or default.

List all configured profiles

Beginner
aws configure list-profiles

↓ Click command to explain

When to use this

See all named profiles before switching or to debug a profile-not-found error.

Check active AWS identity

Beginner
aws sts get-caller-identity

↓ Click command to explain

When to use this

Verify which AWS account and IAM identity is active before running any destructive command.

Gotcha

This is the first command to run when anything fails with an authentication error. It shows exactly who AWS thinks you are.

Set up AWS SSO login

Intermediate
aws configure sso

↓ Click command to explain

When to use this

Set up AWS SSO so you can log in with your browser instead of long-lived access keys.

Gotcha

After setup you still need to run aws sso login --profile yourprofile before each session or commands fail with confusing token expired errors.

Refresh an expired SSO session

Intermediate
aws sso login --profile myprofile

↓ Click command to explain

When to use this

Refresh your SSO session when it has expired so subsequent commands work again.

Switch active profile for the shell session

Beginner
export AWS_PROFILE=myprofile

↓ Click command to explain

When to use this

Switch the active profile for your entire shell session without adding --profile to every command.

Gotcha

This environment variable persists for the entire terminal session including any scripts you run from it, unset it with unset AWS_PROFILE when done.

Disable the CLI output pager

Intermediate
aws configure set cli_pager ""

↓ Click command to explain

When to use this

Disable the default pager that pipes all CLI v2 output through less, which causes CI scripts to hang waiting for a keypress.

Gotcha

This is the single most common reason AWS CLI v2 scripts hang silently in CI pipelines, set it globally or pass --no-cli-pager on every command.

Extract a single value with --query and --output text

Beginner
aws sts get-caller-identity --query Account --output text

↓ Click command to explain

--query JMESPath expression selecting which part of the JSON response to return
--output text Print the result as a bare string instead of JSON, ideal for shell variables

When to use this

Extract a single value from any AWS CLI response as a bare string for use in shell scripts and variables.

Gotcha

If your --query expression returns null it means the path is wrong, AWS CLI does not error on a bad JMESPath expression, it silently returns null.

Read a single configuration value

Beginner
aws configure get region

↓ Click command to explain

When to use this

Check a single configuration value like region or output format for the active profile from within a script.

Check the installed AWS CLI version

Beginner
aws --version

↓ Click command to explain

When to use this

Confirm whether you are running AWS CLI v1 or v2 before following a tutorial, since many flags and behaviors differ between major versions.

List S3 buckets or objects

Beginner
aws s3 ls

↓ Click command to explain

When to use this

List all buckets or list objects inside a bucket.

Gotcha

aws s3 ls with no arguments lists all buckets, aws s3 ls s3://bucketname/ lists objects, the trailing slash matters for listing a prefix correctly.

List objects under a prefix recursively

Beginner
aws s3 ls s3://my-bucket/prefix/ --recursive

↓ Click command to explain

--recursive List all objects under the prefix, not just the top level
--human-readable Show sizes in KB, MB, GB instead of raw bytes

When to use this

List every object under a folder-like prefix in a bucket, not just the immediate children.

Copy a local file to S3

Beginner Destructive
aws s3 cp ./file.txt s3://my-bucket/folder/file.txt

↓ Click command to explain

When to use this

Upload a single local file to a specific key in an S3 bucket.

Gotcha

s3://bucket/path and s3://bucket/path/ are different, adding a trailing slash means copy into that prefix as a folder not replace that exact key.

Copy a file from S3 to local

Beginner
aws s3 cp s3://my-bucket/folder/file.txt ./file.txt

↓ Click command to explain

--recursive Download an entire prefix instead of a single object

When to use this

Download a single object from S3 to the local filesystem.

Sync a local folder up to S3

Beginner Destructive
aws s3 sync ./local-folder s3://my-bucket/prefix/

↓ Click command to explain

--delete Remove destination files that no longer exist in the source
--dryrun Preview exactly what would change without executing anything
--exclude / --include Filter which files are synced by glob pattern

When to use this

Upload only new or changed files from a local folder to a bucket, useful for deploying static sites.

Gotcha

Always run with --dryrun before the first time you use --delete on a production bucket, sync with --delete permanently removes files with no undo.

Sync an S3 prefix down to local

Beginner
aws s3 sync s3://my-bucket/prefix/ ./local-folder

↓ Click command to explain

When to use this

Pull down only new or changed objects from a bucket to a local folder, such as restoring a backup.

Delete objects from S3

Intermediate Destructive
aws s3 rm s3://my-bucket/folder/ --recursive

↓ Click command to explain

--recursive Delete every object under the prefix instead of a single object
--dryrun Preview which objects would be deleted without deleting them

When to use this

Remove an object or an entire folder-like prefix of objects from a bucket.

Gotcha

There is no trash or undo in S3, deleted objects are gone, always use --dryrun first and double check the prefix before running without it.

Create a new S3 bucket

Beginner Destructive
aws s3 mb s3://my-new-bucket --region us-east-1

↓ Click command to explain

When to use this

Create a brand-new S3 bucket in a specific region.

Gotcha

Bucket names are globally unique across all AWS accounts, if the name is taken you get an error with no suggestion.

Delete an S3 bucket

Advanced Destructive
aws s3 rb s3://my-bucket --force

↓ Click command to explain

--force Delete all objects in the bucket first, then delete the bucket itself

When to use this

Permanently remove an empty or non-empty bucket, such as tearing down a temporary environment.

Gotcha

This fails on a versioned bucket even with --force since old versions remain, you must delete all object versions first with list-object-versions and delete-objects.

Generate a presigned URL

Intermediate
aws s3 presign s3://my-bucket/file.txt --expires-in 3600

↓ Click command to explain

When to use this

Generate a temporary public URL to share a private S3 object without changing bucket permissions.

Gotcha

The URL is valid for anyone who has it until it expires, it uses your current credentials so if those expire before the URL does the URL stops working.

Check if an object exists and view its metadata

Intermediate
aws s3api head-object --bucket my-bucket --key folder/file.txt

↓ Click command to explain

When to use this

Check if an object exists and see its metadata without downloading it.

Gotcha

Returns a 404 error if the object does not exist which is a useful existence check in scripts.

List all versions of all objects

Advanced
aws s3api list-object-versions --bucket my-bucket

↓ Click command to explain

When to use this

See all versions of all objects in a versioned bucket, required before you can fully delete a versioned bucket.

Gotcha

aws s3 rb --force does not work on versioned buckets, you must delete all versions first using list-object-versions and delete-objects in a loop.

View a bucket's resource policy

Intermediate
aws s3api get-bucket-policy --bucket my-bucket

↓ Click command to explain

When to use this

Inspect the JSON resource policy attached to a bucket to audit who can access it.

Set an object's access control list

Advanced Destructive
aws s3api put-object-acl --bucket my-bucket --key file.txt --acl public-read

↓ Click command to explain

When to use this

Make a specific object publicly readable via a canned ACL rather than a bucket-wide policy.

Gotcha

Bucket-level Block Public Access settings override object ACLs, if Block Public Access is enabled making an object public-read via ACL silently fails to make it public.

Get one raw page of results without auto-pagination

Intermediate
aws s3api list-objects-v2 --bucket my-bucket --no-paginate

↓ Click command to explain

--no-paginate Disable the CLI's automatic looping through every page of results

When to use this

Get one raw page of API results without the CLI looping through all pages automatically.

Gotcha

Combining --page-size and --max-items with different values can cause missing or duplicated items, if you use both keep them equal.

Limit results and resume pagination manually

Intermediate
aws s3api list-objects-v2 --bucket my-bucket --max-items 100

↓ Click command to explain

--max-items Return at most this many results, along with a NextToken if more exist
--starting-token Resume a previous paginated call using the NextToken it returned

When to use this

Get only the first 100 results and use the returned NextToken with --starting-token to resume pagination in the next call.

List all EC2 instances

Beginner
aws ec2 describe-instances --query "Reservations[].Instances[].{ID:InstanceId,State:State.Name,Type:InstanceType}" --output table

↓ Click command to explain

--query Reservations[].Instances[].{...} Project a readable summary instead of the raw nested JSON
--filters Name=instance-state-name,Values=running Show only instances in a specific state

When to use this

List all EC2 instances and their current state in your account and region.

Gotcha

The raw output is deeply nested JSON that is almost unreadable without a --query expression, always add --query and --output table when reading interactively.

List only running instances

Intermediate
aws ec2 describe-instances --filters Name=instance-state-name,Values=running --query "Reservations[].Instances[].[InstanceId,InstanceType,PublicIpAddress]" --output table

↓ Click command to explain

When to use this

Get a quick table of instance ID, type, and public IP for every currently running instance.

Start a stopped instance

Beginner Destructive
aws ec2 start-instances --instance-ids i-1234567890abcdef0

↓ Click command to explain

When to use this

Power on an instance that was previously stopped.

Stop a running instance

Beginner Destructive
aws ec2 stop-instances --instance-ids i-1234567890abcdef0

↓ Click command to explain

When to use this

Shut down an instance to stop paying for compute while keeping its EBS volumes and configuration.

Gotcha

Stopping an instance does not delete it or its EBS volumes, you continue to pay for EBS storage while stopped.

Terminate an instance permanently

Advanced Destructive
aws ec2 terminate-instances --instance-ids i-1234567890abcdef0

↓ Click command to explain

When to use this

Permanently destroy an instance that is no longer needed.

Gotcha

This permanently deletes the instance and by default also deletes any EBS root volumes with the DeleteOnTermination flag set, there is no undo and no confirmation prompt.

Launch a new EC2 instance

Advanced Destructive
aws ec2 run-instances --image-id ami-12345678 --instance-type t3.micro --key-name my-keypair --security-group-ids sg-12345678 --subnet-id subnet-12345678 --count 1

↓ Click command to explain

When to use this

Launch one or more new EC2 instances from an AMI with a specific instance type, key pair, and network configuration.

Gotcha

You will be billed immediately once the instance enters the running state.

List your own AMIs

Intermediate
aws ec2 describe-images --owners self --query "Images[*].{ID:ImageId,Name:Name}" --output table

↓ Click command to explain

--owners self Only show AMIs owned by your account instead of all public AMIs

When to use this

List AMIs you own in the current region.

Gotcha

Without --owners self this queries public AMIs which returns thousands of results and is very slow.

Tag an EC2 resource

Beginner Destructive
aws ec2 create-tags --resources i-1234567890abcdef0 --tags Key=Name,Value=my-server

↓ Click command to explain

When to use this

Add a Name tag or any custom tag to an instance, volume, or other taggable EC2 resource.

View a security group's rules

Beginner
aws ec2 describe-security-groups --group-ids sg-12345678

↓ Click command to explain

When to use this

Inspect the inbound and outbound rules of a specific security group.

Open a port on a security group

Intermediate Destructive
aws ec2 authorize-security-group-ingress --group-id sg-12345678 --protocol tcp --port 22 --cidr 0.0.0.0/0

↓ Click command to explain

When to use this

Allow inbound traffic on a specific port and protocol, such as opening SSH access to an instance.

Gotcha

0.0.0.0/0 opens the port to the entire internet, always restrict to your IP or a specific CIDR in production.

List EC2 key pairs

Beginner
aws ec2 describe-key-pairs

↓ Click command to explain

When to use this

See which SSH key pairs are registered in the current region.

Create a new SSH key pair

Intermediate Destructive
aws ec2 create-key-pair --key-name my-keypair --query KeyMaterial --output text > my-keypair.pem && chmod 400 my-keypair.pem

↓ Click command to explain

When to use this

Generate a brand-new key pair for SSH access to future EC2 instances.

Gotcha

AWS only shows you the private key material once at creation time, if you lose this file you cannot recover the key and must create a new one.

Find unattached EBS volumes

Beginner
aws ec2 describe-volumes --filters Name=status,Values=available

↓ Click command to explain

When to use this

Find detached EBS volumes you are paying for but not using.

List your EBS snapshots

Beginner
aws ec2 describe-snapshots --owner-ids self

↓ Click command to explain

When to use this

Review existing EBS snapshots for backup auditing or cost review.

Filter and project fields with JMESPath in one query

Advanced
aws ec2 describe-instances --query "Reservations[].Instances[?State.Name=='running'].[InstanceId,Tags[?Key=='Name'].Value|[0]]" --output text

↓ Click command to explain

When to use this

Filter EC2 instances by state and extract specific fields in one query.

Gotcha

If any part of your JMESPath expression has a typo AWS returns null with no error message, test your query incrementally adding one part at a time.

List IAM users

Beginner
aws iam list-users --query "Users[*].{User:UserName,Created:CreateDate}" --output table

↓ Click command to explain

When to use this

See every IAM user in the account along with when each one was created.

Create an IAM user

Intermediate Destructive
aws iam create-user --user-name newuser

↓ Click command to explain

When to use this

Create a new IAM identity for a person or service that needs AWS access.

Gotcha

Creating a user does not give them any permissions or a way to log in, you must also create access keys or a login profile and attach policies separately.

Create an access key for a user

Intermediate Destructive
aws iam create-access-key --user-name myuser

↓ Click command to explain

When to use this

Generate programmatic access credentials for an IAM user.

Gotcha

The secret access key is only shown once at creation time, save it immediately, you cannot retrieve it again and must create a new key pair if lost.

Attach a managed policy to a user

Intermediate Destructive
aws iam attach-user-policy --user-name myuser --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

↓ Click command to explain

When to use this

Grant an IAM user permissions by attaching an AWS managed or customer managed policy.

Gotcha

Attaching AdministratorAccess to a user instead of scoping to minimum required permissions is the most common IAM security mistake.

List policies attached to a user

Beginner
aws iam list-attached-user-policies --user-name myuser

↓ Click command to explain

When to use this

Audit exactly which managed policies are attached to a specific user.

Create an IAM role

Advanced Destructive
aws iam create-role --role-name my-role --assume-role-policy-document file://trust-policy.json

↓ Click command to explain

When to use this

Create a role that a service or another account can assume, defined by a trust policy document.

Gotcha

The trust policy controls who can assume the role, confusing trust policy with permissions policy is the most common IAM conceptual error.

Attach a managed policy to a role

Intermediate Destructive
aws iam attach-role-policy --role-name my-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

↓ Click command to explain

When to use this

Grant a role the permissions it needs by attaching a managed policy.

Create a customer managed policy

Advanced Destructive
aws iam create-policy --policy-name my-policy --policy-document file://policy.json

↓ Click command to explain

When to use this

Define a reusable custom permissions policy from a local JSON document.

Test whether an identity can perform an action

Advanced
aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::123456789012:user/myuser --action-names s3:GetObject --resource-arns arn:aws:s3:::my-bucket/*

↓ Click command to explain

When to use this

Test whether an IAM identity has permission to perform an action before deploying code that needs it.

Gotcha

Most developers do not know this command exists and instead find out about missing permissions by running the actual operation and getting a 403.

List IAM roles

Beginner
aws iam list-roles --query "Roles[*].{Name:RoleName,ARN:Arn}" --output table

↓ Click command to explain

When to use this

See every IAM role in the account and its ARN.

View a role's details

Beginner
aws iam get-role --role-name my-role

↓ Click command to explain

When to use this

Inspect a role's trust policy and metadata.

Delete an IAM access key

Intermediate Destructive
aws iam delete-access-key --user-name myuser --access-key-id AKIAIOSFODNN7EXAMPLE

↓ Click command to explain

When to use this

Revoke a specific access key, such as one that leaked or is being rotated out.

Check the currently assumed identity

Beginner
aws sts get-caller-identity

↓ Click command to explain

When to use this

The single most important debugging command in the entire AWS CLI, run this whenever something is failing with auth or permission errors.

Assume an IAM role

Advanced Destructive
aws sts assume-role --role-arn arn:aws:iam::123456789012:role/my-role --role-session-name my-session

↓ Click command to explain

--role-session-name Required in practice, as a name identifying this temporary session in logs and CloudTrail
--duration-seconds Extend the session length beyond the default 1 hour, up to the role's configured maximum

When to use this

Obtain temporary credentials for a role, such as a cross-account role, for the current session.

Gotcha

The --role-session-name parameter is required in practice even though it looks optional, default session duration is 1 hour which may be too short for long-running scripts, use --duration-seconds to extend up to the role's maximum.

Assume a role and export credentials into the shell

Advanced Destructive
creds=$(aws sts assume-role --role-arn arn:aws:iam::123456789012:role/my-role --role-session-name my-session --query Credentials --output json) && export AWS_ACCESS_KEY_ID=$(echo $creds | jq -r .AccessKeyId) && export AWS_SECRET_ACCESS_KEY=$(echo $creds | jq -r .SecretAccessKey) && export AWS_SESSION_TOKEN=$(echo $creds | jq -r .SessionToken)

↓ Click command to explain

When to use this

Assume a role and automatically export the temporary credentials into your shell environment for immediate use.

Gotcha

These environment variables override everything else in the credential chain, unset all three when done or your next command will use these temporary credentials even after they expire.

Configure automatic role assumption via a profile

Advanced
# ~/.aws/config [profile cross-account] role_arn = arn:aws:iam::123456789012:role/my-role source_profile = default

↓ Click command to explain

When to use this

The correct long-term way to work with assumed roles, AWS CLI automatically calls sts assume-role and refreshes credentials without any manual export.

Gotcha

This is the approach AWS recommends but most tutorials show the manual export method because it is faster to explain.

Get a session token with MFA

Advanced Destructive
aws sts get-session-token --duration-seconds 3600 --serial-number arn:aws:iam::123456789012:mfa/myuser --token-code 123456

↓ Click command to explain

When to use this

Get temporary credentials when MFA is required on your account.

Assume a role using a web identity token

Advanced Destructive
aws sts assume-role-with-web-identity --role-arn arn:aws:iam::123456789012:role/my-role --role-session-name my-session --web-identity-token $ID_TOKEN

↓ Click command to explain

When to use this

Federate into an AWS role using an OIDC token, such as the token GitHub Actions provides for keyless CI/CD deployments.

Gotcha

This is what powers GitHub Actions OIDC and similar keyless CI integrations, so no long-lived AWS access keys are stored anywhere.

Decode an encoded authorization failure message

Advanced
aws sts decode-authorization-message --encoded-message <encoded-message>

↓ Click command to explain

When to use this

Decode the long encoded message AWS returns for certain authorization denials to see exactly which permission was missing.

Gotcha

Some IAM denial errors return an opaque base64-like blob instead of a plain reason, this command is the only way to read what it actually says.

Get temporary credentials for a federated user

Advanced Destructive
aws sts get-federation-token --name my-federated-user --policy file://policy.json --duration-seconds 3600

↓ Click command to explain

When to use this

Issue short-lived, scoped-down credentials for a federated user or application, such as a third-party tool that needs temporary limited access.

List Lambda functions

Beginner
aws lambda list-functions --query "Functions[*].{Name:FunctionName,Runtime:Runtime,Modified:LastModified}" --output table

↓ Click command to explain

When to use this

See every Lambda function in the current region along with its runtime and last modified date.

Invoke a Lambda function synchronously

Intermediate Destructive
aws lambda invoke --function-name my-function --payload file://event.json --cli-binary-format raw-in-base64-out response.json

↓ Click command to explain

--cli-binary-format raw-in-base64-out Required in AWS CLI v2 when passing a JSON payload file, tells the CLI not to double-encode it

When to use this

Manually invoke a Lambda function with a test event and inspect its response.

Gotcha

--cli-binary-format raw-in-base64-out is required in AWS CLI v2 when passing a JSON payload, without it you get a validation error about base64 encoding, this is the most common Lambda invoke failure when following v1 tutorials on a v2 CLI.

Invoke a Lambda function asynchronously

Intermediate Destructive
aws lambda invoke --function-name my-function --invocation-type Event --payload file://event.json --cli-binary-format raw-in-base64-out response.json

↓ Click command to explain

--invocation-type Event Fire-and-forget async invocation instead of waiting for the result

When to use this

Trigger a Lambda function without waiting for it to finish, useful for background processing.

Gotcha

invocation-type Event means fire-and-forget async, the response.json will contain only a 202 status code not the function result, check CloudWatch Logs for the actual output.

Deploy new code to a Lambda function

Intermediate Destructive
aws lambda update-function-code --function-name my-function --zip-file fileb://function.zip

↓ Click command to explain

When to use this

Push a new deployment package to an existing Lambda function.

Gotcha

fileb:// with a b prefix reads the file as binary, using file:// for a zip file causes a corrupted upload that may silently fail or produce a broken deployment.

Create a new Lambda function

Advanced Destructive
aws lambda create-function --function-name my-function --runtime python3.12 --role arn:aws:iam::123456789012:role/lambda-role --handler lambda_function.lambda_handler --zip-file fileb://function.zip

↓ Click command to explain

When to use this

Create a brand-new Lambda function from a local deployment package.

View a Lambda function's configuration

Beginner
aws lambda get-function --function-name my-function

↓ Click command to explain

When to use this

Inspect a function's configuration, code location, and current state.

Create a public HTTPS endpoint for a function

Advanced Destructive
aws lambda create-function-url-config --function-name my-function --auth-type NONE

↓ Click command to explain

When to use this

Expose a Lambda function directly over HTTPS without setting up API Gateway.

Gotcha

auth-type NONE makes the function publicly invokable by anyone with the URL, use AWS_IAM for private endpoints.

List a function's event source mappings

Intermediate
aws lambda list-event-source-mappings --function-name my-function

↓ Click command to explain

When to use this

See which SQS queues, DynamoDB streams, or Kinesis streams are wired to trigger a function.

Delete a Lambda function

Advanced Destructive
aws lambda delete-function --function-name my-function

↓ Click command to explain

When to use this

Permanently remove a function that is no longer needed.

Gotcha

This immediately and permanently deletes the function and its configuration, there is no recycle bin or undo.

Grant another service permission to invoke a function

Advanced Destructive
aws lambda add-permission --function-name my-function --statement-id allow-s3 --action lambda:InvokeFunction --principal s3.amazonaws.com --source-arn arn:aws:s3:::my-bucket

↓ Click command to explain

When to use this

Allow an AWS service like S3 or EventBridge to invoke a Lambda function as part of an event trigger.

Authenticate Docker against ECR

Intermediate
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com

↓ Click command to explain

When to use this

Log Docker in to a private ECR registry so you can push or pull images.

Gotcha

The auth token is region-scoped, if you authenticate against us-east-1 and try to push to a repository in eu-west-1 it will fail with an unauthorized error, always specify the correct region.

Create an ECR repository

Intermediate Destructive
aws ecr create-repository --repository-name my-app

↓ Click command to explain

When to use this

Create a new private container image repository.

List ECR repositories

Beginner
aws ecr describe-repositories --query "repositories[*].{Name:repositoryName,URI:repositoryUri}" --output table

↓ Click command to explain

When to use this

See every ECR repository in the account and its full pull URI.

List images in a repository

Beginner
aws ecr list-images --repository-name my-app

↓ Click command to explain

When to use this

See every image digest and tag pushed to a repository.

Delete an image from ECR

Advanced Destructive
aws ecr batch-delete-image --repository-name my-app --image-ids imageTag=old-tag

↓ Click command to explain

When to use this

Remove old or unused image tags to reduce storage costs.

Gotcha

ECR does not automatically delete old images, untagged images accumulate and generate storage costs, set a lifecycle policy to automate cleanup.

List ECS clusters

Beginner
aws ecs list-clusters

↓ Click command to explain

When to use this

See every ECS cluster in the current region.

View an ECS service's status

Intermediate
aws ecs describe-services --cluster my-cluster --services my-service

↓ Click command to explain

When to use this

Check the running count, desired count, and deployment status of an ECS service.

Scale an ECS service

Intermediate Destructive
aws ecs update-service --cluster my-cluster --service my-service --desired-count 3

↓ Click command to explain

When to use this

Scale an ECS service up or down without redeploying.

Open a shell inside a running ECS task

Advanced
aws ecs execute-command --cluster my-cluster --task task-id --container my-container --interactive --command /bin/sh

↓ Click command to explain

When to use this

Debug a running ECS Fargate or EC2-backed task by getting an interactive shell inside its container.

Gotcha

This requires --enable-execute-command to have been set on the service or task definition AND the SSM Session Manager plugin installed locally, missing either one gives a confusing error that does not clearly identify which prerequisite is missing.

Configure kubectl for an EKS cluster

Intermediate
aws eks update-kubeconfig --region us-east-1 --name my-cluster

↓ Click command to explain

When to use this

Configure kubectl to connect to an EKS cluster so you can run kubectl commands against it.

Gotcha

If you run this with one IAM profile and then run kubectl commands under a different profile or role, kubectl will fail with You must be logged in to the server, the IAM identity used for update-kubeconfig must match or be mapped in the cluster's access configuration.

List EKS clusters

Beginner
aws eks list-clusters

↓ Click command to explain

When to use this

See every EKS cluster in the current region.

View an EKS cluster's details

Intermediate
aws eks describe-cluster --name my-cluster

↓ Click command to explain

When to use this

Inspect a cluster's endpoint, version, and networking configuration.

List VPCs

Beginner
aws ec2 describe-vpcs --query "Vpcs[*].{ID:VpcId,CIDR:CidrBlock}" --output table

↓ Click command to explain

When to use this

See every VPC in the current region along with its CIDR block.

List subnets

Beginner
aws ec2 describe-subnets --filters Name=vpc-id,Values=vpc-12345678

↓ Click command to explain

When to use this

List every subnet inside a specific VPC along with its availability zone and CIDR.

Create a new VPC

Advanced Destructive
aws ec2 create-vpc --cidr-block 10.0.0.0/16

↓ Click command to explain

When to use this

Create a new isolated network for a new environment or account.

Gotcha

A newly created VPC has no subnets, route tables, or internet gateway attached, it is an empty network shell until you build out the rest.

View route tables

Intermediate
aws ec2 describe-route-tables --filters Name=vpc-id,Values=vpc-12345678

↓ Click command to explain

When to use this

Inspect how traffic is routed within a VPC, such as whether a subnet has a route to an internet gateway.

List internet gateways

Intermediate
aws ec2 describe-internet-gateways

↓ Click command to explain

When to use this

Check which internet gateway is attached to a VPC when debugging why instances can't reach the internet.

List load balancers

Beginner
aws elbv2 describe-load-balancers --query "LoadBalancers[*].{Name:LoadBalancerName,DNS:DNSName,State:State.Code}" --output table

↓ Click command to explain

When to use this

See every Application or Network Load Balancer and its DNS name.

Check target group health

Intermediate
aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/my-targets/1234567890abcdef

↓ Click command to explain

When to use this

Debug why a load balancer is returning errors by checking whether its targets are passing health checks.

Gotcha

A target showing unhealthy usually means the health check path returns a non-200 response or the security group blocks the health check port, not that the instance itself is down.

List Route53 hosted zones

Beginner
aws route53 list-hosted-zones

↓ Click command to explain

When to use this

See every DNS hosted zone managed in the account.

List DNS records in a hosted zone

Intermediate
aws route53 list-resource-record-sets --hosted-zone-id Z1234567890ABC

↓ Click command to explain

When to use this

See every DNS record configured within a specific hosted zone.

Create or update a DNS record

Advanced Destructive
aws route53 change-resource-record-sets --hosted-zone-id Z1234567890ABC --change-batch file://change-batch.json

↓ Click command to explain

When to use this

Point a domain or subdomain at a new target, such as updating a CNAME after migrating a load balancer.

Gotcha

DNS changes take time to propagate based on the record's TTL, a low TTL before a planned migration makes future changes take effect faster.

List CloudWatch log groups

Beginner
aws logs describe-log-groups --query "logGroups[*].logGroupName" --output text

↓ Click command to explain

When to use this

See every log group in the account, such as Lambda function logs or ECS task logs.

Stream live logs

Beginner
aws logs tail /aws/lambda/my-function --follow

↓ Click command to explain

When to use this

Stream live logs from a Lambda function or any CloudWatch log group like a tail -f.

Gotcha

aws logs tail is a newer command that most developers do not know exists, it is far easier than get-log-events for live log monitoring.

Search log events by pattern

Intermediate
aws logs filter-log-events --log-group-name /aws/lambda/my-function --filter-pattern ERROR --start-time 1718400000000

↓ Click command to explain

When to use this

Search a log group for lines matching a specific pattern, such as ERROR, within a time range.

Gotcha

--start-time and --end-time are epoch milliseconds not seconds, passing seconds instead of milliseconds returns no results without an error message.

Run a CloudWatch Logs Insights query

Advanced
aws logs start-query --log-group-name /aws/lambda/my-function --start-time 1718400000 --end-time 1718486400 --query-string "fields @timestamp, @message | filter @message like /ERROR/ | sort @timestamp desc | limit 20"

↓ Click command to explain

When to use this

Run a CloudWatch Logs Insights query for powerful log analytics.

Gotcha

start-query returns a query ID immediately, you must then call get-query-results with that ID to retrieve the results once the query completes.

Retrieve Logs Insights query results

Advanced
aws logs get-query-results --query-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

↓ Click command to explain

When to use this

Fetch the results of a previously started CloudWatch Logs Insights query.

Gotcha

Call this in a loop until status is Complete, the query may take several seconds depending on log volume.

Start a shell session on an EC2 instance

Intermediate
aws ssm start-session --target i-1234567890abcdef0

↓ Click command to explain

When to use this

Get a shell on an EC2 instance without SSH or open inbound ports.

Gotcha

Requires the SSM agent running on the instance AND the Session Manager plugin installed on your local machine AND the instance to have an IAM role with AmazonSSMManagedInstanceCore, missing any of these three gives different errors.

Read a value from Parameter Store

Beginner
aws ssm get-parameter --name /my-app/database-url --with-decryption

↓ Click command to explain

When to use this

Read a configuration value or secret stored in Systems Manager Parameter Store.

Gotcha

--with-decryption is required for SecureString parameters, without it you get the encrypted value not the plaintext, the flag is silently ignored for String and StringList parameters so forgetting it only breaks SecureString.

Store a value in Parameter Store

Intermediate Destructive
aws ssm put-parameter --name /my-app/api-key --value mysecretvalue --type SecureString --overwrite

↓ Click command to explain

When to use this

Store or update a configuration value or encrypted secret in Parameter Store.

Run a shell command on EC2 instances remotely

Advanced Destructive
aws ssm send-command --document-name AWS-RunShellScript --targets Key=instanceids,Values=i-1234567890abcdef0 --parameters commands=["df -h"]

↓ Click command to explain

When to use this

Run a shell command on one or more EC2 instances without SSH.

Create a CloudWatch alarm

Advanced Destructive
aws cloudwatch put-metric-alarm --alarm-name high-cpu --metric-name CPUUtilization --namespace AWS/EC2 --statistic Average --period 300 --threshold 80 --comparison-operator GreaterThanThreshold --evaluation-periods 2 --alarm-actions arn:aws:sns:us-east-1:123456789012:my-topic --dimensions Name=InstanceId,Value=i-1234567890abcdef0

↓ Click command to explain

When to use this

Set up an alarm that notifies an SNS topic when a metric like CPU utilization crosses a threshold.

Read historical metric data

Intermediate
aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization --dimensions Name=InstanceId,Value=i-1234567890abcdef0 --start-time 2026-07-01T00:00:00Z --end-time 2026-07-02T00:00:00Z --period 3600 --statistics Average

↓ Click command to explain

When to use this

Pull historical metric values for a resource over a time range, such as average CPU over the last day.

List CloudWatch alarms

Beginner
aws cloudwatch describe-alarms --query "MetricAlarms[*].{Name:AlarmName,State:StateValue}" --output table

↓ Click command to explain

When to use this

See every configured alarm and whether it is currently OK, ALARM, or INSUFFICIENT_DATA.

List RDS database instances

Beginner
aws rds describe-db-instances --query "DBInstances[*].{ID:DBInstanceIdentifier,Status:DBInstanceStatus,Engine:Engine}" --output table

↓ Click command to explain

When to use this

See every RDS instance in the account, its engine, and its current status.

Create a manual RDS snapshot

Intermediate Destructive
aws rds create-db-snapshot --db-instance-identifier mydb --db-snapshot-identifier mydb-backup-2026-07-05

↓ Click command to explain

When to use this

Take a manual, on-demand backup of a database before a risky migration or change.

Delete an RDS instance

Advanced Destructive
aws rds delete-db-instance --db-instance-identifier mydb --skip-final-snapshot

↓ Click command to explain

When to use this

Permanently decommission a database instance that is no longer needed.

Gotcha

--skip-final-snapshot is commonly copied from tutorial and CI scripts but means your data is permanently destroyed with no backup, remove this flag on production databases and let AWS create a final snapshot before deletion.

Restore a database from a snapshot

Advanced Destructive
aws rds restore-db-instance-from-db-snapshot --db-instance-identifier mydb-restored --db-snapshot-identifier mydb-backup-2026-07-05 --db-instance-class db.t3.micro

↓ Click command to explain

When to use this

Create a new database instance from an existing snapshot, such as recovering from an incident or standing up a test copy.

Deploy or update a CloudFormation stack

Intermediate Destructive
aws cloudformation deploy --template-file template.yaml --stack-name my-stack --capabilities CAPABILITY_IAM

↓ Click command to explain

When to use this

Create or update infrastructure defined in a CloudFormation template idempotently.

Gotcha

deploy is idempotent and creates the stack if it does not exist or updates it if it does, this is almost always what you want, use create-stack only if you specifically need to fail when the stack already exists.

Read a CloudFormation stack's outputs

Beginner
aws cloudformation describe-stacks --stack-name my-stack --query "Stacks[0].Outputs"

↓ Click command to explain

When to use this

Read the output values from a CloudFormation stack like a load balancer URL or database endpoint.

Debug a failed CloudFormation deployment

Intermediate
aws cloudformation describe-stack-events --stack-name my-stack --query "StackEvents[?ResourceStatus=='FAILED']" --output table

↓ Click command to explain

When to use this

Find out why a CloudFormation stack deployment failed.

Delete a CloudFormation stack

Advanced Destructive
aws cloudformation delete-stack --stack-name my-stack

↓ Click command to explain

When to use this

Tear down every resource defined in a stack, such as decommissioning an entire environment.

Gotcha

This deletes every resource defined in the stack, for stacks containing RDS databases or S3 buckets the deletion may be blocked by DeletionPolicy or non-empty bucket errors.

Read a secret's value

Intermediate
aws secretsmanager get-secret-value --secret-id my-secret --query SecretString --output text | jq -r .password

↓ Click command to explain

When to use this

Retrieve and decode a specific key from a JSON-formatted secret in Secrets Manager.

Gotcha

SecretString is itself a JSON string not a JSON object, you cannot use --query to navigate into keys inside it directly, pipe the output to jq to extract a nested key.

Create a new secret

Intermediate Destructive
aws secretsmanager create-secret --name my-secret --secret-string file://secret.json

↓ Click command to explain

When to use this

Store a new credential or API key in Secrets Manager.

Update an existing secret's value

Intermediate Destructive
aws secretsmanager put-secret-value --secret-id my-secret --secret-string newvalue

↓ Click command to explain

When to use this

Rotate or update the value of an existing secret without changing its ARN or name.

List all secrets

Beginner
aws secretsmanager list-secrets --query "SecretList[*].{Name:Name,ARN:ARN}" --output table

↓ Click command to explain

When to use this

See every secret stored in Secrets Manager for the account and region.

Reference Tools

This tool now has its own dedicated page with an interactive debugger → Visit AWS Credential Chain Debugger

AWS resolves credentials in this exact order. The first source that has valid credentials wins. This is the root cause of most AWS CLI authentication errors.

1

Command line options

--profile myprofile or --region us-east-1

These override everything else. If you pass --profile on the command line it wins regardless of environment variables or config files.

2

Environment variables

AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_PROFILE

If any of these are set in your shell they will be used. This is the most common cause of using the wrong credentials, which are often a leftover export from a previous assume-role session.

3

AWS SSO session cache

~/.aws/sso/cache/

If you use aws configure sso and the session has not expired the cached token is used here. If it has expired you get a confusing error rather than a prompt to log in again. Fix with aws sso login --profile yourprofile.

4

Named profile in config and credentials files

~/.aws/config and ~/.aws/credentials

The profile named default is used automatically. The most common error here is a profile that exists in credentials but not in config or vice versa. Run aws configure list-profiles to see what is actually there.

5

Assumed role via source_profile

role_arn + source_profile in ~/.aws/config

AWS CLI automatically calls sts assume-role and refreshes the temporary credentials. This is the right way to work with assumed roles and avoids manual export of credentials entirely.

6

EC2 instance profile or ECS task role

Metadata service at 169.254.169.254

Only available when running on EC2, ECS, Lambda, or similar AWS compute. If you are running locally and reach this step it means none of the above sources found credentials and the call will fail.

Debug Commands

Check which identity is currently active

aws sts get-caller-identity

Run this before any destructive command. Shows your Account ID, UserId, and ARN. If this fails your credentials are not configured correctly.

Check which profile is active and where credentials are coming from

aws configure list

Shows whether each configuration value comes from an env variable, config file, or default. The source column tells you exactly which file or variable is winning.

List all configured profiles

aws configure list-profiles

If your profile is not in this list the error will be The config profile X could not be found.

Check active credentials for a specific profile

aws sts get-caller-identity --profile myprofile

Replace myprofile with your profile name. If this returns an error the profile credentials are expired or misconfigured.

Not sure which S3 command to use? Answer two questions.

Scenario Command Note
Copy one file to or from S3
aws s3 cp
aws s3 cp ./file.txt s3://my-bucket/folder/file.txt
For single files only. Does not recurse into directories unless you add --recursive.
Mirror a local folder to S3 or S3 to local keeping both in sync
aws s3 sync
aws s3 sync ./local-folder s3://my-bucket/prefix/ --delete
Only copies files that are new or changed. --delete removes files from the destination that no longer exist in the source. Always run with --dryrun first on production buckets.
Move a file and delete the source after upload
aws s3 mv
aws s3 mv s3://source-bucket/file.txt s3://dest-bucket/file.txt
Destructive on the source. There is no undo. Use cp if you want to keep the original.
Delete files from S3
aws s3 rm
aws s3 rm s3://my-bucket/folder/ --recursive
Always use --dryrun first. Without --recursive only deletes a single object. With --recursive deletes everything under the prefix. There is no trash or undo in S3.
Advanced operations like presigned URLs versioning ACLs multipart uploads
aws s3api
aws s3api put-object --bucket my-bucket --key file.txt --body file.txt
The s3api subcommand maps directly to S3 REST API operations. Use it when the high-level aws s3 commands do not expose the option you need.

Frequently Asked Questions

The AWS CLI is a single command-line tool that wraps every AWS service API behind one consistent interface, and for engineers who manage AWS infrastructure day to day it is often faster and more precise than clicking through the console. Almost every action available in the AWS Management Console has a direct CLI equivalent, but the CLI adds what the console cannot: it is scriptable, reproducible, and pipeable into other Unix tools like jq and grep, which makes it the backbone of CI/CD pipelines, cron jobs, and one-off investigations alike. Whether the task is checking why a Lambda function is failing, rotating a secret, or auditing which IAM policies are attached to a role, the CLI turns what would be several minutes of console navigation into a single reusable command.

The reason the AWS CLI shows up constantly in daily engineering work is that AWS environments are rarely static. Auto-scaling groups launch and terminate instances continuously, Lambda functions deploy multiple times a day, and IAM permissions get adjusted as teams and services change. Engineers are constantly checking the current state of the world: is this instance still running, did that deployment actually update the function code, does this role really have the permission it needs. Commands like aws sts get-caller-identity, aws ec2 describe-instances, and aws logs tail form the same kind of always-reached-for read loop that kubectl get and docker ps represent in their respective ecosystems, and most real AWS CLI usage is those few commands repeated with different arguments.

The single most important mental model for working with the AWS CLI is the credential chain: the ordered list of places the CLI looks for credentials before it gives up. Command-line flags beat environment variables, which beat the SSO cache, which beats named profiles in your config files, which beats an assumed role, which beats the EC2 or ECS metadata service. Almost every confusing AWS CLI authentication error traces back to a credential source further up this chain winning unexpectedly, whether a leftover AWS_PROFILE environment variable from a previous session, or an SSO token that quietly expired. Once that ordered list clicks, debugging authentication stops being guesswork: run aws configure list and aws sts get-caller-identity, and the winning source is right there in the output.

Three mistakes account for the overwhelming majority of AWS CLI frustration. The first is forgetting that --query returns null silently on a bad JMESPath expression instead of raising an error, which makes a typo in a query look like missing data. The second is confusing s3 cp with s3 sync: cp only touches the exact file or prefix you name, while sync recursively mirrors an entire folder and, combined with --delete, can permanently remove files that exist only in the destination. The third is running a destructive command like terminate-instances or delete-db-instance against the wrong account entirely, because a stale AWS_PROFILE or an expired SSO session silently fell back to a different set of credentials. Running aws sts get-caller-identity before any destructive command is the single habit that prevents the most expensive version of this mistake.