feat: add agent icon assets and refresh-favicon skill (#1499)

Download favicon/icons for all 6 agents into assets/agents/:
- claude.png    — Anthropic GitHub org avatar (4.5K)
- openclaw.png  — openclaw.ai/apple-touch-icon.png (5.8K)
- zeroclaw.png  — zeroclaw-labs GitHub org avatar (11K)
- codex.png     — OpenAI GitHub org avatar (4.0K)
- opencode.svg  — opencode.ai/favicon.svg (612B)
- kilocode.png  — Kilo-Org GitHub org avatar (1.3K)

Update manifest.json icon fields to point to raw.githubusercontent.com
URLs for the local files (stable, CDN-served, versioned in repo).

Add assets/agents/.sources.json tracking each agent's canonical source
URL and extension for use by the refresh-favicon skill.

Add .claude/skills/refresh-favicon/SKILL.md — a skill that re-downloads
all agent icons from their source URLs, detects content types, updates
.sources.json, and syncs manifest.json icon fields.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
L 2026-02-19 23:55:13 -05:00 • committed by GitHub
parent bb56302c67
commit 635d358ca3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 110 additions and 13 deletions

View file

@ -0,0 +1,76 @@
# Refresh Agent Favicons
Re-download all agent icon/favicon files into `assets/agents/` and keep the manifest `icon` fields in sync.
## When to use
Run this when:
- An agent's logo changes (new branding, new org avatar)
- An icon URL breaks (404 or stale redirect)
- A new agent is added to the manifest without a local icon
- You suspect an icon file is corrupt or outdated
## Arguments
- `--agent <id>` — Refresh only the specified agent (e.g. `--agent openclaw`). Omit to refresh all.
- `--dry-run` — Print what would be downloaded without writing files.
## Procedure
### Step 1: Read the manifest
```bash
python3 -c "import json; d=json.load(open('manifest.json')); [print(k, v.get('icon','')) for k,v in d['agents'].items()]"
```
### Step 2: Determine source URLs
For each agent, the canonical icon source URL is tracked in `assets/agents/.sources.json`.
If it doesn't exist, fall back to the current `icon` field in `manifest.json`.
### Step 3: Download each icon
For each agent (or the specified `--agent`):
1. Fetch the source URL with `curl -fsSL -o assets/agents/{agent}.{ext}`
2. Detect the file extension from the `Content-Type` header:
- `image/svg+xml` → `.svg`
- `image/png` → `.png`
- `image/jpeg` → `.jpg`
- `image/x-icon` or `image/vnd.microsoft.icon` → `.ico`
3. If the HTTP response is not 200, print a warning and skip that agent
4. If `--dry-run`, print what would be downloaded without writing
### Step 4: Update assets/.sources.json
Write (or update) `assets/agents/.sources.json` with the mapping of each agent to its source URL and detected extension:
```json
{
"claude": { "url": "https://...", "ext": "png" },
"openclaw": { "url": "https://...", "ext": "png" },
...
}
```
### Step 5: Update manifest.json icon fields
For each refreshed agent, set `icon` in `manifest.json` to the raw GitHub URL:
```
https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/{agent}.{ext}
```
### Step 6: Verify
```bash
ls -lh assets/agents/
python3 -c "import json; d=json.load(open('manifest.json')); [print(k, d['agents'][k].get('icon','MISSING')) for k in d['agents']]"
```
### Step 7: Summary
Print a summary:
- Agents refreshed (with old → new byte sizes)
- Agents skipped (errors or dry-run)
- Any icon URL changes detected

View file

@ -0,0 +1,8 @@
{
"claude": { "url": "https://avatars.githubusercontent.com/u/76263028?s=200&v=4", "ext": "png" },
"openclaw": { "url": "https://openclaw.ai/apple-touch-icon.png", "ext": "png" },
"zeroclaw": { "url": "https://avatars.githubusercontent.com/u/261820148?s=200&v=4", "ext": "png" },
"codex": { "url": "https://avatars.githubusercontent.com/u/14957082?s=200&v=4", "ext": "png" },
"opencode": { "url": "https://opencode.ai/apple-touch-icon.png", "ext": "png" },
"kilocode": { "url": "https://avatars.githubusercontent.com/u/201822503?s=200&v=4", "ext": "png" }
}

BIN
assets/agents/claude.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets/agents/codex.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

BIN
assets/agents/kilocode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/agents/openclaw.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
assets/agents/opencode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
assets/agents/zeroclaw.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -27,8 +27,10 @@
"bypassPermissionsModeAccepted": true
}
},
"icon": "https://avatars.githubusercontent.com/u/76263028?s=200&v=4",
"featured_cloud": ["sprite"]
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/claude.png",
"featured_cloud": [
"sprite"
]
},
"openclaw": {
"name": "OpenClaw",
@ -48,12 +50,14 @@
"default": "openrouter/auto"
}
},
"icon": "https://openclaw.ai/apple-touch-icon.png",
"featured_cloud": ["fly"]
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/openclaw.png",
"featured_cloud": [
"fly"
]
},
"zeroclaw": {
"name": "ZeroClaw",
"description": "Fast, small, fully autonomous AI assistant infrastructure — deploy anywhere, swap anything",
"description": "Fast, small, fully autonomous AI assistant infrastructure \u2014 deploy anywhere, swap anything",
"url": "https://github.com/zeroclaw-labs/zeroclaw",
"install": "curl -LsSf https://raw.githubusercontent.com/zeroclaw-labs/zeroclaw/main/scripts/install.sh | bash -s -- --install-rust --install-system-deps",
"launch": "zeroclaw agent",
@ -62,8 +66,11 @@
"ZEROCLAW_PROVIDER": "openrouter"
},
"notes": "Rust-based agent framework built by Harvard/MIT/Sundai.Club communities. Natively supports OpenRouter via OPENROUTER_API_KEY + ZEROCLAW_PROVIDER=openrouter. Requires compilation from source (~5-10 min).",
"icon": "https://avatars.githubusercontent.com/u/261820148?s=200&v=4",
"featured_cloud": ["hetzner", "fly"]
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/zeroclaw.png",
"featured_cloud": [
"hetzner",
"fly"
]
},
"codex": {
"name": "Codex CLI",
@ -77,8 +84,10 @@
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
},
"notes": "Works with OpenRouter via OPENAI_BASE_URL override pointing to openrouter.ai/api/v1",
"icon": "https://avatars.githubusercontent.com/u/14957082?s=200&v=4",
"featured_cloud": ["fly"]
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/codex.png",
"featured_cloud": [
"fly"
]
},
"opencode": {
"name": "OpenCode",
@ -90,8 +99,10 @@
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
},
"notes": "Natively supports OpenRouter via OPENROUTER_API_KEY env var. Go-based TUI using Bubble Tea.",
"icon": "https://opencode.ai/favicon.svg",
"featured_cloud": ["daytona"]
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/opencode.png",
"featured_cloud": [
"daytona"
]
},
"kilocode": {
"name": "Kilo Code",
@ -105,8 +116,10 @@
"OPENROUTER_API_KEY": "${OPENROUTER_API_KEY}"
},
"notes": "Natively supports OpenRouter as a provider via KILO_PROVIDER_TYPE=openrouter. CLI installable via npm as @kilocode/cli, invocable as 'kilocode' or 'kilo'.",
"icon": "https://avatars.githubusercontent.com/u/201822503?s=200&v=4",
"featured_cloud": ["fly"]
"icon": "https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/assets/agents/kilocode.png",
"featured_cloud": [
"fly"
]
}
},
"clouds": {