CloudCleaner
Finds AWS resources nobody is using, proves it, works out the order they have to be dismantled in, and asks a human before touching anything.
pip install cloudcleaner-agent
The command it installs is cloudcleaner.
The problem
Stopping an EC2 instance does not stop the bill. Stop releases the compute
and nothing else — the root volume, any extra volumes, and the public IPv4
address all keep charging. A stopped t3.micro with a 16 GB volume and an
Elastic IP still costs about $4.93 a month, indefinitely.
Deleting is a dependency puzzle. You cannot release an Elastic IP while it
is associated. You cannot delete a volume while it is attached. Volumes created
with DeleteOnTermination=false outlive the instance and bill silently forever.
AWS reports exactly one blocker per attempt, so the order is discovered by trial
and error.
CloudCleaner does both parts: it finds the waste, and it works out the sequence.
Try it without an AWS account
A demo account ships with the package, so nothing is read or changed:
CLOUDCLEANER_PROVIDER=fixture cloudcleaner scan
CLOUDCLEANER_PROVIDER=fixture cloudcleaner sweep
RESOURCE TYPE STATE $/MO
i-0999prod888 ec2 running $34.37
vol-0orphan11 ebs available $8.00 *
i-0abc123def456789 ec2 stopped $4.93 *
eipalloc-0unused9 eip unassociated $3.65 *
4 resources · $50.95/mo total · $16.58/mo not running but still billing (*)
Against a real account
cloudcleaner doctor # check credentials and configuration first
cloudcleaner scan
cloudcleaner investigate i-0abc123def456789
CLOUDCLEANER_DRY_RUN defaults to true. Nothing in AWS is modified until you
set it to false.
What an investigation looks like
i-0abc123def456789 payments-poc (ec2/stopped) $4.93/mo
-> retire (95%, high) Stopped 41 days with average CPU 0.4%, and still
billing $4.93/mo for its volume and address.
1. disassociate_address eipassoc-0c1b2a3 $0.00 54.211.8.12 is attached
! 2. release_address eipalloc-0f2e3d4 $3.65 public IPv4 bills hourly
3. snapshot_volume vol-0a9b8c7d6 $0.00 restore point first
! 4. terminate_instance i-0abc123def456789 $4.93 idle instance
! 5. delete_volume vol-0a9b8c7d6 $1.28 DeleteOnTermination=false
3 of 5 steps cannot be undone $9.86/mo
Type 'APPROVE i-0abc123def456789' to run this plan:
The order is computed, not scripted: dependencies are discovered at runtime and topologically sorted, so a cycle raises rather than producing a sequence that fails halfway.
Commands
cloudcleaner scan |
what the account holds and what it costs |
cloudcleaner sweep |
investigate everything, approve nothing |
cloudcleaner investigate <id> |
one resource, with the approval prompt |
cloudcleaner history |
past runs, realised versus simulated savings |
cloudcleaner doctor |
check credentials and configuration |
cloudcleaner serve |
the HTTP API (needs the [server] extra) |
Safety
Three independent gates stand between a verdict and a deletion:
- The model advises. It sees only evidence and returns a typed verdict. It can be wrong, and a human can overrule it.
- The policy decides. Plain Python — protected environments, protected tags, minimum age, risk score. No prompt reaches it, so it cannot be argued with or injected.
- A human commits. You type the resource id exactly. Never
y/n.
Every volume is snapshotted before deletion, a restore recipe is written before anything runs, and dry-run savings are recorded as simulated — never as money saved.
Configuration
Read from .env in the working directory, upwards from it, or
~/.cloudcleaner/.env.
| Variable | Default | Effect |
|---|---|---|
GROQ_API_KEY |
— | required unless AI is disabled |
CLOUDCLEANER_PROVIDER |
aws |
fixture runs offline against the demo account |
CLOUDCLEANER_DRY_RUN |
true |
false actually modifies AWS |
CLOUDCLEANER_AI_ENABLED |
true |
false uses the rules engine only; nothing leaves the machine |
CLOUDCLEANER_DATA_DIR |
./output or ~/.cloudcleaner |
where the database and logs are written |
AWS_ENDPOINT_URL |
— | point boto3 at LocalStack |
GITHUB_TOKEN |
— | optional; without it, code activity is skipped rather than failing |
METRIC_WINDOW_DAYS |
7 |
CloudWatch lookback |
Extras
pip install cloudcleaner-agent # the CLI
pip install 'cloudcleaner-agent[server]' # plus the HTTP API and web frontend
pip install 'cloudcleaner-agent[all]' # plus OpenAI, Anthropic, LangSmith
Coverage
Today: EC2 instances, EBS volumes, Elastic IPs, snapshots. CloudWatch usage, cost attribution, and GitHub signals — last commit, branch existence, PR status, CI runs — so the agent can tell whether the project that owns a resource is still alive.
Not yet: RDS, NAT gateways, load balancers, ElastiCache, multi-account.
Requirements
Python 3.12+. AWS credentials with read access plus whichever write permissions
you intend to use. A Groq API key, free at console.groq.com,
unless you run with CLOUDCLEANER_AI_ENABLED=false.
MIT licensed.
Metadata
Release files for cloudcleaner-agent 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cloudcleaner_agent-0.1.0.tar.gz | 65.5 kB | Without provenance | Details for cloudcleaner_agent-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cloudcleaner_agent-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for cloudcleaner_agent-0.1.0-py3-none-any.whl |
Total release size: 134.6 kB
Release files / cloudcleaner_agent-0.1.0.tar.gz
| Download URL | cloudcleaner_agent-0.1.0.tar.gz |
|---|---|
| Size | 65.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a35bbe0b55ef34e054eba097fa778eae9b796226cf4c0bdb9112c0f03f08d0ca
|
|
BLAKE2b-256 checksum How to use checksums |
8c0ae8cbd25f817432b7f183bf129ffbd809160326324e8044902bd6134aa766
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / cloudcleaner_agent-0.1.0-py3-none-any.whl
| Download URL | cloudcleaner_agent-0.1.0-py3-none-any.whl |
|---|---|
| Size | 69.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
613f7b87e84c3b6921fc1766ea85445c16b7442fc8cf0f617920801afba210d7
|
|
BLAKE2b-256 checksum How to use checksums |
a0cb2d6422263918e615c0eb0b3780e242ad86c1de7ee678c1f0b9b7070cc977
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for cloudcleaner-agent 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.