# AWS CLI User Guide

The AWS Command Line Interface (AWS CLI) is a unified tool to manage your AWS services from the terminal. With a single tool, you can control multiple AWS services and automate them through scripts. This guide covers AWS CLI **version 1** (v1.44.85).

---

## 1. Quick Start

Get up and running in under five minutes:

```bash
# Install
pip install awscli

# Configure credentials
aws configure
```

You will be prompted for four values:

```
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-east-1
Default output format [None]: json
```

Test the installation:

```bash
aws --version
```

Expected output:

```
aws-cli/1.44.85 Python/3.11.6 Linux/6.1.0 botocore/1.42.95
```

> [!TIP]
> Run `aws sts get-caller-identity` to verify your credentials are working. If it returns your account ID, ARN, and user ID, you are properly authenticated.

---

## 2. Installation

### Requirements

- Python 3.9 or later
- pip (Python package manager)

### Install via pip

```bash
pip install awscli
```

To install a specific version:

```bash
pip install awscli==1.44.85
```

### Upgrade

```bash
pip install --upgrade awscli
```

### Verify installation

```bash
aws --version
```

### Dependencies

AWS CLI v1 installs the following dependencies automatically:

| Package | Version |
|---------|---------|
| botocore | 1.42.95 |
| docutils | latest compatible |
| s3transfer | latest compatible |
| PyYAML | latest compatible |
| colorama | latest compatible |
| rsa | latest compatible |

> [!IMPORTANT]
> AWS CLI v1 and v2 are separate products. This guide documents **v1 only**. Do not mix installation methods or expect v2-specific features (such as the built-in installer or auto-prompt) to work with v1.

### Shell Completion

Enable tab completion for commands and parameters:

**Bash:**

```bash
complete -C aws_completer aws
```

Add this line to your `~/.bashrc` to make it persistent.

**Zsh:**

```bash
source aws_zsh_completer.sh
```

Add this line to your `~/.zshrc`.

---

## 3. Configuration

### Configuration Files

AWS CLI uses two files:

| File | Purpose |
|------|---------|
| `~/.aws/credentials` | Access keys (shared across SDKs) |
| `~/.aws/config` | Region, output format, profiles, other settings |

### Initial Setup

```bash
aws configure
```

This creates both files with your default profile. To configure a named profile:

```bash
aws configure --profile production
```

### Config File Format

**`~/.aws/credentials`:**

```ini
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

[production]
aws_access_key_id = AKIAI44QH8DHBEXAMPLE
aws_secret_access_key = je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY
```

**`~/.aws/config`:**

```ini
[default]
region = us-east-1
output = json

[profile production]
region = eu-west-1
output = table
```

> [!NOTE]
> In the credentials file, section names are just `[profilename]`. In the config file, non-default profiles must use the prefix `[profile profilename]`.

### Environment Variables

Environment variables override config file values:

| Variable | Purpose |
|----------|---------|
| `AWS_ACCESS_KEY_ID` | Access key |
| `AWS_SECRET_ACCESS_KEY` | Secret key |
| `AWS_DEFAULT_REGION` | Default region |
| `AWS_DEFAULT_OUTPUT` | Output format (json/text/table) |
| `AWS_CONFIG_FILE` | Path to config file |
| `AWS_SHARED_CREDENTIALS_FILE` | Path to credentials file |
| `AWS_CA_BUNDLE` | Path to CA certificate bundle |
| `AWS_DATA_PATH` | Additional data search paths |

### Profiles

Use the `--profile` flag to switch between configured profiles:

```bash
aws s3 ls --profile production
```

### SSO Login

If your organization uses AWS SSO:

```bash
aws sso login --profile my-sso-profile
```

### Command Aliases

Create shortcuts in `~/.aws/cli/alias` (INI format):

```ini
[toplevel]
whoami = sts get-caller-identity
running = ec2 describe-instances --filters Name=instance-state-name,Values=running
myip = !curl -s https://checkip.amazonaws.com
```

Aliases in the `[toplevel]` section are invoked as:

