Skip to content

Commit 7860f86

Browse files
authored
Merge branch 'main' into feat/ec2-fleet-strategy
2 parents c96db29 + cc615e8 commit 7860f86

30 files changed

Lines changed: 1945 additions & 89 deletions

File tree

.gitignore

Lines changed: 78 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

LEGAL_DISCLAIMER.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
3+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
4+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
5+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
6+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,76 @@ See the full [ROADMAP](./docs/guides/ROADMAP.md) for details on each iteration.
6969

7070
## Getting started
7171

72-
### Installation and deployment
72+
### Claude Code plugin (recommended)
73+
74+
This repository ships a [Claude Code plugin](https://docs.anthropic.com/en/docs/claude-code/plugins) that provides guided workflows for setup, deployment, task submission, and troubleshooting.
75+
76+
#### Installing the plugin
77+
78+
```bash
79+
git clone https://github.com/aws-samples/sample-autonomous-cloud-coding-agents.git
80+
cd sample-autonomous-cloud-coding-agents
81+
claude --plugin-dir docs/abca-plugin
82+
```
83+
84+
The `--plugin-dir` flag tells Claude Code to load the local plugin from the `docs/abca-plugin/` directory. The plugin's skills, commands, agents, and hooks will be available immediately.
85+
86+
> **Tip:** If you use Claude Code via VS Code or JetBrains, you can add `--plugin-dir docs/abca-plugin` to the extension's CLI arguments setting.
87+
88+
#### What the plugin provides
89+
90+
**Skills** (guided multi-step workflows — Claude activates these automatically based on your request):
91+
92+
| Skill | Triggers on | What it does |
93+
|-------|------------|--------------|
94+
| `setup` | "get started", "install", "first time setup" | Full guided setup: prerequisites, toolchain, deploy, smoke test |
95+
| `deploy` | "deploy", "cdk diff", "destroy" | Deploy, diff, or destroy the CDK stack with pre-checks |
96+
| `onboard-repo` | "add a repo", "onboard", 422 errors | Add a new GitHub repository via Blueprint construct |
97+
| `submit-task` | "submit task", "run agent", "review PR", "quick submit" | Submit a coding task with prompt quality coaching (supports quick mode) |
98+
| `troubleshoot` | "debug", "error", "not working", "failed" | Diagnose deployment, auth, or task execution issues |
99+
| `status` | "status", "health check", "is ABCA running" | Platform health check: stack status, running tasks, build health |
100+
101+
**Agents** (specialized subagents, spawned automatically or via the Agent tool):
102+
103+
| Agent | When it's used |
104+
|-------|---------------|
105+
| `cdk-expert` | CDK architecture, construct design, handler implementation, stack modifications |
106+
| `agent-debugger` | Task failure investigation, CloudWatch log analysis, agent runtime debugging |
107+
108+
**Hook** (runs automatically):
109+
110+
A `SessionStart` hook advertises available skills and agents so Claude can proactively suggest them when your request matches.
111+
112+
#### Local plugin development
113+
114+
If you're modifying the plugin itself, here's the file layout:
115+
116+
```
117+
docs/abca-plugin/
118+
plugin.json # Plugin manifest (name, version, description)
119+
skills/
120+
setup/SKILL.md # First-time setup workflow
121+
deploy/SKILL.md # CDK deployment workflow
122+
onboard-repo/SKILL.md # Repository onboarding workflow
123+
submit-task/SKILL.md # Task submission (guided + quick mode)
124+
troubleshoot/SKILL.md # Diagnostic workflow
125+
status/SKILL.md # Platform health check
126+
agents/
127+
cdk-expert.md # CDK infrastructure specialist
128+
agent-debugger.md # Task failure debugger
129+
hooks/
130+
hooks.json # SessionStart capability advertisement
131+
```
132+
133+
**Key conventions:**
134+
- The plugin lives under `docs/` to keep documentation and plugin content colocated
135+
- Skills live in subdirectories with a `SKILL.md` file (not flat `.md` files)
136+
- Agents are flat `.md` files with YAML frontmatter
137+
- The hook advertises plugin capabilities only (no project-specific content)
138+
139+
**After editing plugin files**, restart Claude Code with `claude --plugin-dir docs/abca-plugin` to pick up changes.
140+
141+
### Manual installation and deployment
73142

74143
Install [mise](https://mise.jdx.dev/getting-started.html) if you want to use repo tasks (`mise run install`, `mise run build`). For monorepo-prefixed tasks (`mise //cdk:build`, etc.), set **`MISE_EXPERIMENTAL=1`** — see [CONTRIBUTING.md](./CONTRIBUTING.md).
75144

agent/run.sh

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,56 @@ if [[ -z "${AWS_REGION:-}" ]]; then
111111
exit 1
112112
fi
113113

114+
# ---------------------------------------------------------------------------
115+
# Resolve AWS credentials (before Docker build to fail fast)
116+
# ---------------------------------------------------------------------------
117+
# Store resolved credentials in variables so they can be applied to DOCKER_ARGS
118+
# after the image is built. This avoids a lengthy Docker build only to discover
119+
# that AWS credentials are missing or expired.
120+
AWS_CRED_MODE=""
121+
RESOLVED_KEY=""
122+
RESOLVED_SECRET=""
123+
RESOLVED_TOKEN=""
124+
125+
if [[ -n "${AWS_ACCESS_KEY_ID:-}" ]]; then
126+
AWS_CRED_MODE="explicit"
127+
RESOLVED_KEY="${AWS_ACCESS_KEY_ID}"
128+
RESOLVED_SECRET="${AWS_SECRET_ACCESS_KEY}"
129+
RESOLVED_TOKEN="${AWS_SESSION_TOKEN:-}"
130+
echo " AWS: using explicit credentials (AWS_ACCESS_KEY_ID)"
131+
elif command -v aws &>/dev/null; then
132+
# Resolve credentials from the AWS CLI (handles SSO, profiles, credential files).
133+
# This avoids the need to mount ~/.aws and replicate the full credential chain
134+
# inside the container — SSO tokens in particular don't resolve well there.
135+
echo " AWS: resolving credentials via AWS CLI${AWS_PROFILE:+ (profile '${AWS_PROFILE}')}..."
136+
EXPORT_CMD=(aws configure export-credentials --format process)
137+
[[ -n "${AWS_PROFILE:-}" ]] && EXPORT_CMD+=(--profile "${AWS_PROFILE}")
138+
139+
CREDS_JSON=$("${EXPORT_CMD[@]}" 2>/dev/null) || {
140+
echo "ERROR: Failed to resolve AWS credentials via AWS CLI." >&2
141+
echo " Possible fixes:" >&2
142+
echo " - Run 'aws sso login${AWS_PROFILE:+ --profile ${AWS_PROFILE}}' if using SSO" >&2
143+
echo " - Run 'aws configure${AWS_PROFILE:+ --profile ${AWS_PROFILE}}' to set up a profile" >&2
144+
echo " - Export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY directly" >&2
145+
exit 1
146+
}
147+
148+
AWS_CRED_MODE="resolved"
149+
RESOLVED_KEY=$(echo "$CREDS_JSON" | python3 -c "import sys,json; c=json.load(sys.stdin); print(c['AccessKeyId'])")
150+
RESOLVED_SECRET=$(echo "$CREDS_JSON" | python3 -c "import sys,json; c=json.load(sys.stdin); print(c['SecretAccessKey'])")
151+
RESOLVED_TOKEN=$(echo "$CREDS_JSON" | python3 -c "import sys,json; c=json.load(sys.stdin); print(c.get('SessionToken',''))")
152+
echo " AWS: resolved temporary credentials (AccessKeyId: ${RESOLVED_KEY:0:8}...)"
153+
elif [[ -d "${HOME}/.aws" ]]; then
154+
AWS_CRED_MODE="mount"
155+
if [[ -n "${AWS_PROFILE:-}" ]]; then
156+
echo " AWS: mounting ~/.aws with profile '${AWS_PROFILE}' (SSO may not work)"
157+
else
158+
echo " AWS: mounting ~/.aws (using default profile)"
159+
fi
160+
else
161+
echo "WARNING: No AWS credentials detected. Set AWS_ACCESS_KEY_ID or AWS_PROFILE, or ensure ~/.aws exists." >&2
162+
fi
163+
114164
# ---------------------------------------------------------------------------
115165
# Build
116166
# ---------------------------------------------------------------------------
@@ -161,49 +211,17 @@ if [[ "$MODE" == "server" ]]; then
161211
DOCKER_ARGS+=(-p 8080:8080)
162212
fi
163213

164-
# AWS credentials: prefer explicit env vars, then resolve from profile/SSO
165-
if [[ -n "${AWS_ACCESS_KEY_ID:-}" ]]; then
166-
DOCKER_ARGS+=(
167-
-e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}"
168-
-e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}"
169-
)
170-
[[ -n "${AWS_SESSION_TOKEN:-}" ]] && DOCKER_ARGS+=(-e "AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}")
171-
echo " AWS: using explicit credentials (AWS_ACCESS_KEY_ID)"
172-
elif command -v aws &>/dev/null; then
173-
# Resolve credentials from the AWS CLI (handles SSO, profiles, credential files).
174-
# This avoids the need to mount ~/.aws and replicate the full credential chain
175-
# inside the container — SSO tokens in particular don't resolve well there.
176-
PROFILE_ARG=()
177-
[[ -n "${AWS_PROFILE:-}" ]] && PROFILE_ARG=(--profile "${AWS_PROFILE}")
178-
179-
echo " AWS: resolving credentials via AWS CLI${AWS_PROFILE:+ (profile '${AWS_PROFILE}')}..."
180-
CREDS_JSON=$(aws configure export-credentials "${PROFILE_ARG[@]}" --format process 2>/dev/null) || {
181-
echo "ERROR: Failed to resolve AWS credentials. Make sure you are logged in:" >&2
182-
echo " aws sso login${AWS_PROFILE:+ --profile ${AWS_PROFILE}}" >&2
183-
exit 1
184-
}
185-
186-
RESOLVED_KEY=$(echo "$CREDS_JSON" | python3 -c "import sys,json; c=json.load(sys.stdin); print(c['AccessKeyId'])")
187-
RESOLVED_SECRET=$(echo "$CREDS_JSON" | python3 -c "import sys,json; c=json.load(sys.stdin); print(c['SecretAccessKey'])")
188-
RESOLVED_TOKEN=$(echo "$CREDS_JSON" | python3 -c "import sys,json; c=json.load(sys.stdin); print(c.get('SessionToken',''))")
189-
214+
# Apply previously resolved AWS credentials to DOCKER_ARGS
215+
if [[ "$AWS_CRED_MODE" == "explicit" || "$AWS_CRED_MODE" == "resolved" ]]; then
190216
DOCKER_ARGS+=(
191217
-e "AWS_ACCESS_KEY_ID=${RESOLVED_KEY}"
192218
-e "AWS_SECRET_ACCESS_KEY=${RESOLVED_SECRET}"
193219
)
194220
[[ -n "${RESOLVED_TOKEN}" ]] && DOCKER_ARGS+=(-e "AWS_SESSION_TOKEN=${RESOLVED_TOKEN}")
195-
echo " AWS: resolved temporary credentials (AccessKeyId: ${RESOLVED_KEY:0:8}...)"
196-
elif [[ -d "${HOME}/.aws" ]]; then
221+
elif [[ "$AWS_CRED_MODE" == "mount" ]]; then
197222
# Fallback: mount ~/.aws directly (works for static credential files, not SSO)
198223
DOCKER_ARGS+=(-v "${HOME}/.aws:/home/agent/.aws:ro")
199-
if [[ -n "${AWS_PROFILE:-}" ]]; then
200-
DOCKER_ARGS+=(-e "AWS_PROFILE=${AWS_PROFILE}")
201-
echo " AWS: mounting ~/.aws with profile '${AWS_PROFILE}' (SSO may not work)"
202-
else
203-
echo " AWS: mounting ~/.aws (using default profile)"
204-
fi
205-
else
206-
echo "WARNING: No AWS credentials detected. Set AWS_ACCESS_KEY_ID or AWS_PROFILE, or ensure ~/.aws exists." >&2
224+
[[ -n "${AWS_PROFILE:-}" ]] && DOCKER_ARGS+=(-e "AWS_PROFILE=${AWS_PROFILE}")
207225
fi
208226

209227
echo ""

0 commit comments

Comments
 (0)