Custom CI/CD Toolkit
An AI-powered deployment toolkit for AWS ECS — deploy any Dockerized app with a single command, with Claude Code as your built-in DevOps assistant.
What's Inside
| Component | Purpose |
|---|---|
deployagent |
CLI tool to deploy Dockerized apps to AWS ECS Fargate |
deployagent-mcp |
Claude Code MCP plugin — AI validates, diagnoses, and deploys via natural language |
Table of Contents
- How It Works
- Prerequisites
- Installation
- Claude Code MCP Plugin
- Configuration — deploy.yaml
- AWS Setup
- CLI Commands
- Troubleshooting
How It Works
Your project + deploy.yaml
↓
Say "deploy the project" to Claude Code
↓
Claude asks: container name? port? tag? replicas? env vars?
↓
1. Validates Dockerfile + K8s manifests (static analysis)
2. Builds Docker image + pushes to ECR
3. Creates / updates ALB + target group (fixed public DNS)
4. Registers new ECS task definition (with env vars injected)
5. Creates or rolling-updates ECS service
6. Waits for service stability
7. Runs health check
8. Saves deploy snapshot to SQLite (for rollback)
↓
App URL: http://<alb-dns-name>
If the health check fails, it automatically rolls back to the last known-good state.
Prerequisites
- Python 3.11+
- Docker Desktop (must be running during deploy)
- AWS account with IAM credentials
- Claude Code VSCode extension (for MCP plugin)
Installation
git clone https://github.com/chiman45/Custom-CICD.git
cd Custom-CICD
pip install -e .
# Verify
deployagent --help
AWS credentials
Create a .env file in the project root (gitignored):
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_DEFAULT_REGION=us-east-1
Claude Code MCP Plugin
The MCP plugin lets Claude Code deploy, validate, and diagnose your app using natural language — no Bash scripts needed.
Setup
The plugin is pre-configured in .mcp.json. Just open the project in VSCode with the Claude Code extension installed and reload the window (Ctrl+Shift+P → Developer: Reload Window). You should see deployagent-validator listed under /mcp.
Available tools
| What you say | Tool Claude uses |
|---|---|
| "deploy the project" | prepare_deploy → ask questions → update_deploy_config → deploy |
| "what's the status?" | get_deploy_logs |
| "show me the logs" | get_service_logs |
| "deployment failed / health check failing" | get_ecs_diagnostics |
| "check my Dockerfile" | validate_dockerfile |
| "check all files before deploy" | pre_deploy_check |
| "fix this file" (after user approves) | apply_fix |
Deploy flow
When you say "deploy the project", Claude will:
- Call
prepare_deploy— readsdeploy.yamland checks AWS for existing resources - Ask you to confirm or change:
- Container name and port
- Docker image tag
- Number of replicas
- Environment variables
- Warn you if the ECS service already exists (rolling update) or if the ALB is missing (needs service recreation)
- Call
deployand stream live logs every 10–15 seconds until done - Print the public App URL at the end
Auto-diagnosis
If a deployment fails, say "fix the deployment error" and Claude will call get_ecs_diagnostics to pull:
- ECS service events and rollout state
- Stopped task exit codes and crash reasons
- Last 60 lines from CloudWatch Logs
- ECR image existence check
Claude reads all of it and diagnoses the root cause automatically.
Configuration — deploy.yaml
service: my-app # label used for deploy history
region: us-east-1
cluster: my-cluster
image:
repository: 123456789.dkr.ecr.us-east-1.amazonaws.com/my-app
tag: latest # use git SHA for unique deploys
dockerfile: ./Dockerfile
build_context: .
ecs:
service_name: my-app-service
task_family: my-app-task
container_name: my-app
container_port: 8080 # port your app listens on inside the container
cpu: 256 # 256 = 0.25 vCPU
memory: 512 # MB
desired_count: 1
environment: # injected as ECS container env vars
NODE_ENV: production
PORT: "8080"
# DATABASE_URL: postgres://...
# Add your app's env vars here
alb:
name: my-app-alb # ALB name (created automatically if it doesn't exist)
target_group_name: my-app-tg
vpc_id: vpc-xxxxxxxxxxxxxxxxx # your VPC ID
subnets:
- subnet-xxxxxxxxxxxxxxxxx
- subnet-xxxxxxxxxxxxxxxxx
security_groups:
- sg-xxxxxxxxxxxxxxxxx
listener_port: 80
health:
endpoint: /health
timeout: 30
retries: 5
# Optional — remove if not using CloudFormation
# cloudformation:
# stack_name: my-app-infra
# template_file: ./infra/template.yaml
# parameters:
# Environment: production
Tip: Use git commit SHA as the tag so every deploy is unique:
# Linux/macOS
sed -i "s/tag: .*/tag: $(git rev-parse --short HEAD)/" deploy.yaml
# Windows PowerShell
(Get-Content deploy.yaml) -replace 'tag: .*', "tag: $(git rev-parse --short HEAD)" | Set-Content deploy.yaml
AWS Setup
Required IAM permissions
Your IAM user needs these permissions (AWS Console → IAM → Users → your user → Add inline policy):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:DescribeServices", "ecs:DescribeTaskDefinition", "ecs:ListTasks",
"ecs:DescribeTasks", "ecs:RegisterTaskDefinition", "ecs:UpdateService",
"ecs:CreateService", "ecs:DeleteService",
"ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability",
"ecr:PutImage", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart",
"ecr:CompleteLayerUpload", "ecr:DescribeImages", "ecr:DescribeRepositories",
"elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:DescribeTargetGroups", "elasticloadbalancing:CreateTargetGroup",
"elasticloadbalancing:DescribeListeners", "elasticloadbalancing:CreateListener",
"elasticloadbalancing:ModifyListener",
"logs:DescribeLogStreams", "logs:GetLogEvents", "logs:FilterLogEvents",
"cloudformation:DescribeStacks", "cloudformation:CreateChangeSet",
"cloudformation:DescribeChangeSet", "cloudformation:ExecuteChangeSet",
"iam:PassRole"
],
"Resource": "*"
}
]
}
One-time AWS resource creation
# Get your account ID
aws sts get-caller-identity --query Account --output text
# Create ECR repository
aws ecr create-repository --repository-name my-app --region us-east-1
# Create ECS cluster
aws ecs create-cluster --cluster-name my-cluster --region us-east-1
# Create ECS task execution role
aws iam create-role \
--role-name ecsTaskExecutionRole \
--assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"ecs-tasks.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
aws iam attach-role-policy \
--role-name ecsTaskExecutionRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
# Create CloudWatch log group
aws logs create-log-group --log-group-name /ecs/my-app-task --region us-east-1
# Look up your VPC, subnet, and security group
aws ec2 describe-vpcs --filters Name=isDefault,Values=true --query "Vpcs[0].VpcId" --output text
aws ec2 describe-subnets --filters Name=vpc-id,Values=<VPC_ID> --query "Subnets[*].SubnetId" --output text
aws ec2 describe-security-groups --filters Name=vpc-id,Values=<VPC_ID> Name=group-name,Values=default --query "SecurityGroups[0].GroupId" --output text
Paste those values into deploy.yaml under alb.vpc_id, alb.subnets, and alb.security_groups.
CLI Commands
You can also use the CLI directly (without Claude Code):
# Dry run — shows what will change, no AWS mutations
deployagent plan deploy.yaml
# Deploy (asks for confirmation)
deployagent apply deploy.yaml
# Deploy without prompt (CI/CD pipelines)
deployagent apply deploy.yaml --yes
# Live health check
deployagent status deploy.yaml
# View full deploy history
deployagent status deploy.yaml --history
# Roll back one deploy
deployagent rollback deploy.yaml
# Roll back two deploys
deployagent rollback deploy.yaml --steps 2
Troubleshooting
| Error | Fix |
|---|---|
docker: error during connect |
Start Docker Desktop |
LoadBalancerNotFound during plan |
ALB doesn't exist yet — it will be created on first deploy |
AccessDeniedException on CloudWatch |
Add logs:DescribeLogStreams and logs:GetLogEvents to your IAM policy |
Nothing to deploy |
Change the image tag — same tag = no change detected |
MCP server not showing in /mcp |
Ctrl+Shift+P → Developer: Reload Window |
| Health check failing after deploy | Say "fix the deployment error" — Claude will run diagnostics automatically |
| Task keeps crashing (exit=1) | Check CloudWatch logs — say "show me the logs" |
| Service has no public URL | ALB was not attached — delete the ECS service and redeploy |
Credits
Built by chiman45
- Typer — CLI framework
- boto3 — AWS SDK
- Rich — terminal output
- FastMCP — MCP server framework
- Claude Code — AI deployment assistant
MIT License — chiman24100@iiitnr.edu.in
Metadata
Release files for chims-deployment 1.0.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 |
|---|---|---|---|---|
| chims_deployment-1.0.0.tar.gz | 47.7 kB | Without provenance | Details for chims_deployment-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| chims_deployment-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for chims_deployment-1.0.0-py3-none-any.whl |
Total release size: 99.4 kB
Release files / chims_deployment-1.0.0.tar.gz
| Download URL | chims_deployment-1.0.0.tar.gz |
|---|---|
| Size | 47.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0ea5a009257092ea9a2ade15660d967f7f7dbe5d891801c692595c33de853928
|
|
BLAKE2b-256 checksum How to use checksums |
3839d1c0874f8beef00a77029172bc6fa0c75ecf6fc52d8709c1dc7d13765288
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / chims_deployment-1.0.0-py3-none-any.whl
| Download URL | chims_deployment-1.0.0-py3-none-any.whl |
|---|---|
| Size | 51.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
538092ec9d5c34b014c1622ac3336a5c22da841dba8a0980e28f8cc8871a5892
|
|
BLAKE2b-256 checksum How to use checksums |
078a6f4a7a65fc32375c649d9844028f1b96e29f47c74f5ab9c326b7a227e9ba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Security for chims-deployment 1.0.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.