1. Architecture Overview
AWS CLI v1 (version 1.44.85) is a universal command-line interface for interacting with Amazon Web Services. Built in Python, it wraps the botocore SDK with a full-featured CLI layer including argument parsing, output formatting, help generation, and a plugin/event system for extensibility.
Note
This document covers the v1 branch of AWS CLI. AWS CLI v2 is a separate codebase with different architecture decisions (bundled Python, auto-prompt, SSO integration). V1 remains actively maintained.
High-Level Component Diagram
┌─────────────────────────────────────────────────────────────────────┐
│ User Shell │
│ $ aws <service> <operation> [--params] │
└────────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ bin/aws → awscli/__main__.py → awscli.clidriver.main() │
└────────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ CLIDriver │
│ ┌──────────────┐ ┌───────────────┐ ┌────────────────────────┐ │
│ │ MainArgParser│ │ Command Table │ │ botocore Session │ │
│ │ │ │ (from models) │ │ - credentials │ │
│ └──────┬───────┘ └───────┬───────┘ │ - config │ │
│ │ │ │ - event system │ │
│ ▼ ▼ │ - service models │ │
│ ┌──────────────────────────────┐ └────────────┬───────────┘ │
│ │ ServiceCommand │ │ │
│ │ └─ ServiceOperation │◄─────────────────┘ │
│ │ └─ botocore call │ │
│ └──────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Output Pipeline │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ JSON │ │ Text │ │ Table │ │ YAML (optional) │ │
│ │Formatter │ │Formatter │ │Formatter │ │ Formatter │ │
│ └──────────┘ └──────────┘ └────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Boot Sequence
bin/awsinvokesawscli/__main__.pymain()callscreate_clidriver()create_clidriver()instantiates a botocoreSession- Plugins are loaded from
~/.aws/config[plugins]section CLIDriveris constructed with the sessionCLIDriver.main()parses top-level args, locates the service commandServiceCommand.__call__()parses the operation, delegates toServiceOperationServiceOperation.__call__()invokes the botocore API call- Response passes through the formatter and is written to stdout
Event-Driven Extensibility
The entire CLI is wired through botocore's event system. Events fire at every stage:
| Event | When Fired |
|---|---|
building-command-table.main |
Command table construction (top-level) |
building-command-table.<service> |
Service sub-command table construction |
building-argument-table.<service>.<operation> |
Operation arguments populated |
process-cli-arg.<service>.<operation> |
Individual argument processing |
calling-command.<service>.<operation> |
Just before API dispatch |
load-cli-arg |
Loading paramfile references (file://, fileb://) |
session-initialized |
Session ready (plugin hook point) |
doc-* |
Various documentation generation events |
Customizations in awscli/customizations/ register handlers for these events to modify behavior, inject arguments, rewrite parameters, or add entirely new commands.
2. System Requirements
Runtime Requirements
| Component | Requirement |
|---|---|
| Python | 3.9 or later |
| OS | Linux, macOS, Windows (any platform with Python 3.9+) |
| Disk | ~50 MB installed (including botocore service models) |
| Network | HTTPS outbound to AWS endpoints (port 443) |
| Shell | bash/zsh (Unix) or cmd/PowerShell (Windows) for completions |
Python Dependencies
| Package | Version Constraint | Purpose |
|---|---|---|
| botocore | ==1.42.95 | AWS SDK core: service models, request signing, credential resolution, sessions |
| docutils | >=0.18.1, <=0.19 | reStructuredText processing for help page generation |
| s3transfer | >=0.16.0, <0.17.0 | High-performance multipart S3 file transfers |
| PyYAML | >=3.10, <6.1 | YAML config parsing |
| colorama | >=0.2.5, <0.4.7 | Cross-platform colored terminal output |
| rsa | >=3.1.2, <4.8 | RSA signing for CloudFront presigned URLs |
Important
The botocore version is pinned exactly (
==1.42.95). Upgrading botocore independently will break API compatibility. Always upgrade aws-cli and botocore together.
Build/Development Requirements
| Tool | Purpose |
|---|---|
| pytest | Test runner |
| isort | Import sorting |
| ruff | Linting and formatting |
| pre-commit | Git hook management |
| groff or mandoc | Man page rendering (Unix help display) |
3. Configuration Reference
Configuration Files
| File | Location | Purpose |
|---|---|---|
| Config | ~/.aws/config |
Profiles, region, output, plugins, service-specific settings |
| Credentials | ~/.aws/credentials |
Access keys and session tokens |
| Aliases | ~/.aws/cli/alias |
Command aliases (shorthand and external) |
| Credential Cache | ~/.aws/cli/cache/ |
Cached assume-role credentials (JSON files) |
Environment Variables
| Variable | Purpose | Overrides |
|---|---|---|
AWS_ACCESS_KEY_ID |
Access key for authentication | credentials file |
AWS_SECRET_ACCESS_KEY |
Secret key for authentication | credentials file |
AWS_SESSION_TOKEN |
Temporary session token | credentials file |
AWS_DEFAULT_REGION |
Default region for requests | config file region |
AWS_DEFAULT_OUTPUT |
Output format (json/text/table) | config file output |
AWS_PROFILE |
Named profile to use | --profile flag |
AWS_CONFIG_FILE |
Path to config file | default ~/.aws/config |
AWS_SHARED_CREDENTIALS_FILE |
Path to credentials file | default ~/.aws/credentials |
AWS_DATA_PATH |
Additional directories for service model data | Built-in models |
AWS_CA_BUNDLE |
Path to custom CA certificate bundle | System CA |
AWS_PAGER |
Pager program for output | system pager |
HTTPS_PROXY / HTTP_PROXY |
Proxy configuration | Direct connection |
NO_PROXY |
Hosts to bypass proxy | None |
Config File Options (~/.aws/config)
[default]
region = us-east-1
output = json
cli_pager = less
[profile dev]
region = us-west-2
output = table
role_arn = arn:aws:iam::123456789012:role/dev-role
source_profile = default
credential_source = Environment
[plugins]
myplugin = awscli_plugin_module
| Option | Values | Default | Description |
|---|---|---|---|
region |
Any AWS region code | None (required) | Default region for API calls |
output |
json, text, table |
json |
Output format |
cli_pager |
Pager command or empty string | System pager | Output pager; empty string disables |
role_arn |
IAM role ARN | None | Role to assume for this profile |
source_profile |
Profile name | None | Profile providing credentials for role assumption |
credential_source |
Environment, Ec2InstanceMetadata, EcsContainer |
None | Where to find credentials for role assumption |
external_id |
String | None | External ID for cross-account role assumption |
mfa_serial |
MFA device ARN | None | MFA device for role assumption |
duration_seconds |
Integer | 3600 | Session duration for assumed roles |
ca_bundle |
File path | System CA | Custom CA certificate bundle |
parameter_validation |
true/false |
true |
Client-side parameter validation |
Tip
Use
aws configureto interactively set up profiles. Useaws configure setfor scripted configuration. Useaws configure listto see which config values are active and where they came from.
Alias Configuration (~/.aws/cli/alias)
[toplevel]
whoami = sts get-caller-identity
running-instances = ec2 describe-instances --filters Name=instance-state-name,Values=running
myip = !curl -s https://checkip.amazonaws.com
Two alias types exist:
| Type | Syntax | Implementation Class |
|---|---|---|
| Service alias | name = service operation [args] |
ServiceAliasCommand |
| External alias | name = !shell-command |
ExternalAliasCommand |
Service aliases are parsed and executed within the CLI process. External aliases (prefixed with !) spawn a subprocess.
4. Deployment & Scaling
Installation Methods
pip (recommended for v1):
pip install awscli
From source:
git clone https://github.com/aws/aws-cli.git
cd aws-cli
pip install -e .
System package managers:
# Debian/Ubuntu
sudo apt install awscli
# RHEL/CentOS
sudo yum install awscli
# macOS (Homebrew)
brew install awscli@1
Shell Completion Setup
Bash:
# Add to ~/.bashrc
complete -C aws_completer aws
# Or source the helper:
source /path/to/bin/aws_bash_completer
Zsh:
# Add to ~/.zshrc
source /path/to/bin/aws_zsh_completer.sh
The completer binary (bin/aws_completer) implements tab completion by introspecting botocore service models dynamically.
Multi-Account / Multi-Region Deployment
Note
AWS CLI v1 supports multiple named profiles natively. Each profile can target a different account, region, and credential source.
For fleet deployments:
- Shared credentials via instance profiles - Use
credential_source = Ec2InstanceMetadataorEcsContainerto avoid distributing static keys. - Role chaining - Use
role_arn+source_profileto centralize credential management. - Config distribution - Distribute
~/.aws/configvia configuration management (Ansible, Chef, Puppet). Keep~/.aws/credentialsempty when using instance roles.
Containerized Usage
FROM python:3.11-slim
RUN pip install awscli==1.44.85
# Credentials injected via environment or instance role
ENV AWS_DEFAULT_REGION=us-east-1
ENTRYPOINT ["aws"]
5. Operations
Credential Resolution Order
The CLI resolves credentials in this fixed order (first match wins):
- Command-line options (
--profile) - Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN) - Credentials file (
~/.aws/credentials) - Config file (
~/.aws/config) - Assume-role (if
role_arnconfigured, using source credentials) - Container credentials (ECS task role via
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) - Instance metadata (EC2 instance profile via IMDS)
Credential Caching
When using role_arn (assume-role), the CLI caches temporary credentials in ~/.aws/cli/cache/ as JSON files. The cache is implemented by JSONFileCache and keyed by a hash of the role parameters. Cached credentials are reused until they expire.
Output Formats
| Format | Flag | Use Case |
|---|---|---|
| JSON | --output json |
Machine parsing, jq pipelines |
| Text | --output text |
Tab-separated, grep/awk friendly |
| Table | --output table |
Human-readable aligned tables |
All formatters support --query (JMESPath) for server-side result filtering.
Pagination
The CLI auto-paginates by default. Control with:
| Option | Effect |
|---|---|
--no-paginate |
Return only first page |
--page-size N |
Items per API call (reduces throttling) |
--max-items N |
Total items returned |
--starting-token |
Resume from a previous NextToken |
Retry Behavior
Retries are handled by botocore with exponential backoff. The default retry mode retries up to 4 times for throttling and transient errors. Configure via:
[default]
retry_mode = standard # or adaptive, legacy
max_attempts = 5
Warning
Setting
max_attemptstoo high withadaptivemode can cause long delays under sustained throttling. Monitor CloudWatch API call metrics to tune appropriately.
Logging and Debugging
# Enable debug output (sent to stderr)
aws --debug s3 ls
# Log botocore wire-level details
aws --debug ec2 describe-instances 2> debug.log
Debug output includes: credential resolution, endpoint calculation, request signing, wire-format request/response, retry attempts, and event handler invocations.
History (Command Logging)
The aws history customization (awscli/customizations/history/) records CLI invocations:
aws history show # Show recent commands
aws history list # List recorded command IDs
6. Performance
S3 Transfer Configuration
The aws s3 commands (cp, sync, mv) use s3transfer for high-performance multipart operations:
| Config | Default | Description |
|---|---|---|
max_concurrent_requests |
10 | Parallel transfer threads |
multipart_threshold |
8 MB | File size above which multipart is used |
multipart_chunksize |
8 MB | Size of each part |
max_queue_size |
1000 | Maximum queued transfer operations |
max_bandwidth |
None | Bytes/sec bandwidth limit |
Configure in ~/.aws/config:
[default]
s3 =
max_concurrent_requests = 20
multipart_threshold = 64MB
multipart_chunksize = 16MB
max_bandwidth = 50MB/s
S3 Benchmarking
The scripts/performance/benchmark_utils.py module provides utilities for measuring S3 transfer performance. It supports:
- Configurable file sizes and concurrency levels
- Throughput measurement (MB/s)
- Comparison across different
s3transferconfigurations
CLI Startup Time
CLI startup involves loading botocore, parsing config, loading plugins, and building the command table. Strategies to minimize cold-start latency:
- Avoid unnecessary plugins in
[plugins] - Use
AWS_DATA_PATHonly when custom models are needed - On Lambda/containers, pre-warm by running
aws --versionin init
Tip
If you only use a few services, startup time is not significantly affected because command table construction is lazy - individual service models load only when that service is invoked.
7. Security
Credential Security Best Practices
| Practice | Implementation |
|---|---|
| Never hardcode credentials | Use IAM roles, instance profiles, or environment variables |
| Rotate access keys regularly | Use aws iam create-access-key + aws iam delete-access-key |
| Use MFA for sensitive operations | Configure mfa_serial in profile |
| Least-privilege IAM policies | Scope policies to required actions/resources |
| Audit credential usage | Enable CloudTrail, review with aws cloudtrail lookup-events |
File Permissions
chmod 600 ~/.aws/credentials
chmod 600 ~/.aws/config
chmod 700 ~/.aws/cli/cache/
Caution
The credentials file and cached role credentials contain sensitive material. Ensure they are readable only by the owning user. The CLI does NOT enforce file permissions automatically.
Request Signing
All API requests are signed using AWS Signature Version 4 (handled by botocore). The signing process:
- Creates a canonical request (method, path, query, headers, payload hash)
- Creates a string to sign (algorithm, timestamp, credential scope, canonical request hash)
- Derives a signing key from the secret access key + date + region + service
- Computes HMAC-SHA256 signature
- Adds
Authorizationheader with credential, signed headers, and signature
SSL/TLS
- All requests use HTTPS by default
- Custom CA bundles:
--ca-bundleflag orAWS_CA_BUNDLEenv var orca_bundleconfig - Certificate verification can be disabled with
--no-verify-ssl(NOT recommended for production)
Caution
Disabling SSL verification (
--no-verify-ssl) exposes credentials and data to man-in-the-middle attacks. Only use for debugging with self-signed certificates in development environments.
CloudFront URL Signing
The awscli/customizations/cloudfront.py module uses the rsa dependency to generate signed URLs and signed cookies for CloudFront distributions. Private keys must be PEM-encoded RSA keys associated with a CloudFront key pair.
Paramfile Security
The CLI supports loading parameter values from files (file://path) and URLs (https://url). This is implemented in awscli/paramfile.py:
file://- reads local file contents as the parameter valuefileb://- reads local file as binary (base64-encoded for JSON params)https://- fetches URL contents (use with caution - validates SSL by default)
Warning
The
https://paramfile scheme fetches content from arbitrary URLs at request time. Ensure URLs are trusted and served over verified TLS to prevent parameter injection.
8. Developer Internals
Module Reference
| Module | File | Responsibility |
|---|---|---|
clidriver |
awscli/clidriver.py |
Main orchestrator: CLIDriver, create_clidriver(), command dispatch |
argparser |
awscli/argparser.py |
MainArgParser, ServiceArgParser, ArgTableArgParser hierarchy |
arguments |
awscli/arguments.py |
Argument type system: BaseCLIArgument, CLIArgument, CustomArgument, BooleanArgument, ListArgument |
commands |
awscli/commands.py |
CLICommand, ServiceCommand, ServiceOperation dispatch |
argprocess |
awscli/argprocess.py |
Argument processing and type coercion |
formatter |
awscli/formatter.py |
JSON, Text, Table output formatting |
help |
awscli/help.py |
Help page generation and rendering |
clidocs |
awscli/clidocs.py |
CLIDocumentEventHandler and subclasses for doc generation |
paramfile |
awscli/paramfile.py |
file://, fileb://, https:// parameter loading |
shorthand |
awscli/shorthand.py |
ParamShorthandParser, ShorthandParser for compact input syntax |
plugin |
awscli/plugin.py |
Plugin loading and initialization |
alias |
awscli/alias.py |
AliasLoader, AliasCommandInjector, ServiceAliasCommand, ExternalAliasCommand |
utils |
awscli/utils.py |
Shared utilities |
compat |
awscli/compat.py |
Python version compatibility layer |
schema |
awscli/schema.py |
JSON schema utilities for argument validation |
table |
awscli/table.py |
Table rendering for --output table |
topictags |
awscli/topictags.py |
Built-in help topic management |
handlers |
awscli/handlers.py |
Central registration of all customization event handlers |
bcdoc/ |
awscli/bcdoc/*.py |
Document generation: ReSTDocument, TextWriter, docevents, style |
customizations/ |
awscli/customizations/*.py |
Per-service CLI enhancements |
Command Dispatch Architecture
CLIDriver.main(args)
│
├── parse top-level args (--region, --output, --profile, --debug)
│
├── look up service in command_table
│ command_table built from botocore.session.get_available_services()
│ + customizations injected via 'building-command-table.main' event
│
├── ServiceCommand.__call__(remaining_args, parsed_globals)
│ │
│ ├── build operation sub-command table from service model
│ │ + customizations via 'building-command-table.<service>' event
│ │
│ └── ServiceOperation.__call__(remaining_args, parsed_globals)
│ │
│ ├── build argument table from operation model
│ │ + customizations via 'building-argument-table' event
│ │
│ ├── parse operation-specific args
│ │
│ ├── fire 'process-cli-arg' for each argument
│ │
│ ├── invoke botocore API call
│ │
│ └── format + display response
│
└── return exit code (0=success, 1=client error, 2=server error, 255=other)
Argument Type System
The argument hierarchy enables both model-driven and custom arguments:
BaseCLIArgument (abstract)
├── CLIArgument ← from botocore operation model
├── CustomArgument ← manually defined (customizations)
│ ├── BooleanArgument
│ └── ListArgument
└── (per-customization subclasses)
Each argument knows how to:
- Add itself to an argparse parser (
add_to_parser()) - Process its parsed value into API-compatible format (
add_to_params())
Shorthand Syntax Parser
The shorthand parser (awscli/shorthand.py) allows compact input without JSON:
# Instead of:
aws ec2 run-instances --tag-specifications '[{"ResourceType":"instance","Tags":[{"Key":"Name","Value":"test"}]}]'
# Shorthand:
aws ec2 run-instances --tag-specifications ResourceType=instance,Tags=[{Key=Name,Value=test}]
Parser implementation uses a recursive descent approach. Key error types:
ShorthandParseSyntaxError- malformed shorthand expressionDuplicateKeyInObjectError- repeated keys in shorthand objectParamUnknownKeyError- unrecognized key name
Customization Registration Pattern
All customizations are registered centrally in awscli/handlers.py:
# Pattern: register handler for a specific event
def register_custom_commands(event_handlers):
event_handlers.register('building-command-table.main', add_custom_commands)
# Handler modifies the command table in-place
def add_custom_commands(command_table, session, **kwargs):
command_table['my-command'] = MyCustomCommand(session)
Major customizations include:
| Customization | Module | Adds |
|---|---|---|
| S3 high-level commands | customizations/s3/ |
aws s3 cp, sync, mv, rm, ls, mb, rb, presign |
| EMR cluster management | customizations/emr/ |
aws emr create-cluster, add-steps, ssh, put, socks |
| Lambda | customizations/lambda_cmd.py |
Zip packaging for update-function-code |
| Configure | customizations/configure/ |
aws configure interactive setup |
| CloudFront signing | customizations/cloudfront.py |
aws cloudfront sign |
| ECS | customizations/ecs/ |
Task definition helpers |
| EKS | customizations/eks/ |
Kubeconfig management |
| CodeDeploy | customizations/codedeploy/ |
Deployment push helpers |
| CloudTrail | customizations/cloudtrail.py |
Log validation |
| Logs | customizations/logs/ |
aws logs tail |
| History | customizations/history/ |
aws history show/list |
Help System Internals
Help generation uses the bcdoc subpackage:
CLIDocumentEventHandler(and variants: Provider, Service, Operation) listens for doc events- Generates reStructuredText from botocore model descriptions +
awscli/data/overlays - On Unix: pipes reST through
rst2man.py(docutils) thengroff/mandocto the pager - On Windows: renders plain text directly to the pager
awscli/data/contains per-service overlays adding CLI-specific examples to help pages
Document event flow:
doc-title → doc-description → doc-synopsis → doc-options → doc-examples → doc-output
Each event handler class (ProviderDocumentEventHandler, ServiceDocumentEventHandler, OperationDocumentEventHandler) generates appropriate content for its scope level.
Plugin System
Plugins are loaded from the [plugins] section of ~/.aws/config:
[plugins]
my_plugin = my_plugin_module
The plugin loading process (awscli/plugin.py):
- Import the module specified as the value
- Call
module.awscli_initialize(event_hooks)passing the botocore event emitter - The plugin registers handlers for whatever events it needs
Plugins can:
- Add new top-level commands
- Modify argument tables
- Intercept and transform requests/responses
- Add new output formats
- Inject custom credential providers
Data-Driven Model Architecture
The CLI is fundamentally data-driven via botocore service models:
- Service models (JSON): define every API operation, its inputs, outputs, and errors
- CLI overlays (
awscli/data/): add CLI-specific metadata (examples, extra descriptions) - Custom data path (
AWS_DATA_PATH): allows injecting additional/override models
This means adding a new AWS service to the CLI requires zero code changes - only a new service model JSON file from botocore.
Error Handling
The codebase defines 86 error types across modules:
| Category | Key Errors | Module |
|---|---|---|
| Argument parsing | ParamError, ParamSyntaxError, ParamUnknownKeyError, TooComplexError |
argprocess |
| Shorthand | ShorthandParseSyntaxError, DuplicateKeyInObjectError |
shorthand |
| Alias | InvalidAliasException |
alias |
| CLI | UnknownArgumentError |
argparser |
| Help rendering | ExecutableNotFoundError (groff/mandoc) |
help |
| Paramfile | ResourceLoadingError |
paramfile |
| EMR | 30+ specific error classes | customizations/emr/ |
Exit codes: 0 = success, 1 = client error (4xx or argument error), 2 = server error (5xx), 255 = unhandled exception.
Testing Strategy
Note
The test suite uses pytest and is organized into three tiers with increasing scope and cost.
| Tier | Location | Strategy | Runs Against |
|---|---|---|---|
| Unit | tests/unit/ |
Heavy mocking, CLIRunner + SessionStubber | No network |
| Functional | tests/functional/ |
Real CLI invocation with stubbed HTTP responses | No network |
| Integration | tests/integration/ |
Real AWS API calls | Live AWS (requires credentials) |
Key test infrastructure:
CLIRunner- test helper that invokes CLI commands programmaticallySessionStubber- patches botocore HTTP layer to return canned responses- Pre-commit hooks:
check-yaml,end-of-file-fixer,trailing-whitespace,isort,ruff
Running tests:
# Unit tests
pytest tests/unit/
# Functional tests
pytest tests/functional/
# Specific test file
pytest tests/unit/test_clidriver.py
# With coverage
pytest --cov=awscli tests/unit/
Contributing Patterns
When adding a new customization:
- Create module in
awscli/customizations/ - Define command class extending
BasicCommand(for new commands) or register event handlers (for modifications) - Register in
awscli/handlers.pyvia the appropriate event - Add CLI overlay data in
awscli/data/if needed (examples, descriptions) - Write unit tests in
tests/unit/customizations/ - Write functional tests in
tests/functional/
9. Integration Points
Botocore Integration
The CLI is a thin layer over botocore. Key integration points:
| CLI Component | Botocore Component | Integration |
|---|---|---|
| CLIDriver | botocore.session.Session |
Session provides service models, credentials, config |
| ServiceCommand | botocore.service_model |
Operations derived from service model |
| ServiceOperation | botocore.client |
Actual API calls via botocore client |
| Argument types | botocore.model.Shape |
Argument metadata from model shapes |
| Events | botocore.hooks.EventEmitter |
Shared event system between CLI and SDK |
| Credentials | botocore.credentials |
Full credential provider chain |
| Retries | botocore.retries |
Retry logic lives in botocore |
| Pagination | botocore.paginate |
Paginator from service model pagination config |
S3Transfer Integration
High-level S3 commands (aws s3 cp/sync/mv) use the s3transfer library for:
- Multipart uploads (parallel part uploading)
- Multipart downloads (parallel part downloading)
- Transfer progress callbacks
- Bandwidth throttling
- Automatic content-type detection
Shell Integration
| Feature | Mechanism |
|---|---|
| Tab completion | bin/aws_completer binary + bash/zsh completion scripts |
| Pager output | Respects AWS_PAGER, PAGER, or system default |
| External aliases | ! prefix spawns subprocess with shell |
| Paramfile | file:// reads filesystem; fileb:// reads binary |
| Output piping | Stdout is the formatted response; stderr for errors/debug |
Important
When piping CLI output, the pager is automatically disabled. The CLI detects non-TTY stdout and writes directly to the pipe.
CI/CD Integration
# Non-interactive usage pattern
export AWS_DEFAULT_REGION=us-east-1
export AWS_ACCESS_KEY_ID=$CI_AWS_KEY
export AWS_SECRET_ACCESS_KEY=$CI_AWS_SECRET
# Disable pager for scripted use
export AWS_PAGER=""
# Use --output text for easy parsing
INSTANCE_ID=$(aws ec2 run-instances \
--image-id ami-12345 \
--instance-type t3.micro \
--query 'Instances[0].InstanceId' \
--output text)
Docker / Container Integration
When running in containers:
- ECS tasks: credentials auto-injected via
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - EC2 instances: IMDS provides credentials automatically
- Kubernetes: use IAM Roles for Service Accounts (IRSA) which sets
AWS_WEB_IDENTITY_TOKEN_FILE
Tip
In ephemeral containers, avoid writing to
~/.aws/entirely. Use environment variables for credentials and pass--regionexplicitly. This eliminates filesystem state and simplifies container image management.
Custom Data Path
The AWS_DATA_PATH environment variable allows injecting additional service models:
export AWS_DATA_PATH=/opt/custom-models
# Structure:
# /opt/custom-models/
# myservice/
# 2024-01-01/
# service-2.json (service model)
# paginators-1.json (pagination config)
# waiters-2.json (waiter definitions)
This enables using AWS CLI with custom/internal services that follow the botocore model format, or overriding behavior of existing services for testing.
Quick Reference
Common Administrative Commands
# Show active configuration and source
aws configure list
# Show caller identity (verify credentials)
aws sts get-caller-identity
# List all configured profiles
aws configure list-profiles
# Set a config value
aws configure set region us-west-2 --profile prod
# Get a config value
aws configure get region --profile prod
# Show CLI version
aws --version
Troubleshooting Checklist
| Symptom | Likely Cause | Resolution |
|---|---|---|
Unable to locate credentials |
No valid credential source | Check env vars, credentials file, instance role |
ExpiredTokenException |
Cached assume-role token expired | Delete ~/.aws/cli/cache/ contents |
Could not connect to the endpoint URL |
Wrong region or network issue | Verify region, check proxy/firewall |
An error occurred (AccessDenied) |
Insufficient IAM permissions | Review IAM policy for the identity |
command not found: aws |
Not in PATH | Verify installation, check which aws |
| Help shows "groff" error | groff/mandoc not installed | Install groff or use aws help 2>/dev/null | cat |
| Slow startup | Many plugins or large custom data path | Audit [plugins], check AWS_DATA_PATH |