This is a simple command line tool to get the cost of your AWS account. It uses the AWS Cost Explorer API to get the cost and output the results to the console, text, csv, markdown or JSON. E.g. so it can be used in a workflow to get the cost of your account and use it in subsequent steps.
It is modeled on the excellent azure-cost-cli and follows the same commands, options and output formats where AWS has an equivalent.
⚠️ Important: AWS charges for every Cost Explorer API request (USD 0.01 per request at the time of writing). A singleaccumulatedCostrun makes 4–5 requests. See Is there cost involved?
AWS Cost Overview for my-account (123456789012) from 10/1/2026 to 10/22/2026
╭─ AWS Costs ─╮ Accumulated cost in USD
│ Today: 4.10 USD │ 01 Oct ██ 3.95
│ Yesterday: 4.32 USD │ 02 Oct ███ 8.02
│ Since start 92.47 USD │ ...
│ of Oct: │ 22 Oct ████████████████████ 92.47
│ Forecast for 131.20 USD │ 23 Oct ████████████████████ 96.41
│ Oct: │ ...
│ Last 7 days: 29.83 USD │ 31 Oct ████████████████████████████ 131.2
│ Last 30 days: 92.47 USD │
│ Total in 92.47 USD │
│ timeframe: │
╰────────────────────────────────╯
╭─ By Service ─╮
│ ■ Amazon Elastic Compute Cloud - Compute 41.20 USD
│ ■ Amazon Relational Database Service 22.75 USD
│ ■ EC2 - Other 11.04 USD
│ ■ Amazon Simple Storage Service 6.31 USD
│ ...
╰────────────────────────────────╯
╭─ By Region ─╮
│ ■ eu-west-1 80.12 USD
│ ■ us-east-1 11.90 USD
│ ■ global 0.45 USD
╰────────────────────────────────╯
- .NET 8.0 or .NET 9.0 SDK to build and install the tool. (Not needed on the target machine if you use the self-contained executable.)
- AWS credentials the AWS SDK can find (see Authentication).
- Cost Explorer enabled for the account.
The tool is not published to nuget.org (yet), so you install it from a package you build locally. Pick one of the options below.
A .NET global tool is installed per user into ~/.dotnet/tools (%USERPROFILE%\.dotnet\tools on Windows) and is available from any directory.
# 1. Build the NuGet package (written to src/nupkg)
dotnet pack src/aws-cost-cli.csproj -c Release
# 2. Install it globally for your user from that folder
dotnet tool install --global aws-cost-cli --add-source src/nupkg
# 3. Use it from anywhere
aws-cost --version
aws-cost accumulatedCost~/.dotnet/tools is added to your PATH by the .NET SDK installer. If aws-cost is not found, open a new terminal, or add the folder yourself:
# Windows (PowerShell) - permanently for the current user
[Environment]::SetEnvironmentVariable("PATH", $env:PATH + ";$env:USERPROFILE\.dotnet\tools", "User")# Linux / macOS - add to ~/.bashrc or ~/.zshrc
export PATH="$PATH:$HOME/.dotnet/tools"Copy the .nupkg from src/nupkg to a shared folder (or push it to a private feed such as Azure Artifacts, GitHub Packages or AWS CodeArtifact). Every user then installs it once:
# From a file share
dotnet tool install --global aws-cost-cli --add-source \\fileserver\nuget
# From a private feed that is already configured in your nuget.config
dotnet tool install --global aws-cost-cliTo install into a specific folder instead of the per-user location (for example a shared tools folder on a build agent), use --tool-path:
dotnet tool install aws-cost-cli --add-source src/nupkg --tool-path C:\tools\aws-costPublish a single executable that bundles the .NET runtime, then copy it to any machine:
# Windows x64 (use linux-x64, linux-arm64, osx-arm64, osx-x64 for other platforms)
dotnet publish src/aws-cost-cli.csproj -c Release -f net9.0 -r win-x64 --self-contained \
-p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true \
-p:AssemblyName=aws-cost -o publish/win-x64This produces publish/win-x64/aws-cost.exe (about 90 MB). Put it in a folder on your PATH, for example:
# Windows (PowerShell) - current user only, no admin rights required
New-Item -ItemType Directory -Force "$env:LOCALAPPDATA\Programs\aws-cost" | Out-Null
Copy-Item publish\win-x64\aws-cost.exe "$env:LOCALAPPDATA\Programs\aws-cost\"
[Environment]::SetEnvironmentVariable("PATH", $env:PATH + ";$env:LOCALAPPDATA\Programs\aws-cost", "User")# Linux / macOS - current user
mkdir -p ~/.local/bin && cp publish/linux-x64/aws-cost ~/.local/bin/ && chmod +x ~/.local/bin/aws-costdotnet run --project src -f net9.0 -- accumulatedCostBump the <Version> in src/aws-cost-cli.csproj, build a new package and update the installed tool:
dotnet pack src/aws-cost-cli.csproj -c Release
dotnet tool update --global aws-cost-cli --add-source src/nupkgWith a --version parameter, you can install a specific version. Use the --no-cache parameter to force a re-read of the package source if it cannot find the latest version.
dotnet tool uninstall --global aws-cost-cli
dotnet tool list --global # verify it is goneFor the self-contained executable, simply delete aws-cost.exe / aws-cost and remove the folder from your PATH.
You can invoke the tool using the aws-cost command. You can use the --help parameter to get a list of all available options.
aws-cost --helpWhich will show:
USAGE:
aws-cost [OPTIONS] [COMMAND]
EXAMPLES:
aws-cost accumulatedCost
aws-cost accumulatedCost --profile my-profile
aws-cost accumulatedCost -o json
aws-cost accumulatedCost -t TheLastMonth -o markdown
aws-cost accumulatedCost --from 2026-01-01 --to 2026-03-31
aws-cost accumulatedCost --filter REGION=eu-west-1 --filter tag:Environment=prod
OPTIONS:
DEFAULT
-h, --help Prints help information
-v, --version Prints version information
--debug Increase logging verbosity to show all debug logs
--no-color Disable ANSI color output. Useful for CI/logging environments
--quiet Suppress all status/progress messages. Only actual data output is written
-p, --profile The AWS named profile to use. Defaults to the standard AWS credential chain
-r, --region The AWS region of the Cost Explorer endpoint. Defaults to us-east-1
-o, --output The output format to use. Defaults to Console (Console, Json, JsonC, Text, Markdown, Csv)
-t, --timeframe The timeframe to use for the costs. Defaults to MonthToDate (MonthToDate, TheLastMonth, WeekToDate, Custom)
--from The start date (inclusive) to use for the costs
--to The end date (inclusive) to use for the costs
--others-cutoff 10 The number of items to show before collapsing the rest into an 'Others' item
--query JMESPath query string, applicable for the Json output only
--skipHeader Skip header creation for specific output formats
--filter Filter the costs. Format: DIMENSION=value1,value2 or tag:Key=value1,value2
-m, --metric UnblendedCost The cost metric to use (UnblendedCost, BlendedCost, AmortizedCost, NetUnblendedCost, NetAmortizedCost)
--endpoint-url <URL> Override the Cost Explorer endpoint URL
--fail-if-over Fail with exit code 1 if total cost exceeds this amount
COMMANDS:
accumulatedCost Show the accumulated cost details
If the application is not working properly, you can use the
--debugparameter to see the caller identity and every Cost Explorer request that is made.
Cost Explorer data is refreshed at least once every 24 hours, so "Today" is an estimate and can lag behind.
The tool uses the standard AWS SDK for .NET credential chain, so anything that works for the AWS CLI works here:
| Method | How |
|---|---|
| Console login | aws login (stores a login_session in ~/.aws/config) |
| IAM Identity Center (SSO) | aws sso login --profile my-sso-profile, then aws-cost --profile my-sso-profile |
| Access keys | aws configure, or the AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN env vars |
| Named profile | --profile <name> or the AWS_PROFILE env var |
| Roles | EC2 instance profiles, ECS task roles, EKS IRSA / Pod Identity, GitHub OIDC (AWS_WEB_IDENTITY_TOKEN_FILE) |
The identity needs the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ce:GetCostAndUsage",
"ce:GetCostForecast",
"sts:GetCallerIdentity",
"iam:ListAccountAliases"
],
"Resource": "*"
}
]
}iam:ListAccountAliases is optional; it is only used to show a friendly account name. The AWS managed policy AWSBillingReadOnlyAccess also works.
In an AWS Organization, running against the management (payer) account shows the costs of all member accounts, including a By Linked Account breakdown. In a member account you only see that account's costs.
These flags are available on every command:
| Flag | Description |
|---|---|
--no-color |
Disable ANSI color and escape codes. Useful when piping output to files or running in CI environments where color codes appear as garbage. |
--quiet |
Suppress all status spinners and progress messages. Only the actual data output is written. Useful for scripting or when redirecting output. |
--debug |
Show verbose debug information including the caller identity and the Cost Explorer requests. |
-v, --version |
Print the tool version. |
Examples:
# Pipe clean output to a file without escape codes
aws-cost accumulatedCost -o text --no-color > report.txt
# Use in a script without spinner noise
aws-cost accumulatedCost -o json --quiet | jq '.totals.totalCostInTimeframe'You can use this tool in a GitHub workflow to get the cost of your account and store the results in markdown as a Job Summary. Authenticate with GitHub OIDC so no long-lived keys are needed:
name: AWS Cost CLI Workflow
on:
workflow_dispatch:
schedule:
- cron: '0 7 * * *'
permissions:
id-token: write
contents: read
jobs:
run-aws-cost-cli:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_COST_ROLE_ARN }}
aws-region: us-east-1
- name: Install AWS Cost CLI
run: |
dotnet pack src/aws-cost-cli.csproj -c Release
dotnet tool install --global aws-cost-cli --add-source src/nupkg
- name: Run AWS Cost CLI
run: aws-cost accumulatedCost -o markdown --quiet >> $GITHUB_STEP_SUMMARYUse the --fail-if-over <amount> flag to fail a pipeline step when costs exceed a threshold. When the total cost in the timeframe exceeds the specified amount, the command writes a warning to stderr and exits with code 1. Output is still written normally before the check, so piped output (e.g. to a file) is not affected.
- name: Check AWS costs
run: aws-cost accumulatedCost -o json --quiet --fail-if-over 500 > costs.jsonIf costs exceed 500, the step fails and the workflow stops (or you can use continue-on-error: true to proceed with a warning). The JSON output is still written to costs.json regardless.
This will retrieve the accumulated cost of the account. This is the total cost since the beginning of the period specified. It also fetches the forecast until the end of the month (when the timeframe includes today) and organises the costs by service, region and linked account. You can use the different formatters to get the results in different formats.
aws-cost accumulatedCost --profile prodThis is the default command when you do not specify a command.
With the --filter option you can pass in one or more Cost Explorer dimensions or tags to filter on.
aws-cost --filter "REGION=eu-west-1,eu-central-1" --filter "tag:owner=me"In the example above, we look for costs in either eu-west-1 or eu-central-1 and having a tag named owner with the value me.
Commonly used dimensions: SERVICE, REGION, LINKED_ACCOUNT, USAGE_TYPE, INSTANCE_TYPE, RECORD_TYPE, PURCHASE_TYPE. Service names must match the Cost Explorer names exactly, e.g. SERVICE=Amazon Elastic Compute Cloud - Compute (quote values that contain spaces).
Filters are passed along to the Cost Explorer API, so less data is retrieved. Compared to the query, where the data is queried with a JMESPath expression and can be projected as well.
Multiple filters are combined with an and expression, while the values are split by the , and used as an or.
Tip: exclude credits and refunds from the totals with the
-m NetUnblendedCostmetric, or filter onRECORD_TYPE=Usage.
Use the --query to specify a JMESPath expression. This allows you to filter the results. For example, to get the yesterday cost of the account, you can use the following query:
aws-cost -o json --query "totals.yesterdayCost"Or to list only the services and their cost:
aws-cost -o json --query "byServiceNames[*].[ServiceName, Cost]"will output:
[["Amazon Elastic Compute Cloud - Compute",41.2],["Amazon Relational Database Service",22.75],["EC2 - Other",11.04]]For the JMESPath parsing, it uses the JMESPath.Net library. Not all constructions might be implemented yet.
The default timeframe is the month to date. You can specify a custom timeframe using the --from and --to parameters (setting both automatically switches to Custom). Dates use the ISO 8601 format (yyyy-MM-dd) and both are inclusive.
Options are:
- MonthToDate
- TheLastMonth
- WeekToDate (starting on Sunday)
- Custom
All dates are in UTC, which is what Cost Explorer uses. Cost Explorer keeps 13 months of history by default (up to 38 months when multi-year data is enabled).
Select the cost metric with -m / --metric:
| Metric | Description |
|---|---|
UnblendedCost (default) |
Costs as they are charged, matching most of the bill |
BlendedCost |
Average rates across an organization's consolidated billing family |
AmortizedCost |
Upfront Reserved Instance / Savings Plans fees spread over the term |
NetUnblendedCost |
Unblended cost after discounts (e.g. EDP, credits) |
NetAmortizedCost |
Amortized cost after discounts |
See Understanding your AWS Cost Datasets for details.
The tool supports multiple output formats. The default is Console which will output the results to the console. You can specify a different format using the --output parameter. The following formats are supported:
The default output format. It will output the results to the console in a graphical way, as shown at the top of this page.
The Json format is great for further processing of the data. It will output the results in a JSON format to the console. Using the > operator, you can redirect the output to a file. Use jsonc to get a colorized output.
aws-cost accumulatedCost -o json > cost.json{
"account": {
"accountId": "123456789012",
"alias": "my-account"
},
"timeframe": {
"from": "2026-10-01",
"to": "2026-10-22",
"metric": "UnblendedCost"
},
"totals": {
"todaysCost": 4.10,
"yesterdayCost": 4.32,
"sinceStartOfMonthCost": 92.47,
"lastSevenDaysCost": 29.83,
"lastThirtyDaysCost": 92.47,
"totalCostInTimeframe": 92.47,
"forecastedEndOfMonthCost": 131.20,
"currency": "USD"
},
"cost": [
{ "Date": "2026-10-01", "Cost": 3.95, "Currency": "USD" },
{ "Date": "2026-10-02", "Cost": 4.07, "Currency": "USD" }
],
"forecastedCosts": [
{ "Date": "2026-10-23", "Cost": 3.94, "Currency": "USD" }
],
"byServiceNames": [
{ "ServiceName": "Amazon Elastic Compute Cloud - Compute", "Cost": 41.20, "Currency": "USD" }
],
"byRegion": [
{ "Region": "eu-west-1", "Cost": 80.12, "Currency": "USD" }
],
"byLinkedAccount": [
{ "LinkedAccount": "my-account (123456789012)", "Cost": 92.47, "Currency": "USD" }
]
}Tip: Use the
--queryparameter here to manipulate the results, like filtering and projecting the data. Do keep in mind that it operates over the already fetched data.
A simple textual format.
AWS Cost Overview for my-account (123456789012) from 10/1/2026 to 10/22/2026
Totals:
Today: 4.10 USD
Yesterday: 4.32 USD
Since start of Oct: 92.47 USD
Forecast for Oct: 131.20 USD
Last 7 days: 29.83 USD
Last 30 days: 92.47 USD
Total cost in timeframe: 92.47 USD
By Service Name:
Amazon Elastic Compute Cloud - Compute: 41.20 USD
Amazon Relational Database Service: 22.75 USD
EC2 - Other: 11.04 USD
Amazon Simple Storage Service: 6.31 USD
AmazonCloudWatch: 4.02 USD
By Region:
eu-west-1: 80.12 USD
us-east-1: 11.90 USD
global: 0.45 USD
When the timeframe ends before today (e.g. -t TheLastMonth), the last day with data is used instead of "Today" and "Yesterday".
A CSV format with the daily costs, which can be used in Excel or other tools. It will use the default culture of your system for the separators. If you combine the output of multiple runs into one file (like using the >> to append to a file), you can use the --skipHeader parameter to prevent the header from being written multiple times.
aws-cost accumulatedCost -o csv > cost.csvDate,Cost,Currency
10/1/2026,3.95000000,USD
10/2/2026,4.07000000,USD
10/3/2026,4.11000000,USDA markdown format. It will output the results in a series of simple tables, plus mermaid charts that render on GitHub.
aws-cost accumulatedCost -o markdown > cost.md# AWS Cost Overview
> Accumulated UnblendedCost for account `my-account (123456789012)` from **10/1/2026** to **10/22/2026**
## Totals
|Period|Amount|
|---|---:|
|Today|4.10 USD|
|Yesterday|4.32 USD|
|Since start of Oct|92.47 USD|
|Forecast for Oct|131.20 USD|
|Last 7 days|29.83 USD|
|Last 30 days|92.47 USD|
|Total cost in timeframe|92.47 USD|
## By Service Name
|Service|Amount|
|---|---:|
|Amazon Elastic Compute Cloud - Compute|41.20 USD|
|Amazon Relational Database Service|22.75 USD|
|EC2 - Other|11.04 USD|
## By Region
|Region|Amount|
|---|---:|
|eu-west-1|80.12 USD|
|us-east-1|11.90 USD|
<sup>Generated at 2026-10-22 07:40:23 for AWS account `123456789012`</sup>Excluded in the above sample, but it will also include mermaidjs diagrams as well.
When the tool detects an exception, it will write this to the error stream and return with a -1 (shown as 255 by most shells). This can be used in scripts to detect if something went wrong. If you want to capture any errors as well, redirect the error stream to a different file:
aws-cost accumulatedCost -o markdown > cost.md 2>error.logCommon errors:
| Error | Fix |
|---|---|
Failed to resolve AWS credentials |
Run aws login, aws sso login --profile <name> or aws configure, or pass --profile. |
The AWS profile 'x' could not be found |
Check aws configure list-profiles. |
AWS error (AccessDeniedException) |
Grant the permissions above and make sure Cost Explorer is enabled. |
AWS error (DataUnavailableException) |
Cost Explorer was enabled recently; data becomes available within 24 hours. |
Validation error on --filter |
Use DIMENSION=value or tag:Key=value. |
The tool reports on the account of the credentials it uses. To report on several accounts, loop over your profiles:
for profile in dev test prod; do
echo "Account: $profile"
aws-cost accumulatedCost -o markdown --quiet --profile $profile
doneOr using PowerShell, appending all daily costs into a single CSV file:
$profiles = "dev", "test", "prod"
aws-cost accumulatedCost -o csv --quiet --profile $profiles[0] | Set-Content .\report.csv
$profiles | Select-Object -Skip 1 | ForEach-Object {
aws-cost accumulatedCost -o csv --quiet --skipHeader --profile $_ | Add-Content .\report.csv
}Using the --skipHeader parameter is important here, otherwise you will get a header for each account.
With AWS Organizations, it is usually easier (and cheaper) to run once against the management account and use the By Linked Account breakdown, or filter on a single member account:
aws-cost accumulatedCost --profile management --filter LINKED_ACCOUNT=123456789012Yes. Unlike the Azure Cost Management API, the AWS Cost Explorer API is billed per request: USD 0.01 per paginated request at the time of writing. The accumulatedCost command makes:
| Request | Count |
|---|---|
GetCostAndUsage (daily totals) |
1 |
GetCostForecast (only when the timeframe includes today) |
0–1 |
GetCostAndUsage grouped by service, region, linked account |
3 |
So a run costs about USD 0.04–0.05 (a bit more if results are paginated). Running it daily from a scheduled workflow costs roughly USD 1.50 per month. Cost Explorer data refreshes about once a day, so running it more often than every few hours gives little extra value.
dotnet build aws-cost-cli.sln
dotnet test aws-cost-cli.slnsrc/
├── Program.cs # Entry point, DI, command registration, AWS error handling
├── Commands/ # Settings + commands (one folder per command)
│ └── AccumulatedCost/
├── CostApi/ # Cost Explorer / STS integration (ICostRetriever)
├── OutputFormatters/ # Console, Json, Text, Markdown, Csv
└── Infrastructure/ # DI registrar/resolver, helpers
tests/AwsCostCli.Tests/ # xUnit + Moq + Shouldly
Based on azure-cost-cli by Michiel van Oudheusden, licensed under Apache-2.0. The Spectre.Console rendering helpers in src/OutputFormatters/SpectreConsole are taken from that project.