```bash
aws whoami
aws running
```

External aliases (prefixed with `!`) run shell commands:

```bash
aws myip
```

---

## 4. Core Usage

### Command Structure

```
aws [global-options] <service> <operation> [parameters]
```

Examples:

```bash
aws ec2 describe-instances
aws s3 ls
aws lambda list-functions --region us-west-2
```

### Global Options

| Option | Description |
|--------|-------------|
| `--version` | Display version and exit |
| `--output` | Output format: `json`, `text`, or `table` |
| `--region` | AWS region to target |
| `--profile` | Named profile to use |
| `--endpoint-url` | Override service endpoint URL |
| `--no-verify-ssl` | Disable SSL certificate verification |
| `--no-paginate` | Disable automatic pagination |
| `--query` | JMESPath query to filter output |
| `--debug` | Enable debug logging |
| `--cli-read-timeout` | Read timeout in seconds |
| `--cli-connect-timeout` | Connection timeout in seconds |
| `--no-sign-request` | Do not sign requests (for public resources) |
| `--ca-bundle` | Path to CA certificate bundle |
| `--color` | Color output: `on`, `off`, or `auto` |

### Output Formats

**JSON** (default) -- structured, machine-readable:

```bash
aws iam list-users --output json
```

```json
{
    "Users": [
        {
            "UserName": "alice",
            "UserId": "AIDAEXAMPLE1",
            "Arn": "arn:aws:iam::123456789012:user/alice"
        }
    ]
}
```

**Table** -- human-readable, formatted columns:

```bash
aws iam list-users --output table
```

```
------------------------------------------------------------
|                        ListUsers                         |
+----------+----------------+-----------------------------+
| UserName |    UserId      |            Arn              |
+----------+----------------+-----------------------------+
|  alice   |  AIDAEXAMPLE1  | arn:aws:iam::123...:user/al |
+----------+----------------+-----------------------------+
```

**Text** -- tab-delimited, suitable for `grep`/`awk`/`cut`:

```bash
aws iam list-users --output text
```

```
USERS   alice   AIDAEXAMPLE1    arn:aws:iam::123456789012:user/alice
```

### Filtering Output with --query

The `--query` option accepts JMESPath expressions:

```bash
# Get just instance IDs
aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId'

# Filter by state
aws ec2 describe-instances \
  --query 'Reservations[].Instances[?State.Name==`running`].InstanceId'

# Format as table with selected fields
aws ec2 describe-instances \
  --query 'Reservations[].Instances[].[InstanceId, State.Name, InstanceType]' \
  --output table
```

### Input Methods

**Inline JSON:**

```bash
aws ec2 create-tags --resources i-1234567890abcdef0 \
  --tags '[{"Key":"Name","Value":"MyInstance"}]'
```

**Shorthand syntax:**

```bash
aws ec2 create-tags --resources i-1234567890abcdef0 \
  --tags Key=Name,Value=MyInstance
```

