CLI and library for analyzing AWS costs across accounts and services. Wraps the AWS Cost Explorer API and adds month-over-month pivots, change alerts, and usage-type breakdowns, with optional chart export. A Lincoln Loop project.
The core install is intentionally lightweight — only boto3, click,
tabulate, and python-dateutil.
From a tagged release on GitHub:
pip install "git+https://github.com/lincolnloop/aws-cost-analysis@v0.6.0"
# with chart export:
pip install "aws-cost-analysis[viz] @ git+https://github.com/lincolnloop/aws-cost-analysis@v0.6.0"Or run the CLI without installing it:
uvx --from "git+https://github.com/lincolnloop/aws-cost-analysis@v0.6.0" \
aws-costs analyze-services --months 3 --tableFor local development:
pyenv install 3.12 # if not already installed
uv sync # builds .venv and installs the project editableBy default the tools use the standard boto3 credential chain. Pick a profile via
AWS_PROFILE, or pass --profile / --region to the CLI:
export AWS_PROFILE=my-profile
aws-costs --profile my-profile --region us-east-1 analyze-services --tableLibrary callers can inject any boto3.Session (see Library usage),
which is the supported way to drive a specific profile or assumed-role
credentials without mutating process-wide state.
Required IAM permissions:
ce:GetCostAndUsageorganizations:ListAccounts(for account-name resolution)
aws-costs analyze-accounts --months 3 --table
aws-costs analyze-services --months 6 --format csv
aws-costs analyze-usage "Amazon RDS" --months 2 --table
aws-costs analyze-usage-types ec2 --months 3 --table
aws-costs analyze-alerts --amount 50 --percent 15
aws-costs list-available-servicesCommon options:
| flag | description |
|---|---|
--months N |
Months of history (default 2) |
--include-current |
Include the current (incomplete) month |
--format json|csv|tsv|html |
Persisted output format |
--table |
Print pivot table to terminal |
--sheets |
Print CSV to stdout (accounts only) |
--output-dir DIR |
Output directory (default cost_reports/) |
Outputs land in cost_reports/{AWS_PROFILE}/ with timestamped filenames like
account_costs_2m_20260504_171500_pivot.json.
The analysis functions are importable and return plain Python list[dict]
records — a tidy "raw" list and a formatted month-over-month pivot:
from aws_cost_analysis.cost_analysis import analyze_service_costs
raw, pivot = analyze_service_costs(months=6)
# raw → [{"month": "2026-04", "key": "AWS Lambda", "cost": 9.99}, ...]
# pivot → [{"Service": "AWS Lambda", "2026-04": "$9.99", ..., "+/- $": "...", "+/- %": "..."}, ...]
print(pivot)Every function that talks to AWS accepts an optional session keyword. When
omitted, the standard boto3 credential chain is used. Pass an explicit
boto3.Session to target a specific profile or assumed-role credentials —
useful for multi-account tooling and tests, with no process-wide state:
import boto3
from aws_cost_analysis.cost_analysis import analyze_account_costs
# A specific named profile
session = boto3.Session(profile_name="payer", region_name="us-east-1")
raw, pivot = analyze_account_costs(months=3, session=session)
# Or assumed-role credentials for a client's payer account
sts = boto3.client("sts")
creds = sts.assume_role(
RoleArn="arn:aws:iam::123456789012:role/CostExplorerReadOnly",
RoleSessionName="cost-analysis",
)["Credentials"]
session = boto3.Session(
aws_access_key_id=creds["AccessKeyId"],
aws_secret_access_key=creds["SecretAccessKey"],
aws_session_token=creds["SessionToken"],
)
raw, pivot = analyze_account_costs(months=3, session=session)list_services(...) accepts the same session keyword.
uv sync
.venv/bin/pytest
.venv/bin/ruff check aws_cost_analysis tests
uv run mypy aws_cost_analysisaws_cost_analysis/
├── billing.py # Time-period helpers
├── cost_analysis.py # Cost Explorer queries + data shaping; returns list[dict] records
├── cost_alerts.py # Threshold-based change detection
└── cli.py # Click CLI (entry: aws-costs)
Cost Explorer results flow through create_cost_dataframe → create_cost_pivot,
which produces a tidy list[dict] of raw records plus a formatted pivot with
+/- $ and +/- % delta columns and a Total row appended last.
MIT — see LICENSE. Copyright © Lincoln Loop.