forked from farhoodlabs/skills
refactor: apply FAR-95 skills review follow-ups
- Remove `playwright-ephemeral/` and `shannon/` entirely per board direction - Fix `minimax-image-generation/SKILL.md` so YAML frontmatter is at line 1 - Add `minimax-image-generation/scripts/generate.sh` (argparse, error-checked, executable) and document invoking it via `bash scripts/generate.sh ...` - Deduplicate `minimax-image-generation/CLAUDE.md` against SKILL.md - `github-app-token`: write token to `$GH_CONFIG_DIR/.gh-token` (preferred) or `$AGENT_HOME/.gh-token` (fallback), fail loudly if neither is set instead of leaking to `mktemp` - Refresh root `CLAUDE.md` to match actual directory contents and patterns - Add root `README.md` with human-facing skills index Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -9,19 +9,21 @@ This is a **Claude Code skills repository**. Skills are reusable tools that exte
|
|||||||
## Skill Structure
|
## Skill Structure
|
||||||
|
|
||||||
Each skill follows this convention:
|
Each skill follows this convention:
|
||||||
- **`<skill-name>/SKILL.md`** — Required. Contains YAML frontmatter (`name`, `description`) and usage documentation. This is the entry point Claude Code reads when invoking the skill.
|
- **`<skill-name>/SKILL.md`** — Required. YAML frontmatter (`name`, `description`, …) MUST start on line 1. This is the entry point Claude Code reads when invoking the skill.
|
||||||
- **`<skill-name>/scripts/`** — Implementation scripts (bash). Scripts use `set -euo pipefail` and the `die()` pattern for error handling.
|
- **`<skill-name>/CLAUDE.md`** — Optional. Maintainer / implementation notes kept out of the user-facing SKILL.md to reduce per-invocation token cost.
|
||||||
|
- **`<skill-name>/scripts/`** — Optional. Implementation scripts (typically bash). Scripts use `set -euo pipefail` and the `die()` pattern for error handling. Invoke scripts via `bash scripts/<name>.sh` so they work even when the executable bit did not survive deployment — but also `chmod +x` them on commit.
|
||||||
|
- **`<skill-name>/references/`** — Optional. Supporting files such as YAML templates or long-form reference documentation.
|
||||||
|
|
||||||
## Current Skills
|
## Current Skills
|
||||||
|
|
||||||
- **`github-app-token`** — Documents how to generate short-lived GitHub App installation access tokens. Requires `GITHUB_APP_ID`, `GITHUB_APP_INSTALLATION_ID`, and `GITHUB_APP_PEM_FILE` env vars. Inline commands only — no bundled scripts.
|
- **`github-app-token`** — Generates a short-lived GitHub App installation access token, writes it to `.gh-token` under `$GH_CONFIG_DIR` (preferred) or `$AGENT_HOME` (fallback), and authenticates the `gh` CLI. Requires `GITHUB_APP_ID`, `GITHUB_APP_INSTALLATION_ID`, and one of `GITHUB_APP_PEM` (inline PEM) or `GITHUB_APP_PEM_FILE` (path). Depends on `openssl`, `curl`, `jq`, `gh`.
|
||||||
- **`playwright-ephemeral`** — Provisions ephemeral Playwright MCP browser sessions as Kubernetes Jobs for E2E testing. Creates a Job + Service pair in a dedicated namespace, waits for readiness, and returns the MCP endpoint URL. Requires `kubectl` and appropriate RBAC.
|
- **`minimax-image-generation`** — Generates images from MiniMax's `image-01` model via `/v1/image_generation`. Requires `MINIMAX_API_KEY`; `MINIMAX_API_BASE_URL` is optional. Depends on `curl`, `jq`, `base64`.
|
||||||
- **`shannon`** — Autonomous AI pentester for web apps and APIs. Wraps the Docker-based Shannon pentester as a `/shannon` slash command. Requires `docker`, `git`, and an AI API key (`ANTHROPIC_API_KEY` or equivalent).
|
|
||||||
|
|
||||||
## Key Patterns
|
## Key Patterns
|
||||||
|
|
||||||
- Scripts are pure bash with no external dependencies beyond standard Unix tools (`openssl`, `curl`, `jq`, `kubectl`, `docker`).
|
- Standard Unix tools only (`openssl`, `curl`, `jq`, `base64`). Any skill-specific runtime requirement (e.g. `gh`) is declared in that skill's `SKILL.md`.
|
||||||
- The `die()` function prints errors to stderr and exits non-zero.
|
- `die()` prints errors to stderr and exits non-zero.
|
||||||
|
- Scripts validate required env vars up front and fail loudly rather than defaulting to `mktemp`/`/tmp` for anything secret.
|
||||||
|
|
||||||
## No Build/Test/Lint System
|
## No Build/Test/Lint System
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Skills
|
||||||
|
|
||||||
|
A collection of Claude Code skills — reusable tools that extend Claude Code's capabilities. Each skill lives in its own top-level directory and ships a `SKILL.md` (the entry point Claude Code reads when invoking the skill) plus any supporting scripts or references.
|
||||||
|
|
||||||
|
## Available skills
|
||||||
|
|
||||||
|
| Skill | What it does |
|
||||||
|
|---|---|
|
||||||
|
| [`github-app-token`](./github-app-token) | Generate a short-lived GitHub App installation access token and authenticate the `gh` CLI with it. |
|
||||||
|
| [`minimax-image-generation`](./minimax-image-generation) | Generate images from MiniMax's `image-01` model via the `/v1/image_generation` endpoint. |
|
||||||
|
|
||||||
|
## Skill layout
|
||||||
|
|
||||||
|
```
|
||||||
|
<skill-name>/
|
||||||
|
├── SKILL.md # Required. YAML frontmatter (name, description) + usage docs.
|
||||||
|
├── CLAUDE.md # Optional. Maintainer / implementation notes.
|
||||||
|
└── scripts/ # Optional. Bash or other implementation scripts.
|
||||||
|
```
|
||||||
|
|
||||||
|
Scripts use `set -euo pipefail` and a shared `die()` pattern for error handling. Scripts are invoked via `bash scripts/<name>.sh` (not `./scripts/<name>.sh`) so that they work even when the executable bit did not survive deployment.
|
||||||
|
|
||||||
|
## No build / test / lint tooling
|
||||||
|
|
||||||
|
There is no centralized build, test, or lint system. Each skill is self-contained and pulls in only standard Unix tools as declared in its `SKILL.md`.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
- New skills get a new top-level directory with at minimum a `SKILL.md` that starts with YAML frontmatter on line 1.
|
||||||
|
- Keep `SKILL.md` focused on decision flow + user-facing usage. Move implementation details, API references, and rarely-needed tables into `CLAUDE.md` or a `references/` subdirectory to keep per-invocation token cost low.
|
||||||
|
- Add a row to the table above.
|
||||||
@@ -24,6 +24,6 @@ Generate a short-lived GitHub App installation token and authenticate `gh`.
|
|||||||
bash github-app-token/scripts/generate-token.sh
|
bash github-app-token/scripts/generate-token.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
The script validates env vars, generates a JWT, exchanges it for an installation token, writes the token to `$AGENT_HOME/.gh-token`, and runs `gh auth login`. On success it prints a confirmation line. On failure it exits non-zero with a descriptive error.
|
The script validates env vars, generates a JWT, exchanges it for an installation token, writes the token to `.gh-token` inside `$GH_CONFIG_DIR` (preferred) or `$AGENT_HOME` (fallback), and runs `gh auth login`. If neither `GH_CONFIG_DIR` nor `AGENT_HOME` is set the script exits non-zero rather than silently writing the token to a default location. On success it prints a confirmation line. On failure it exits non-zero with a descriptive error.
|
||||||
|
|
||||||
Requires `openssl`, `curl`, `jq`, and `gh`.
|
Requires `openssl`, `curl`, `jq`, and `gh`.
|
||||||
|
|||||||
@@ -49,9 +49,20 @@ RESPONSE=$(curl -sf -X POST \
|
|||||||
TOKEN=$(echo "$RESPONSE" | jq -r '.token // empty')
|
TOKEN=$(echo "$RESPONSE" | jq -r '.token // empty')
|
||||||
[[ -z "$TOKEN" ]] && die "No token in GitHub response: $RESPONSE"
|
[[ -z "$TOKEN" ]] && die "No token in GitHub response: $RESPONSE"
|
||||||
|
|
||||||
# --- Write token to file ---
|
# --- Resolve token file location ---
|
||||||
GH_TOKEN_FILE="${AGENT_HOME:+${AGENT_HOME}/.gh-token}"
|
# Prefer GH_CONFIG_DIR (so the token lives alongside the per-agent gh config),
|
||||||
GH_TOKEN_FILE="${GH_TOKEN_FILE:-$(mktemp)}"
|
# fall back to AGENT_HOME, fail loudly if neither is set rather than silently
|
||||||
|
# writing to /tmp and leaking the token.
|
||||||
|
if [[ -n "${GH_CONFIG_DIR:-}" ]]; then
|
||||||
|
GH_TOKEN_DIR="$GH_CONFIG_DIR"
|
||||||
|
elif [[ -n "${AGENT_HOME:-}" ]]; then
|
||||||
|
GH_TOKEN_DIR="$AGENT_HOME"
|
||||||
|
else
|
||||||
|
die "Neither GH_CONFIG_DIR nor AGENT_HOME is set — refusing to write the token to a default location"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$GH_TOKEN_DIR"
|
||||||
|
GH_TOKEN_FILE="$GH_TOKEN_DIR/.gh-token"
|
||||||
|
|
||||||
printf '%s' "$TOKEN" > "$GH_TOKEN_FILE"
|
printf '%s' "$TOKEN" > "$GH_TOKEN_FILE"
|
||||||
chmod 600 "$GH_TOKEN_FILE"
|
chmod 600 "$GH_TOKEN_FILE"
|
||||||
|
|||||||
@@ -1,62 +1,32 @@
|
|||||||
# MiniMax Image Generation — Implementation Notes
|
# MiniMax Image Generation — Implementation Notes
|
||||||
|
|
||||||
|
User-facing docs (aspect ratios, usage, env vars) live in `SKILL.md`. This file is for maintenance notes only.
|
||||||
|
|
||||||
## API Reference
|
## API Reference
|
||||||
|
|
||||||
- **Endpoint**: `POST /v1/image_generation`
|
- **Endpoint**: `POST /v1/image_generation`
|
||||||
- **Base URL**: `https://api.minimax.io` (international) or `https://api.minimaxi.com` (China)
|
- **Base URL**: `https://api.minimax.io` (international) or `https://api.minimaxi.com` (China)
|
||||||
- **Auth**: `Authorization: Bearer <MINIMAX_API_KEY>`
|
- **Auth**: `Authorization: Bearer <MINIMAX_API_KEY>`
|
||||||
- **Model**: `image-01`
|
- **Model**: `image-01`
|
||||||
- **Response**: JSON with `data.image_base64[]` array
|
- **Response**: JSON with `data.image_base64[]` array; errors surface in `base_resp.status_code` / `base_resp.status_msg`.
|
||||||
|
|
||||||
## Example API Call
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -X POST "https://api.minimax.io/v1/image_generation" \
|
|
||||||
-H "Authorization: Bearer ${MINIMAX_API_KEY}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"model": "image-01",
|
|
||||||
"prompt": "men Dressing in white t shirt, full-body stand front view image :25, outdoor",
|
|
||||||
"aspect_ratio": "16:9",
|
|
||||||
"num_images": 1,
|
|
||||||
"response_format": "base64"
|
|
||||||
}'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Response Format
|
## Response Format
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"data": {
|
"data": { "image_base64": ["<base64-encoded-jpeg>"] },
|
||||||
"image_base64": ["<base64-encoded-jpeg>"]
|
|
||||||
},
|
|
||||||
"model": "image-01",
|
"model": "image-01",
|
||||||
"request_id": "<id>"
|
"request_id": "<id>",
|
||||||
|
"base_resp": { "status_code": 0, "status_msg": "success" }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Aspect Ratios
|
|
||||||
|
|
||||||
| Ratio | Dimensions | Use Case |
|
|
||||||
|-------|-----------|----------|
|
|
||||||
| `16:9` | 1920×1080 | Desktop wallpaper, banners |
|
|
||||||
| `1:1` | 1024×1024 | Social media, profile images |
|
|
||||||
| `9:16` | 1080×1920 | Mobile wallpaper, stories |
|
|
||||||
| `4:3` | 1024×768 | Presentations |
|
|
||||||
| `3:4` | 768×1024 | Posters, portraits |
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
- `curl` — HTTP requests
|
|
||||||
- `jq` — JSON parsing
|
|
||||||
- `base64` — Decode image data (coreutils)
|
|
||||||
|
|
||||||
All three are standard Unix tools. No Python or Node required.
|
|
||||||
|
|
||||||
## File Structure
|
## File Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
minimax-image-generation/
|
minimax-image-generation/
|
||||||
├── SKILL.md # Skill definition + user-facing docs
|
├── SKILL.md # Skill definition + user-facing docs
|
||||||
└── CLAUDE.md # These implementation notes
|
├── CLAUDE.md # These implementation notes
|
||||||
|
└── scripts/
|
||||||
|
└── generate.sh # Generate images (invoke via `bash scripts/generate.sh …`)
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,16 +1,3 @@
|
|||||||
# MiniMax Image Generation Skill
|
|
||||||
|
|
||||||
Claude Code skill for generating images via the MiniMax API.
|
|
||||||
Wraps the MiniMax `/v1/image_generation` endpoint as a `/minimax-image-generation` slash command.
|
|
||||||
|
|
||||||
## Structure
|
|
||||||
- `SKILL.md` — skill definition + usage documentation
|
|
||||||
- `CLAUDE.md` — implementation notes
|
|
||||||
|
|
||||||
## Rules
|
|
||||||
- Set `MINIMAX_API_KEY` env var before use
|
|
||||||
- Images are written to disk as `output-0.jpeg`, `output-1.jpeg`, etc.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
name: minimax-image-generation
|
name: minimax-image-generation
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
@@ -48,57 +35,31 @@ metadata:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
export MINIMAX_API_KEY="your-minimax-api-key"
|
export MINIMAX_API_KEY="your-minimax-api-key"
|
||||||
/minimax-image-generation "a cat wearing a spacesuit, cinematic photography"
|
bash minimax-image-generation/scripts/generate.sh "a cat wearing a spacesuit, cinematic photography"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
Always invoke the script via `bash scripts/generate.sh …` (or `bash minimax-image-generation/scripts/generate.sh …` when running from the repo root). Do **not** rely on the executable bit — invoking through `bash` is the supported entry point, and works even when the file permissions were not preserved during deployment.
|
||||||
|
|
||||||
## Parse User Intent
|
## Parse User Intent
|
||||||
|
|
||||||
Extract from the user's input:
|
Extract from the user's input:
|
||||||
|
|
||||||
1. **PROMPT**: The image description (required)
|
1. **PROMPT**: The image description (required, positional argument)
|
||||||
2. **ASPECT_RATIO**: `16:9` (default), `1:1`, `9:16`, `4:3`, `3:4`
|
2. **ASPECT_RATIO**: `16:9` (default), `1:1`, `9:16`, `4:3`, `3:4` — via `--aspect-ratio=<ratio>`
|
||||||
|
3. **COUNT**: number of images to generate (default `1`) — via `--count=<N>`
|
||||||
|
4. **OUTPUT_PREFIX**: filename stem (default `output`) — via `--output=<stem>`
|
||||||
|
|
||||||
---
|
## Script Usage
|
||||||
|
|
||||||
## API Call Example
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Verify credentials
|
bash minimax-image-generation/scripts/generate.sh \
|
||||||
if [ -z "${MINIMAX_API_KEY:-}" ]; then
|
"a sunset over the ocean, cinematic" \
|
||||||
echo "ERROR: MINIMAX_API_KEY is not set."
|
--aspect-ratio=16:9 \
|
||||||
exit 1
|
--count=1 \
|
||||||
fi
|
--output=sunset
|
||||||
|
|
||||||
API_BASE_URL="${MINIMAX_API_BASE_URL:-https://api.minimax.io}"
|
|
||||||
PROMPT="<your prompt here>"
|
|
||||||
ASPECT_RATIO="16:9"
|
|
||||||
|
|
||||||
# Call the API
|
|
||||||
response=$(curl -s -X POST "${API_BASE_URL}/v1/image_generation" \
|
|
||||||
-H "Authorization: Bearer ${MINIMAX_API_KEY}" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{
|
|
||||||
\"model\": \"image-01\",
|
|
||||||
\"prompt\": \"${PROMPT}\",
|
|
||||||
\"aspect_ratio\": \"${ASPECT_RATIO}\",
|
|
||||||
\"response_format\": \"base64\"
|
|
||||||
}")
|
|
||||||
|
|
||||||
# Decode and save
|
|
||||||
images=$(echo "$response" | jq -r '.data.image_base64[]')
|
|
||||||
idx=0
|
|
||||||
for image_b64 in $images; do
|
|
||||||
echo "$image_b64" | base64 -d > "output-${idx}.jpeg"
|
|
||||||
echo "Saved: output-${idx}.jpeg"
|
|
||||||
idx=$((idx + 1))
|
|
||||||
done
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Replace `<your prompt here>` with the user's image description.**
|
The script writes `<output>-0.jpeg`, `<output>-1.jpeg`, … to the current working directory. On failure it exits non-zero with a descriptive error.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Aspect Ratio Guide
|
## Aspect Ratio Guide
|
||||||
|
|
||||||
@@ -110,28 +71,13 @@ done
|
|||||||
| `4:3` | Standard — presentations, blog images |
|
| `4:3` | Standard — presentations, blog images |
|
||||||
| `3:4` | Portrait standard — posters, portraits |
|
| `3:4` | Portrait standard — posters, portraits |
|
||||||
|
|
||||||
---
|
## Environment Variables
|
||||||
|
|
||||||
## Configuration Reference
|
|
||||||
|
|
||||||
### Environment Variables
|
|
||||||
|
|
||||||
| Variable | Required | Description |
|
| Variable | Required | Description |
|
||||||
|----------|----------|-------------|
|
|----------|----------|-------------|
|
||||||
| `MINIMAX_API_KEY` | Yes | Your MiniMax API key |
|
| `MINIMAX_API_KEY` | Yes | Your MiniMax API key |
|
||||||
| `MINIMAX_API_BASE_URL` | No | API base URL (default: `https://api.minimax.io`) |
|
| `MINIMAX_API_BASE_URL` | No | API base URL (default: `https://api.minimax.io`) |
|
||||||
|
|
||||||
### API Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Default | Description |
|
|
||||||
|-----------|------|---------|-------------|
|
|
||||||
| `model` | string | `image-01` | Model to use |
|
|
||||||
| `prompt` | string | required | Image description |
|
|
||||||
| `aspect_ratio` | string | `16:9` | Image aspect ratio |
|
|
||||||
| `response_format` | string | `base64` | Output format |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
Executable
+83
@@ -0,0 +1,83 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# generate.sh — Generate images via MiniMax /v1/image_generation.
|
||||||
|
# Usage: bash scripts/generate.sh "<prompt>" [--aspect-ratio=16:9] [--count=1] [--output=output]
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
die() { echo "ERROR: $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
# --- Dependencies ---
|
||||||
|
for cmd in curl jq base64; do
|
||||||
|
command -v "$cmd" >/dev/null 2>&1 || die "Required command not found: $cmd"
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- Credentials ---
|
||||||
|
[[ -z "${MINIMAX_API_KEY:-}" ]] && die "MINIMAX_API_KEY is not set"
|
||||||
|
API_BASE_URL="${MINIMAX_API_BASE_URL:-https://api.minimax.io}"
|
||||||
|
|
||||||
|
# --- Parse args ---
|
||||||
|
PROMPT=""
|
||||||
|
ASPECT_RATIO="16:9"
|
||||||
|
COUNT=1
|
||||||
|
OUTPUT_PREFIX="output"
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--aspect-ratio=*) ASPECT_RATIO="${arg#*=}" ;;
|
||||||
|
--count=*) COUNT="${arg#*=}" ;;
|
||||||
|
--output=*) OUTPUT_PREFIX="${arg#*=}" ;;
|
||||||
|
--*) die "Unknown flag: $arg" ;;
|
||||||
|
*) if [[ -z "$PROMPT" ]]; then PROMPT="$arg"; else die "Unexpected positional argument: $arg"; fi ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -z "$PROMPT" ]] && die "Usage: bash scripts/generate.sh \"<prompt>\" [--aspect-ratio=16:9] [--count=1] [--output=output]"
|
||||||
|
|
||||||
|
case "$ASPECT_RATIO" in
|
||||||
|
16:9|1:1|9:16|4:3|3:4) ;;
|
||||||
|
*) die "Unsupported aspect ratio: $ASPECT_RATIO (valid: 16:9, 1:1, 9:16, 4:3, 3:4)" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if ! [[ "$COUNT" =~ ^[0-9]+$ ]] || (( COUNT < 1 )); then
|
||||||
|
die "Invalid --count: $COUNT (must be a positive integer)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🎨 MiniMax Image Generation" >&2
|
||||||
|
echo "├─ Prompt: \"$PROMPT\"" >&2
|
||||||
|
echo "├─ Aspect ratio: $ASPECT_RATIO" >&2
|
||||||
|
echo "├─ Count: $COUNT" >&2
|
||||||
|
echo "└─ Model: image-01" >&2
|
||||||
|
echo "" >&2
|
||||||
|
|
||||||
|
# --- Build JSON payload safely (jq handles escaping) ---
|
||||||
|
PAYLOAD=$(jq -n \
|
||||||
|
--arg prompt "$PROMPT" \
|
||||||
|
--arg ratio "$ASPECT_RATIO" \
|
||||||
|
--argjson n "$COUNT" \
|
||||||
|
'{model:"image-01", prompt:$prompt, aspect_ratio:$ratio, num_images:$n, response_format:"base64"}')
|
||||||
|
|
||||||
|
# --- Call API ---
|
||||||
|
RESPONSE=$(curl -sS -X POST "${API_BASE_URL}/v1/image_generation" \
|
||||||
|
-H "Authorization: Bearer ${MINIMAX_API_KEY}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$PAYLOAD") || die "MiniMax API request failed"
|
||||||
|
|
||||||
|
# --- Check for API error ---
|
||||||
|
ERR=$(echo "$RESPONSE" | jq -r '.base_resp.status_msg // empty')
|
||||||
|
CODE=$(echo "$RESPONSE" | jq -r '.base_resp.status_code // 0')
|
||||||
|
if [[ "$CODE" != "0" && -n "$ERR" ]]; then
|
||||||
|
die "MiniMax API error (code=$CODE): $ERR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Decode and save ---
|
||||||
|
COUNT_SAVED=0
|
||||||
|
while IFS= read -r image_b64; do
|
||||||
|
[[ -z "$image_b64" ]] && continue
|
||||||
|
OUT="${OUTPUT_PREFIX}-${COUNT_SAVED}.jpeg"
|
||||||
|
echo "$image_b64" | base64 -d > "$OUT" || die "Failed to decode image $COUNT_SAVED"
|
||||||
|
echo "Saved: $OUT" >&2
|
||||||
|
COUNT_SAVED=$((COUNT_SAVED + 1))
|
||||||
|
done < <(echo "$RESPONSE" | jq -r '.data.image_base64[]?')
|
||||||
|
|
||||||
|
(( COUNT_SAVED == 0 )) && die "No images returned: $RESPONSE"
|
||||||
|
|
||||||
|
echo "Done." >&2
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Shannon Skill
|
|
||||||
|
|
||||||
Claude Code skill for autonomous AI pentesting via Shannon.
|
|
||||||
Wraps the Docker-based Shannon pentester as a `/shannon` slash command.
|
|
||||||
|
|
||||||
## Structure
|
|
||||||
- `SKILL.md` — skill definition (deployed to ~/.claude/skills/shannon/)
|
|
||||||
- `scripts/setup-shannon.sh` — installer/updater for Shannon
|
|
||||||
- `scripts/sync.sh` — deploy to ~/.claude, ~/.agents, ~/.codex
|
|
||||||
|
|
||||||
## Commands
|
|
||||||
```bash
|
|
||||||
bash scripts/sync.sh # Deploy to all skill locations
|
|
||||||
```
|
|
||||||
|
|
||||||
## Rules
|
|
||||||
- ALWAYS confirm authorization before running pentests
|
|
||||||
- NEVER target production systems
|
|
||||||
- After edits: run `bash scripts/sync.sh` to deploy
|
|
||||||
@@ -1,536 +0,0 @@
|
|||||||
---
|
|
||||||
name: shannon
|
|
||||||
version: "1.0.0"
|
|
||||||
description: "Autonomous AI pentester for web apps and APIs. Run white-box security assessments with Shannon — analyzes source code, identifies attack vectors, and executes real exploits to prove vulnerabilities. Triggered by 'shannon', 'pentest', 'security audit', 'vuln scan'."
|
|
||||||
argument-hint: 'shannon http://localhost:3000 myapp, shannon --workspace=audit1 http://staging.example.com myrepo'
|
|
||||||
allowed-tools: Bash, Read, Write, AskUserQuestion, WebSearch
|
|
||||||
homepage: https://github.com/KeygraphHQ/shannon
|
|
||||||
repository: https://github.com/KeygraphHQ/shannon
|
|
||||||
author: KeygraphHQ
|
|
||||||
license: AGPL-3.0
|
|
||||||
user-invocable: true
|
|
||||||
metadata:
|
|
||||||
openclaw:
|
|
||||||
emoji: "🔐"
|
|
||||||
category: "security"
|
|
||||||
requires:
|
|
||||||
env:
|
|
||||||
- ANTHROPIC_API_KEY
|
|
||||||
optionalEnv:
|
|
||||||
- ANTHROPIC_AUTH_TOKEN
|
|
||||||
- ANTHROPIC_BASE_URL
|
|
||||||
- ANTHROPIC_MODEL
|
|
||||||
- ANTHROPIC_SMALL_FAST_MODEL
|
|
||||||
- CLAUDE_CODE_OAUTH_TOKEN
|
|
||||||
- CLAUDE_CODE_USE_BEDROCK
|
|
||||||
- CLAUDE_CODE_USE_VERTEX
|
|
||||||
- AWS_REGION
|
|
||||||
- AWS_ACCESS_KEY_ID
|
|
||||||
- AWS_SECRET_ACCESS_KEY
|
|
||||||
bins:
|
|
||||||
- docker
|
|
||||||
- git
|
|
||||||
primaryEnv: ANTHROPIC_API_KEY
|
|
||||||
files:
|
|
||||||
- "scripts/*"
|
|
||||||
tags:
|
|
||||||
- security
|
|
||||||
- pentesting
|
|
||||||
- pentest
|
|
||||||
- vulnerability
|
|
||||||
- exploit
|
|
||||||
- owasp
|
|
||||||
- xss
|
|
||||||
- sqli
|
|
||||||
- ssrf
|
|
||||||
- authentication
|
|
||||||
- authorization
|
|
||||||
- white-box
|
|
||||||
- appsec
|
|
||||||
---
|
|
||||||
|
|
||||||
# Shannon: Autonomous AI Pentester for Web Apps & APIs
|
|
||||||
|
|
||||||
> **Permissions overview:** This skill orchestrates Shannon, a Docker-based pentesting tool that actively executes attacks against a target application. It clones/updates the Shannon repo locally, runs Docker containers, and reads pentest reports. **Shannon performs real exploits — only run against apps you own or have explicit written authorization to test.** Never run against production systems.
|
|
||||||
|
|
||||||
Shannon analyzes your source code, identifies attack vectors, and executes real exploits to prove vulnerabilities before they reach production. 96.15% exploit success rate on the XBOW security benchmark. Covers OWASP Top 10: Injection, XSS, SSRF, Broken Auth, Broken AuthZ, and more.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## CRITICAL: Safety Checks (ALWAYS run first)
|
|
||||||
|
|
||||||
Before doing ANYTHING, you MUST confirm:
|
|
||||||
|
|
||||||
1. **Authorization**: Ask the user — "Do you have explicit authorization to pentest this target?" If they say no or are unsure, STOP and explain they need written permission from the system owner.
|
|
||||||
2. **Environment**: Confirm the target is a local, staging, or sandboxed environment — NEVER production.
|
|
||||||
3. **Scope**: Clarify what they want tested (full pentest vs specific category).
|
|
||||||
|
|
||||||
```
|
|
||||||
⚠️ Shannon executes REAL ATTACKS with mutative effects.
|
|
||||||
├─ Only run on systems you OWN or have WRITTEN AUTHORIZATION to test
|
|
||||||
├─ Never target production environments
|
|
||||||
├─ Results require human review — LLM output may contain hallucinations
|
|
||||||
└─ You are responsible for complying with all applicable laws
|
|
||||||
```
|
|
||||||
|
|
||||||
Display this warning BEFORE every pentest run. If the user has already confirmed authorization in this session, a brief reminder suffices.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Parse User Intent
|
|
||||||
|
|
||||||
Extract from the user's input:
|
|
||||||
|
|
||||||
1. **TARGET_URL**: The URL to pentest (e.g., `http://localhost:3000`, `http://staging.example.com`)
|
|
||||||
2. **REPO_NAME**: The source code folder name (placed in `./repos/` inside Shannon)
|
|
||||||
3. **SCOPE**: Full pentest (default) or specific categories (injection, xss, ssrf, auth, authz)
|
|
||||||
4. **WORKSPACE**: Named workspace for resume capability (optional)
|
|
||||||
5. **CONFIG**: Custom YAML config path (optional, for auth flows, focus/avoid rules)
|
|
||||||
|
|
||||||
Common invocation patterns:
|
|
||||||
- `/shannon http://localhost:3000 myapp` → Full pentest of local app
|
|
||||||
- `/shannon --workspace=audit1 http://staging.example.com backend-api` → Named workspace for resuming
|
|
||||||
- `/shannon --scope=xss,injection http://localhost:8080 frontend` → Targeted categories
|
|
||||||
- `/shannon status` → Check running pentests
|
|
||||||
- `/shannon results` → Show latest report
|
|
||||||
- `/shannon stop` → Stop running pentest
|
|
||||||
|
|
||||||
Display parsed intent:
|
|
||||||
```
|
|
||||||
🔐 Shannon Pentest
|
|
||||||
├─ Target: {TARGET_URL}
|
|
||||||
├─ Source: repos/{REPO_NAME}
|
|
||||||
├─ Scope: {SCOPE or "Full (all 5 OWASP categories)"}
|
|
||||||
├─ Workspace: {WORKSPACE or "auto-generated"}
|
|
||||||
└─ Config: {CONFIG or "default"}
|
|
||||||
|
|
||||||
Estimated runtime: 1–1.5 hours │ Estimated cost: ~$50 (Claude Sonnet)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 0: Ensure Shannon is Installed
|
|
||||||
|
|
||||||
Check if Shannon is cloned locally:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
SHANNON_HOME="${SHANNON_HOME:-$HOME/shannon}"
|
|
||||||
|
|
||||||
if [ -d "$SHANNON_HOME" ] && [ -f "$SHANNON_HOME/shannon" ]; then
|
|
||||||
echo "Shannon found at $SHANNON_HOME"
|
|
||||||
cd "$SHANNON_HOME" && git pull --ff-only 2>/dev/null || true
|
|
||||||
else
|
|
||||||
echo "Shannon not found. Cloning..."
|
|
||||||
git clone https://github.com/KeygraphHQ/shannon.git "$SHANNON_HOME"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Verify Docker is available
|
|
||||||
if command -v docker &>/dev/null; then
|
|
||||||
echo "Docker: $(docker --version)"
|
|
||||||
else
|
|
||||||
echo "ERROR: Docker is required. Install Docker Desktop: https://docker.com/products/docker-desktop"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
If Shannon is not installed, clone it and inform the user. If Docker is missing, stop and tell them to install it.
|
|
||||||
|
|
||||||
**SHANNON_HOME** defaults to `~/shannon`. Users can override with `SHANNON_HOME` env var.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 1: Prepare Source Code
|
|
||||||
|
|
||||||
Shannon needs the target's source code in `$SHANNON_HOME/repos/{REPO_NAME}/`.
|
|
||||||
|
|
||||||
Ask the user where their source code is:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# If user provides a local path
|
|
||||||
REPO_PATH="/path/to/their/source"
|
|
||||||
REPO_NAME="myapp"
|
|
||||||
|
|
||||||
# Create symlink or copy into Shannon's repos directory
|
|
||||||
mkdir -p "$SHANNON_HOME/repos"
|
|
||||||
if [ ! -d "$SHANNON_HOME/repos/$REPO_NAME" ]; then
|
|
||||||
ln -s "$(realpath "$REPO_PATH")" "$SHANNON_HOME/repos/$REPO_NAME"
|
|
||||||
echo "Linked $REPO_PATH → repos/$REPO_NAME"
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
If the user provides a GitHub URL instead:
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME/repos"
|
|
||||||
git clone "$GITHUB_URL" "$REPO_NAME"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 2: Configure Authentication (if needed)
|
|
||||||
|
|
||||||
If the target requires login, help the user create a YAML config:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# $SHANNON_HOME/configs/target-config.yaml
|
|
||||||
authentication:
|
|
||||||
type: form # "form" or "sso"
|
|
||||||
login_url: "http://localhost:3000/login"
|
|
||||||
credentials:
|
|
||||||
username: "admin"
|
|
||||||
password: "password123"
|
|
||||||
flow: "Navigate to login page, enter username and password, click Sign In"
|
|
||||||
success_condition:
|
|
||||||
url_contains: "/dashboard"
|
|
||||||
|
|
||||||
rules:
|
|
||||||
avoid:
|
|
||||||
- "/logout"
|
|
||||||
- "/admin/delete"
|
|
||||||
focus:
|
|
||||||
- "/api/"
|
|
||||||
- "/auth/"
|
|
||||||
|
|
||||||
pipeline:
|
|
||||||
max_concurrent_pipelines: 5 # 1-5, default 5
|
|
||||||
```
|
|
||||||
|
|
||||||
**Only create a config if the target requires authentication or has specific scope rules.** For open/unauthenticated targets, no config is needed.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 3: Verify API Credentials
|
|
||||||
|
|
||||||
Check that AI provider credentials are available:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME"
|
|
||||||
|
|
||||||
# Check for AI provider credentials
|
|
||||||
if [ -n "${ANTHROPIC_API_KEY:-}" ]; then
|
|
||||||
echo "✅ ANTHROPIC_API_KEY is set"
|
|
||||||
elif [ -n "${ANTHROPIC_AUTH_TOKEN:-}" ] && [ -n "${ANTHROPIC_BASE_URL:-}" ]; then
|
|
||||||
echo "✅ MiniMax mode: ANTHROPIC_AUTH_TOKEN + ANTHROPIC_BASE_URL are set"
|
|
||||||
echo " Base URL: $ANTHROPIC_BASE_URL"
|
|
||||||
echo " Model: ${ANTHROPIC_MODEL:-MiniMax-M2.7}"
|
|
||||||
elif [ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]; then
|
|
||||||
echo "✅ CLAUDE_CODE_OAUTH_TOKEN is set"
|
|
||||||
elif [ "${CLAUDE_CODE_USE_BEDROCK:-}" = "1" ]; then
|
|
||||||
echo "✅ AWS Bedrock mode enabled"
|
|
||||||
elif [ "${CLAUDE_CODE_USE_VERTEX:-}" = "1" ]; then
|
|
||||||
echo "✅ Google Vertex AI mode enabled"
|
|
||||||
else
|
|
||||||
echo "❌ No AI credentials found."
|
|
||||||
echo "Set one of: ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN+ANTHROPIC_BASE_URL (MiniMax), CLAUDE_CODE_OAUTH_TOKEN, or enable Bedrock/Vertex"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
If no credentials are found, explain the options:
|
|
||||||
- **Direct API** (recommended): `export ANTHROPIC_API_KEY=sk-ant-...`
|
|
||||||
- **MiniMax**: Set `ANTHROPIC_AUTH_TOKEN` and `ANTHROPIC_BASE_URL` (see MiniMax section below)
|
|
||||||
- **OAuth**: `export CLAUDE_CODE_OAUTH_TOKEN=...`
|
|
||||||
- **AWS Bedrock**: `export CLAUDE_CODE_USE_BEDROCK=1` + AWS credentials
|
|
||||||
- **Google Vertex**: `export CLAUDE_CODE_USE_VERTEX=1` + service account in `./credentials/`
|
|
||||||
|
|
||||||
Also recommend: `export CLAUDE_CODE_MAX_OUTPUT_TOKENS=64000`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 4: Launch the Pentest
|
|
||||||
|
|
||||||
**CRITICAL: Confirm with the user before launching.** Display the full command and wait for approval.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME"
|
|
||||||
|
|
||||||
# Build the command
|
|
||||||
CMD="./shannon start URL={TARGET_URL} REPO={REPO_NAME}"
|
|
||||||
|
|
||||||
# Add optional flags
|
|
||||||
# CONFIG=configs/target-config.yaml (if auth config exists)
|
|
||||||
# WORKSPACE={WORKSPACE} (if user specified)
|
|
||||||
# OUTPUT=./audit-logs/ (default)
|
|
||||||
|
|
||||||
echo "Ready to launch:"
|
|
||||||
echo " $CMD"
|
|
||||||
echo ""
|
|
||||||
echo "This will start Docker containers and begin the pentest."
|
|
||||||
echo "Runtime: ~1-1.5 hours │ Cost: ~\$50 (Claude Sonnet)"
|
|
||||||
```
|
|
||||||
|
|
||||||
After user confirms, run in background:
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME" && ./shannon start URL={TARGET_URL} REPO={REPO_NAME} {EXTRA_FLAGS}
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `run_in_background: true` with a timeout of 600000ms (10 minutes for initial setup). The pentest itself runs in Docker and will continue independently.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 5: Monitor Progress
|
|
||||||
|
|
||||||
While the pentest runs, the user can check status:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME"
|
|
||||||
|
|
||||||
# List active workspaces
|
|
||||||
./shannon workspaces
|
|
||||||
|
|
||||||
# View logs for a specific workflow
|
|
||||||
./shannon logs ID={workflow-id}
|
|
||||||
```
|
|
||||||
|
|
||||||
Explain the 5-phase pipeline:
|
|
||||||
```
|
|
||||||
Shannon Pipeline (5 phases, parallel where possible):
|
|
||||||
├─ Phase 1: Pre-Recon — Source code analysis + external scans (Nmap, Subfinder, WhatWeb)
|
|
||||||
├─ Phase 2: Recon — Live attack surface mapping via browser automation
|
|
||||||
├─ Phase 3: Vulnerability Analysis — 5 parallel agents (Injection, XSS, SSRF, Auth, AuthZ)
|
|
||||||
├─ Phase 4: Exploitation — Dedicated agents execute real attacks to validate findings
|
|
||||||
└─ Phase 5: Reporting — Executive summary with reproducible PoCs
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 6: Read and Interpret Results
|
|
||||||
|
|
||||||
Reports are saved to `$SHANNON_HOME/audit-logs/{hostname}_{sessionId}/`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME"
|
|
||||||
|
|
||||||
# Find the latest report
|
|
||||||
LATEST=$(ls -td audit-logs/*/ 2>/dev/null | head -1)
|
|
||||||
if [ -n "$LATEST" ]; then
|
|
||||||
echo "Latest report: $LATEST"
|
|
||||||
# Find the main report file
|
|
||||||
find "$LATEST" -name "*.md" -type f | head -5
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
Read the report and present a summary:
|
|
||||||
|
|
||||||
```
|
|
||||||
🔐 Shannon Pentest Report: {TARGET}
|
|
||||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
||||||
|
|
||||||
🔴 Critical: {N} vulnerabilities
|
|
||||||
🟠 High: {N} vulnerabilities
|
|
||||||
🟡 Medium: {N} vulnerabilities
|
|
||||||
🔵 Low: {N} vulnerabilities
|
|
||||||
|
|
||||||
Top Findings:
|
|
||||||
1. [CRITICAL] {Vuln type} — {location} — PoC: {brief description}
|
|
||||||
2. [HIGH] {Vuln type} — {location} — PoC: {brief description}
|
|
||||||
3. ...
|
|
||||||
|
|
||||||
Each finding includes a reproducible proof-of-concept exploit.
|
|
||||||
```
|
|
||||||
|
|
||||||
**IMPORTANT: Shannon's "no exploit, no report" policy means every finding has a working PoC.** But remind the user that LLM-generated content requires human review.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Utility Commands
|
|
||||||
|
|
||||||
### Check status
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME" && ./shannon workspaces
|
|
||||||
```
|
|
||||||
|
|
||||||
### View logs
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME" && ./shannon logs ID={workflow-id}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Stop pentest
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME" && ./shannon stop
|
|
||||||
```
|
|
||||||
|
|
||||||
### Stop and clean up all data
|
|
||||||
```bash
|
|
||||||
# DESTRUCTIVE — confirm with user first
|
|
||||||
cd "$SHANNON_HOME" && ./shannon stop CLEAN=true
|
|
||||||
```
|
|
||||||
|
|
||||||
### Resume a previous workspace
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME" && ./shannon start URL={URL} REPO={REPO} WORKSPACE={name}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Targeting Local Apps
|
|
||||||
|
|
||||||
If the user's app runs on localhost, explain:
|
|
||||||
```
|
|
||||||
Shannon runs inside Docker. To reach your local app:
|
|
||||||
├─ Use http://host.docker.internal:{PORT} instead of http://localhost:{PORT}
|
|
||||||
├─ macOS/Windows: works automatically with Docker Desktop
|
|
||||||
└─ Linux: add --add-host=host.docker.internal:host-gateway to docker run
|
|
||||||
```
|
|
||||||
|
|
||||||
Automatically translate `localhost` URLs to `host.docker.internal` in the command.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Using MiniMax as AI Provider
|
|
||||||
|
|
||||||
Shannon supports [MiniMax](https://platform.minimax.io) as an alternative AI backend via the Anthropic SDK compatibility layer. MiniMax provides the `MiniMax-M2.7` model through an Anthropic-compatible API endpoint.
|
|
||||||
|
|
||||||
### MiniMax Setup
|
|
||||||
|
|
||||||
1. **Get a MiniMax API key** from [platform.minimax.io](https://platform.minimax.io).
|
|
||||||
|
|
||||||
2. **Configure environment variables** — either export them directly or add to `~/.claude/settings.json`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Export directly
|
|
||||||
export ANTHROPIC_AUTH_TOKEN="your-minimax-api-key"
|
|
||||||
export ANTHROPIC_BASE_URL="https://api.minimax.io/anthropic" # International
|
|
||||||
# export ANTHROPIC_BASE_URL="https://api.minimaxi.com/anthropic" # China
|
|
||||||
|
|
||||||
# Set model (all model slots use the same MiniMax model)
|
|
||||||
export ANTHROPIC_MODEL="MiniMax-M2.7"
|
|
||||||
export ANTHROPIC_SMALL_FAST_MODEL="MiniMax-M2.7"
|
|
||||||
export ANTHROPIC_DEFAULT_SONNET_MODEL="MiniMax-M2.7"
|
|
||||||
export ANTHROPIC_DEFAULT_OPUS_MODEL="MiniMax-M2.7"
|
|
||||||
export ANTHROPIC_DEFAULT_HAIKU_MODEL="MiniMax-M2.7"
|
|
||||||
```
|
|
||||||
|
|
||||||
Or in `~/.claude/settings.json`:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"env": {
|
|
||||||
"ANTHROPIC_AUTH_TOKEN": "your-minimax-api-key",
|
|
||||||
"ANTHROPIC_BASE_URL": "https://api.minimax.io/anthropic",
|
|
||||||
"ANTHROPIC_MODEL": "MiniMax-M2.7",
|
|
||||||
"ANTHROPIC_SMALL_FAST_MODEL": "MiniMax-M2.7",
|
|
||||||
"ANTHROPIC_DEFAULT_SONNET_MODEL": "MiniMax-M2.7",
|
|
||||||
"ANTHROPIC_DEFAULT_OPUS_MODEL": "MiniMax-M2.7",
|
|
||||||
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "MiniMax-M2.7",
|
|
||||||
"API_TIMEOUT_MS": "3000000",
|
|
||||||
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Clear conflicting env vars** — ensure `ANTHROPIC_API_KEY` is not set when using MiniMax, as it takes precedence:
|
|
||||||
```bash
|
|
||||||
unset ANTHROPIC_API_KEY
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Run Shannon normally** — the MiniMax credentials are passed through to Shannon's Docker containers via the Anthropic SDK compatibility layer:
|
|
||||||
```bash
|
|
||||||
cd "$SHANNON_HOME" && ./shannon start URL=http://localhost:3000 REPO=myapp
|
|
||||||
```
|
|
||||||
|
|
||||||
### MiniMax Notes
|
|
||||||
- MiniMax uses `ANTHROPIC_AUTH_TOKEN` (not `ANTHROPIC_API_KEY`) for authentication
|
|
||||||
- The `ANTHROPIC_BASE_URL` routes requests to MiniMax's Anthropic-compatible endpoint
|
|
||||||
- Set `API_TIMEOUT_MS=3000000` for extended timeouts (recommended for pentesting workloads)
|
|
||||||
- Set `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` to reduce non-essential API calls
|
|
||||||
- MiniMax provides a single model (`MiniMax-M2.7`) that is used for all model slots
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Configuration Reference
|
|
||||||
|
|
||||||
### Environment Variables
|
|
||||||
| Variable | Required | Description |
|
|
||||||
|----------|----------|-------------|
|
|
||||||
| `ANTHROPIC_API_KEY` | One of these | Direct Anthropic API key |
|
|
||||||
| `ANTHROPIC_AUTH_TOKEN` | required | MiniMax (or compatible) auth token |
|
|
||||||
| `ANTHROPIC_BASE_URL` | | API base URL (for MiniMax: `https://api.minimax.io/anthropic`) |
|
|
||||||
| `ANTHROPIC_MODEL` | | Model override (e.g., `MiniMax-M2.7`) |
|
|
||||||
| `ANTHROPIC_SMALL_FAST_MODEL` | | Small/fast model override |
|
|
||||||
| `CLAUDE_CODE_OAUTH_TOKEN` | | Anthropic OAuth token |
|
|
||||||
| `CLAUDE_CODE_USE_BEDROCK` | | Set to `1` for AWS Bedrock |
|
|
||||||
| `CLAUDE_CODE_USE_VERTEX` | | Set to `1` for Google Vertex AI |
|
|
||||||
| `CLAUDE_CODE_MAX_OUTPUT_TOKENS` | Recommended | Set to `64000` |
|
|
||||||
| `API_TIMEOUT_MS` | Optional | Request timeout in ms (MiniMax: `3000000`) |
|
|
||||||
| `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | Optional | Set to `1` to reduce non-essential calls |
|
|
||||||
| `SHANNON_HOME` | Optional | Shannon install dir (default: `~/shannon`) |
|
|
||||||
|
|
||||||
### YAML Config Options
|
|
||||||
| Section | Field | Description |
|
|
||||||
|---------|-------|-------------|
|
|
||||||
| `authentication.type` | `form` / `sso` | Login method |
|
|
||||||
| `authentication.login_url` | URL | Login page |
|
|
||||||
| `authentication.credentials` | object | username, password, totp_secret |
|
|
||||||
| `authentication.flow` | string | Natural language login instructions |
|
|
||||||
| `authentication.success_condition` | object | `url_contains` or `element_present` |
|
|
||||||
| `rules.avoid` | list | Paths/subdomains to skip |
|
|
||||||
| `rules.focus` | list | Paths/subdomains to prioritize |
|
|
||||||
| `pipeline.retry_preset` | `subscription` | Extended backoff for rate-limited plans |
|
|
||||||
| `pipeline.max_concurrent_pipelines` | 1-5 | Parallel agent count (default: 5) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Vulnerability Coverage
|
|
||||||
|
|
||||||
Shannon tests 50+ specific cases across 5 OWASP categories:
|
|
||||||
|
|
||||||
| Category | Examples |
|
|
||||||
|----------|----------|
|
|
||||||
| **Injection** | SQL injection, command injection, SSTI, NoSQL injection |
|
|
||||||
| **XSS** | Reflected, stored, DOM-based, via file upload |
|
|
||||||
| **SSRF** | Internal service access, cloud metadata, protocol smuggling |
|
|
||||||
| **Broken Auth** | Default creds, JWT flaws, session fixation, MFA bypass, CSRF |
|
|
||||||
| **Broken AuthZ** | IDOR, privilege escalation, path traversal, forced browsing |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Integrated Security Tools (bundled in Docker)
|
|
||||||
|
|
||||||
- **Nmap** — port scanning and service detection
|
|
||||||
- **Subfinder** — subdomain enumeration
|
|
||||||
- **WhatWeb** — web technology fingerprinting
|
|
||||||
- **Schemathesis** — API schema-based fuzzing
|
|
||||||
- **Chromium** — headless browser for automated exploitation (Playwright)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Context Memory
|
|
||||||
|
|
||||||
For the rest of this conversation, remember:
|
|
||||||
- **SHANNON_HOME**: Path to Shannon installation
|
|
||||||
- **TARGET_URL**: The URL being tested
|
|
||||||
- **REPO_NAME**: Source code folder name
|
|
||||||
- **WORKSPACE**: Workspace name (if any)
|
|
||||||
- **PENTEST_STATUS**: running / completed / stopped
|
|
||||||
|
|
||||||
When the user asks follow-up questions:
|
|
||||||
- Check pentest status and report on progress
|
|
||||||
- Read and interpret new findings from audit-logs
|
|
||||||
- Help remediate discovered vulnerabilities with code fixes
|
|
||||||
- Explain PoC exploits and their impact
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Security & Permissions
|
|
||||||
|
|
||||||
**What this skill does:**
|
|
||||||
- Clones/updates the Shannon repo from GitHub to `~/shannon` (or `$SHANNON_HOME`)
|
|
||||||
- Creates symlinks from user's source code into `~/shannon/repos/`
|
|
||||||
- Starts Docker containers (Temporal server, worker, optional router) via `./shannon` CLI
|
|
||||||
- Reads pentest reports from `~/shannon/audit-logs/`
|
|
||||||
- Optionally creates YAML config files in `~/shannon/configs/`
|
|
||||||
|
|
||||||
**What Shannon does (inside Docker):**
|
|
||||||
- Executes real exploits against the target URL (SQL injection, XSS, SSRF, etc.)
|
|
||||||
- Scans with Nmap, Subfinder, WhatWeb, Schemathesis
|
|
||||||
- Automates browser interactions via headless Chromium
|
|
||||||
- Sends prompts to Anthropic API (or Bedrock/Vertex) for reasoning
|
|
||||||
- Writes reports to `audit-logs/` directory
|
|
||||||
|
|
||||||
**What this skill does NOT do:**
|
|
||||||
- Does not target any system without user confirmation
|
|
||||||
- Does not store or transmit API keys beyond the configured provider
|
|
||||||
- Does not modify the user's source code
|
|
||||||
- Does not access production systems unless explicitly directed (which it warns against)
|
|
||||||
- Does not run without Docker — all attack tools are containerized
|
|
||||||
|
|
||||||
**Review the Shannon source code before first use:** https://github.com/KeygraphHQ/shannon
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# setup-shannon.sh - Install or update Shannon pentester
|
|
||||||
# Usage: bash scripts/setup-shannon.sh [SHANNON_HOME]
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
SHANNON_HOME="${1:-${SHANNON_HOME:-$HOME/shannon}}"
|
|
||||||
|
|
||||||
echo "🔐 Shannon Setup"
|
|
||||||
echo "━━━━━━━━━━━━━━━━"
|
|
||||||
|
|
||||||
# Check Docker
|
|
||||||
if ! command -v docker &>/dev/null; then
|
|
||||||
echo "❌ Docker is required but not installed."
|
|
||||||
echo " Install: https://docker.com/products/docker-desktop"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "✅ Docker: $(docker --version 2>/dev/null | head -1)"
|
|
||||||
|
|
||||||
# Check git
|
|
||||||
if ! command -v git &>/dev/null; then
|
|
||||||
echo "❌ Git is required but not installed."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "✅ Git: $(git --version)"
|
|
||||||
|
|
||||||
# Clone or update Shannon
|
|
||||||
if [ -d "$SHANNON_HOME" ] && [ -f "$SHANNON_HOME/shannon" ]; then
|
|
||||||
echo "✅ Shannon found at $SHANNON_HOME"
|
|
||||||
echo " Updating..."
|
|
||||||
cd "$SHANNON_HOME" && git pull --ff-only 2>/dev/null || echo " (already up to date or can't fast-forward)"
|
|
||||||
else
|
|
||||||
echo "📥 Cloning Shannon to $SHANNON_HOME..."
|
|
||||||
git clone https://github.com/KeygraphHQ/shannon.git "$SHANNON_HOME"
|
|
||||||
echo "✅ Shannon cloned successfully"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check API credentials
|
|
||||||
echo ""
|
|
||||||
echo "API Credentials:"
|
|
||||||
if [ -n "${ANTHROPIC_API_KEY:-}" ]; then
|
|
||||||
echo "✅ ANTHROPIC_API_KEY is set"
|
|
||||||
elif [ -n "${ANTHROPIC_AUTH_TOKEN:-}" ] && [ -n "${ANTHROPIC_BASE_URL:-}" ]; then
|
|
||||||
echo "✅ MiniMax mode: ANTHROPIC_AUTH_TOKEN + ANTHROPIC_BASE_URL are set"
|
|
||||||
echo " Base URL: $ANTHROPIC_BASE_URL"
|
|
||||||
echo " Model: ${ANTHROPIC_MODEL:-MiniMax-M2.7}"
|
|
||||||
elif [ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ]; then
|
|
||||||
echo "✅ CLAUDE_CODE_OAUTH_TOKEN is set"
|
|
||||||
elif [ "${CLAUDE_CODE_USE_BEDROCK:-}" = "1" ]; then
|
|
||||||
echo "✅ AWS Bedrock mode enabled"
|
|
||||||
elif [ "${CLAUDE_CODE_USE_VERTEX:-}" = "1" ]; then
|
|
||||||
echo "✅ Google Vertex AI mode enabled"
|
|
||||||
else
|
|
||||||
echo "⚠️ No AI credentials detected. Set one of:"
|
|
||||||
echo " export ANTHROPIC_API_KEY=sk-ant-..."
|
|
||||||
echo " export ANTHROPIC_AUTH_TOKEN=... + export ANTHROPIC_BASE_URL=https://api.minimax.io/anthropic (MiniMax)"
|
|
||||||
echo " export CLAUDE_CODE_OAUTH_TOKEN=..."
|
|
||||||
echo " export CLAUDE_CODE_USE_BEDROCK=1"
|
|
||||||
echo " export CLAUDE_CODE_USE_VERTEX=1"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Recommended: export CLAUDE_CODE_MAX_OUTPUT_TOKENS=64000"
|
|
||||||
echo ""
|
|
||||||
echo "Shannon is ready at: $SHANNON_HOME"
|
|
||||||
echo "Run a pentest: cd $SHANNON_HOME && ./shannon start URL=http://localhost:3000 REPO=myapp"
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# sync.sh - Deploy shannon skill to all host locations
|
|
||||||
# Usage: bash scripts/sync.sh (run from repo root)
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
SRC="$(cd "$(dirname "$0")/.." && pwd)"
|
|
||||||
echo "Source: $SRC"
|
|
||||||
|
|
||||||
TARGETS=(
|
|
||||||
"$HOME/.claude/skills/shannon"
|
|
||||||
"$HOME/.agents/skills/shannon"
|
|
||||||
"$HOME/.codex/skills/shannon"
|
|
||||||
)
|
|
||||||
|
|
||||||
for t in "${TARGETS[@]}"; do
|
|
||||||
echo ""
|
|
||||||
echo "--- Syncing to $t ---"
|
|
||||||
mkdir -p "$t/scripts"
|
|
||||||
|
|
||||||
cp "$SRC/SKILL.md" "$t/"
|
|
||||||
|
|
||||||
# Helper scripts
|
|
||||||
if ls "$SRC/scripts/"*.sh &>/dev/null; then
|
|
||||||
rsync -a "$SRC/scripts/"*.sh "$t/scripts/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo " Deployed to $t"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Sync complete."
|
|
||||||
Reference in New Issue
Block a user