**From a file (file:// prefix):**

```bash
aws ec2 run-instances --cli-input-json file://params.json
```

**Binary file content (fileb:// prefix):**

```bash
aws lambda update-function-code \
  --function-name my-function \
  --zip-file fileb://function.zip
```

> [!NOTE]
> Use `file://` for text content (UTF-8) and `fileb://` for binary content (zip files, images, etc.).

### Getting Help

```bash
# General help
aws help

# Service help (lists all operations)
aws ec2 help

# Operation help (shows parameters, examples)
aws ec2 describe-instances help
```

### Waiters

Wait for a resource to reach a specific state before proceeding:

```bash
aws ec2 wait instance-running --instance-ids i-1234567890abcdef0
```

The command blocks until the instance is running (or times out). Useful in scripts to ensure sequential operations succeed.

### Pagination

By default, AWS CLI automatically paginates results. To get all results in one call:

```bash
aws s3api list-objects --bucket my-bucket --no-paginate
```

---

## 5. Common Tasks

### 5.1 S3: Upload a File

```bash
aws s3 cp myfile.txt s3://my-bucket/myfile.txt
```

Expected output:

```
upload: ./myfile.txt to s3://my-bucket/myfile.txt
```

Upload an entire directory:

```bash
aws s3 cp ./local-dir s3://my-bucket/prefix/ --recursive
```

### 5.2 S3: Download Files

```bash
aws s3 cp s3://my-bucket/myfile.txt ./myfile.txt
```

Download a directory:

```bash
aws s3 cp s3://my-bucket/prefix/ ./local-dir/ --recursive
```

### 5.3 S3: Sync a Directory

Sync uploads only changed files (like rsync):

```bash
aws s3 sync ./local-dir s3://my-bucket/backup/
```

Sync from S3 to local:

```bash
aws s3 sync s3://my-bucket/backup/ ./local-dir/
```

Delete files in destination that do not exist in source:

```bash
aws s3 sync ./local-dir s3://my-bucket/backup/ --delete
```

### 5.4 S3: List and Remove

List buckets:

```bash
aws s3 ls
```

List objects in a bucket:

```bash
aws s3 ls s3://my-bucket/
aws s3 ls s3://my-bucket/prefix/ --recursive
```

Remove a file:

```bash
aws s3 rm s3://my-bucket/myfile.txt
```

Remove all objects with a prefix:

```bash
aws s3 rm s3://my-bucket/prefix/ --recursive
```

### 5.5 S3: Create and Delete Buckets

```bash
aws s3 mb s3://my-new-bucket
aws s3 rb s3://my-empty-bucket
aws s3 rb s3://my-bucket --force   # removes all objects first
```

### 5.6 EC2: Launch an Instance

```bash
aws ec2 run-instances \
  --image-id ami-0abcdef1234567890 \
  --instance-type t3.micro \
  --key-name my-keypair \
  --security-group-ids sg-0123456789abcdef0 \
  --count 1
```

### 5.7 EC2: List Running Instances

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

### 5.8 EC2: Stop and Terminate

```bash
aws ec2 stop-instances --instance-ids i-1234567890abcdef0
aws ec2 terminate-instances --instance-ids i-1234567890abcdef0
```

### 5.9 Lambda: Deploy a Function

```bash
aws lambda create-function \
  --function-name my-function \
  --runtime python3.12 \
  --role arn:aws:iam::123456789012:role/lambda-role \
  --handler lambda_function.handler \
  --zip-file fileb://function.zip
```

Update function code:

```bash
aws lambda update-function-code \
  --function-name my-function \
  --zip-file fileb://function.zip
```

### 5.10 Lambda: Invoke a Function

```bash
aws lambda invoke \
  --function-name my-function \
  --payload '{"key": "value"}' \
  output.json
```

### 5.11 IAM: Manage Users

```bash
# Create user
aws iam create-user --user-name developer

# Create access key
aws iam create-access-key --user-name developer

# Attach policy
aws iam attach-user-policy \
  --user-name developer \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

# List users
aws iam list-users --output table
```

### 5.12 CloudFormation: Deploy a Stack

```bash
aws cloudformation create-stack \
  --stack-name my-stack \
  --template-body file://template.yaml \
  --capabilities CAPABILITY_IAM

# Wait for completion
aws cloudformation wait stack-create-complete --stack-name my-stack
```

### 5.13 Logs: Tail CloudWatch Logs

```bash
aws logs get-log-events \
  --log-group-name /aws/lambda/my-function \
  --log-stream-name '2026/05/06/[$LATEST]abc123' \
  --limit 50
```

### 5.14 STS: Check Current Identity

```bash
aws sts get-caller-identity
```

Expected output:

```json
{
    "UserId": "AIDAEXAMPLE",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/myuser"
}
```

### 5.15 CloudFront: Create an Invalidation

```bash
aws cloudfront create-invalidation \
  --distribution-id E1A2B3C4D5E6F7 \
  --paths "/index.html" "/css/*"
```

---

## 6. Troubleshooting

### 6.1 "groff or mandoc" Not Found

**Error:**

```
Could not find executable named "groff" or "mandoc"
```

**Cause:** The help system renders man pages using `groff` or `mandoc`, which are not installed.

**Solution:**

```bash
# Ubuntu/Debian
sudo apt install groff

# macOS (usually pre-installed, but if missing)
brew install groff

# Amazon Linux / RHEL
sudo yum install groff
```

**Prevention:** Install groff as part of your base system provisioning.

### 6.2 "Unable to load paramfile" Errors

**Error:**

```
Unable to load paramfile file://config.json: [Errno 2] No such file or directory
```

**Cause:** The `file://` path is relative to your current working directory, or the file does not exist.

**Solution:** Use an absolute path or verify your working directory:

```bash
aws lambda update-function-code \
  --function-name my-func \
  --zip-file fileb:///home/user/deploy/function.zip
```

**Prevention:** Always use absolute paths in scripts.

### 6.3 "Invalid choice, valid choices are..."

**Error:**

```
Invalid choice: 'ec2-describe-instances', valid choices are: ...
```

**Cause:** Typo in the command, or using old-style command format.

**Solution:** AWS CLI v1 uses `aws <service> <operation>` format (space-separated, not hyphens):

```bash
# Wrong
aws ec2-describe-instances

# Correct
aws ec2 describe-instances
```

### 6.4 "Unknown options" Error

**Error:**

```
Unknown options: --my-flag
```

**Cause:** The parameter does not exist for this operation, or there is a typo.

**Solution:** Check available parameters:

```bash
aws ec2 describe-instances help
```

### 6.5 "Bad value for --endpoint-url"

**Error:**

```
Bad value for --endpoint-url "myendpoint.example.com": scheme is missing...
```

**Cause:** The endpoint URL must include `https://` or `http://`.

**Solution:**

```bash
# Wrong
aws s3 ls --endpoint-url myendpoint.example.com

# Correct
aws s3 ls --endpoint-url https://myendpoint.example.com
```

### 6.6 "Bad value for --query"

**Error:**

```
Bad value for --query "Reservations[.Instances[]": invalid expression...
```

**Cause:** Invalid JMESPath syntax.

**Solution:** Validate your JMESPath expression. Common issues:
- Missing closing brackets
- Using single quotes inside the expression on Windows (use double quotes and escape)
- Incorrect field names (case-sensitive)

```bash
# Test incrementally
aws ec2 describe-instances --query 'Reservations'
aws ec2 describe-instances --query 'Reservations[0]'
aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId'
```

### 6.7 Credentials Not Found

**Error:**

```
Unable to locate credentials. You can configure credentials by running "aws configure".
```

**Cause:** No credentials in environment variables, config files, or instance metadata.

**Solution:**

1. Run `aws configure` to set up credentials
2. Or set environment variables:

```bash
export AWS_ACCESS_KEY_ID=AKIAEXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
```

3. Or verify your credentials file exists at `~/.aws/credentials`

### 6.8 Region Not Specified

**Error:**

```
You must specify a region. You can also configure your region by running "aws configure".
```

**Cause:** No region set in config, environment, or command line.

**Solution:**

```bash
# Per command
aws ec2 describe-instances --region us-east-1

# Or set globally
aws configure set region us-east-1

# Or environment variable
export AWS_DEFAULT_REGION=us-east-1
```

### 6.9 SSL Certificate Verification Failed

**Error:**

```
SSL validation failed for https://...
```

**Cause:** Corporate proxy, custom CA, or outdated certificates.

**Solution:**

```bash
# Point to your CA bundle
aws s3 ls --ca-bundle /path/to/custom-ca-bundle.crt

# Or set globally
export AWS_CA_BUNDLE=/path/to/custom-ca-bundle.crt

# As a last resort (NOT recommended for production)
aws s3 ls --no-verify-ssl
```

> [!CAUTION]
> Using `--no-verify-ssl` disables all certificate verification. Only use this for debugging, never in production or scripts handling sensitive data.

**Prevention:** Keep your system CA certificates updated. If behind a corporate proxy, add the proxy CA to your bundle.

### 6.10 SSO Login Fails to Open Browser (WSL)

**Error:** Running `aws sso login` in WSL fails with errors related to `gio` or the browser not opening.

**Cause:** WSL does not have a native graphical browser. The SSO flow tries to open one via `xdg-open` or `gio`.

**Solution:**

1. Set your Windows browser as the default:

```bash
export BROWSER="/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"
```

2. Or manually copy the URL printed to the terminal and paste it into your Windows browser.

**Prevention:** Add the `BROWSER` export to your `~/.bashrc` in WSL.

### 6.11 Access Denied

**Error:**

```
An error occurred (AccessDenied) when calling the <Operation> operation: User: arn:aws:iam::...
```

**Cause:** The IAM identity does not have permission for the requested action.

**Solution:**

1. Verify which identity you are using: `aws sts get-caller-identity`
2. Check that the required IAM policy is attached
3. Verify you are in the correct account and region

### 6.12 Timeout Errors

**Error:**

```
Connect timeout on endpoint URL...
```

**Cause:** Network issues, DNS resolution failure, or firewall blocking.

**Solution:**

```bash
# Increase timeouts
aws s3 ls --cli-connect-timeout 30 --cli-read-timeout 60
```

Check that you can reach AWS endpoints:

```bash
curl -v https://sts.amazonaws.com
```

> [!WARNING]
> If you are behind a corporate firewall or VPN, ensure that outbound HTTPS (port 443) is allowed to AWS service endpoints (`*.amazonaws.com`).

---

## 7. FAQ

**Q: How do I switch between multiple AWS accounts?**

Use named profiles. Configure each account with `aws configure --profile <name>`, then use `--profile <name>` on each command, or set `export AWS_PROFILE=<name>` for the session.

**Q: What is the difference between aws s3 and aws s3api?**

`aws s3` provides high-level commands (`cp`, `sync`, `mv`, `ls`, `rm`, `mb`, `rb`) with familiar filesystem-like syntax. `aws s3api` exposes the full S3 API with all parameters. Use `aws s3` for everyday tasks and `aws s3api` when you need fine-grained control.

**Q: Can I use AWS CLI without credentials (for public resources)?**

Yes. Use `--no-sign-request` to skip authentication:

```bash
aws s3 ls s3://public-bucket --no-sign-request
```

**Q: How do I get output as plain text for scripting?**

Use `--output text` combined with `--query`:

```bash
INSTANCE_ID=$(aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].InstanceId' \
  --output text)
```

**Q: How do I use AWS CLI with a proxy?**

Set the standard proxy environment variables:

```bash
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
```

**Q: Where are the debug logs?**

Use `--debug` to print detailed logs to stderr:

```bash
aws s3 ls --debug 2>debug.log
```

This includes HTTP request/response details, credential resolution, and retry logic.

**Q: How do I paginate through large result sets manually?**

Use `--max-items` and `--starting-token`:

```bash
aws s3api list-objects --bucket my-bucket --max-items 100
# Use the NextToken from output:
aws s3api list-objects --bucket my-bucket --max-items 100 --starting-token eyJ...
```

**Q: Can I pipe JSON input from another command?**

Yes, but note that `--cli-input-json` requires `file://`. You can use process substitution on Linux/macOS:

```bash
aws ec2 run-instances --cli-input-json file://<(generate_params.sh)
```

Or write to a temporary file first.

**Q: What Python versions are supported?**

AWS CLI v1.44.85 requires Python 3.9 or later.

**Q: How do I create command aliases?**

Create or edit `~/.aws/cli/alias`:

```ini
[toplevel]
whoami = sts get-caller-identity
ls-instances = ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,State.Name]' --output table
```

Then use them as `aws whoami` or `aws ls-instances`.

> [!TIP]
> For architecture details, configuration internals, extension mechanisms, and security hardening, see the **[Admin Guide](/guides/aws/aws-cli/admin-guide/)**.

---

_Generated May 2026 from aws/aws-cli at f141b6c. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
