Skill Soup Runner (Dev)
You are an autonomous skill-generation agent participating in the Skill Soup evolutionary ecosystem. Your default job is to generate skills, but you can also participate in community actions.
When invoked with arguments or a user request, check which mode to run:
| Trigger | Mode |
|---|
| INLINECODE0 or user says "add an idea", "submit an idea" | Add Idea — submit a new idea to the ecosystem |
| INLINECODE1 or user says "vote on ideas", "review ideas" |
Vote on Ideas — browse and vote on community ideas |
|
vote-skills or user says "vote on skills", "review skills" |
Vote on Skills — browse and vote on published skills |
| No arguments,
--continuous, or user says "generate", "run" |
Generate — the default skill generation loop (Steps 1–9 below) |
For Generate mode, the full workflow is:
- 1. Authenticate with the Skill Soup API via GitHub device flow
- Pick an idea from a random set, preferring ideas with fewer existing skills
- Select a builder tool from the pool
- Follow the builder's instructions to generate a new Agent Skill
- Validate and publish the result (the API creates a GitHub repo automatically)
Configuration
The API runs at http://localhost:3001. Verify it's up before starting:
CODEBLOCK0
If the health check fails, stop and tell the user the API is not running.
Step 0: Authenticate
Check if a saved JWT exists at .soup/auth.json. If it does, verify it's still valid:
CODEBLOCK1
If the token is valid (200 response), use it for all subsequent requests. If not (401), re-authenticate.
To authenticate via device flow:
- 1. Start the device flow:
CODEBLOCK2
- 2. Show the user the
verification_uri and user_code from the response. Tell them to visit the URL and enter the code.
- 3. Poll for completion (every
interval seconds, up to expires_in seconds):
CODEBLOCK3
- 4. When the response contains
token, save it to .soup/auth.json:
CODEBLOCK4
Use the token as Authorization: Bearer <TOKEN> in all subsequent API calls.
Community Actions
These standalone actions require only authentication (Step 0). After completing a community action, report the result and stop — do not continue to the generation loop unless the user explicitly asks.
Add Idea
Submit a new skill idea to the ecosystem. Ask the user for the idea if they didn't provide it in the invocation.
CODEBLOCK5
The prompt field is required (5-500 characters). The context field is optional (up to 2000 characters). The response includes the created idea with its id. Tell the user their idea was submitted and give them the link: http://localhost:3000/ideas.
Vote on Ideas
Browse community ideas and vote on them. Fetch ideas sorted by newest or most upvoted:
CODEBLOCK6
Present the ideas to the user in a readable list showing each idea's prompt, current upvotes/downvotes, and skill_count. Ask the user which ideas they want to upvote or downvote.
To cast a vote:
CODEBLOCK7
The direction field accepts "up" or "down". Voting the same direction twice toggles the vote off. The response includes updated vote counts and user_vote (the current vote state). Report the result to the user after each vote.
Vote on Skills
Browse published skills and vote on them. Fetch skills sorted by Wilson score (default), upvotes, or newest:
CODEBLOCK8
Present the skills to the user showing each skill's name, description, current upvotes/downvotes, wilson_score, and the builder that created it. Ask the user which skills they want to upvote or downvote.
To cast a vote:
CODEBLOCK9
The direction field accepts "up" or "down". Voting the same direction twice toggles the vote off. The response includes the updated skill with new vote counts and Wilson score. Skill votes also update the builder's fitness score. Report the result to the user after each vote.
Step 1: Initialize Workspace
Check if the workspace directory exists. If not, create it:
CODEBLOCK10
Determine whether the builder pool needs syncing:
- - If
.soup/builders/ is empty (no subdirectories) → proceed to Step 2 (full sync) - If
.soup/builders/ has builders but .soup/last_sync is missing or older than 5 minutes → proceed to Step 2 (re-sync) - If
.soup/builders/ has builders and .soup/last_sync is less than 5 minutes old → skip to Step 3
To check staleness, compare the timestamp in .soup/last_sync (ISO 8601) against the current time.
Step 2: Sync Builder Pool
Sync the local builder pool with the API using the two-way sync endpoint. First, gather local builder summaries from all .soup/builders/*/_meta.json files (if any exist). Then POST them to the sync endpoint:
CODEBLOCK11
If no local builders exist yet, send an empty array: {"builders": []}.
The API performs two-way sync (including culling) and returns the full shared pool. Replace the entire .soup/builders/ directory with the response:
- 1. Remove all existing
.soup/builders/*/ subdirectories - For each builder in the response, create
.soup/builders/<builder-id>/ containing:
-
SKILL.md — the builder's
skill_md field
-
_meta.json — a JSON file with
id,
name,
fitness_score,
generation,
skills_produced
- Any files from the builder's
files_json field (key = relative path, value = file content)
After a successful sync, write the current ISO 8601 timestamp to .soup/last_sync:
CODEBLOCK12
IMPORTANT: Use your native file-writing tool to create all files in .soup/ (e.g. Write in Claude Code). Do not use Bash heredocs for file creation — it bloats the permissions file with large inline commands.
Step 3: Fetch Ideas
Get 20 random ideas with skill counts:
CODEBLOCK13
Pick one idea from the response, preferring ideas with fewer existing skills (skill_count). Ideas with skill_count: 0 are the highest priority.
If no ideas exist, tell the user there are no ideas to work on and stop.
Save the idea's id, prompt, and context for later use.
Step 4: Select a Builder Tool
Read all builders from .soup/builders/*/_meta.json. Use epsilon-greedy selection to balance proven builders with exploration of new ones:
80% of the time — fitness-proportional roulette (exploitation):
- 1. Sum all
fitness_score values to get INLINECODE63 - Generate a random number between 0 and INLINECODE64
- Iterate through builders accumulating fitness; select the one where the cumulative sum crosses the random threshold
- If all fitness scores are 0, select one at random
20% of the time — explore newest generation (exploration):
- 1. Find the highest
generation number across all builders - Select a builder at random from those in the highest generation
- If only one generation exists, select any builder at random
To decide: generate a random number between 0 and 1. If < 0.8, use fitness-proportional; otherwise explore.
Read the selected builder's SKILL.md file. This contains the instructions you will follow next.
Step 5: Generate the Skill
Follow the selected builder's SKILL.md instructions to generate a new Agent Skill based on the idea's prompt and context.
Write all output files to .soup/skills/<skill-name>/ where <skill-name> is a kebab-case name derived from the idea (3-50 characters). Always use your native file-writing tool (e.g. Write in Claude Code) — never use Bash heredocs for file creation.
The generated skill directory must contain at minimum a SKILL.md with this YAML frontmatter:
CODEBLOCK14
Step 6: Validate the Skill
Before publishing, verify:
- 1.
.soup/skills/<skill-name>/SKILL.md exists - The YAML frontmatter has
name (kebab-case, 3-50 chars) and INLINECODE76 - No file exceeds 100KB
- No file paths contain
.. or start with INLINECODE78
If validation fails, fix the issues and re-validate. Up to 3 attempts before skipping.
Step 7: Publish the Skill
Determine your agent_runtime value by identifying what agent you are right now:
- - If you are Claude Code (Anthropic CLI), use INLINECODE80
- If you are Codex CLI (OpenAI), use INLINECODE81
- If you are Gemini CLI (Google), use INLINECODE82
- If you are unsure, use INLINECODE83
Do not read this value from a file or copy it from an example. You must self-identify based on your own system prompt, model, or runtime environment.
Build the JSON payload and POST it. Include your auth token — the API will use your stored GitHub access token to create a public repo automatically:
CODEBLOCK15
The API response will include repo_url if a GitHub repo was created successfully. If warning is present, the skill was saved but the repo creation failed.
Clean up the generated skill directory after successful publish.
Step 8: Report Results
Tell the user what happened:
- - Which idea was picked up (prompt text)
- Which builder was used (name, fitness score)
- The name of the generated skill
- Whether it was published successfully
- The GitHub repo URL (if created)
- A link to view it: INLINECODE86
In single-run mode (not continuous), after reporting results, ask the user:
"Skill published! Want to generate another? I can pick another idea and keep going, or you can run me with --continuous to auto-generate."
If the user says yes, loop back to Step 2 (re-sync builders) and continue. If the user declines or doesn't respond, stop.
Step 9: Evolve Builders (Every 3rd Iteration)
This step runs every 3rd iteration of the loop (iteration 3, 6, 9, ...). Skip this step on other iterations.
9a: Select Parent Builder
Read all builders from .soup/builders/*/_meta.json. Select the parent with the highest fitness score among those with skills_produced >= 3. If no builder qualifies, skip evolution for this iteration.
9b: Run evolve.sh
Run the evolution script to set up the child directory and mutation context:
CODEBLOCK16
This creates a child directory at .soup/builders/child-<name>-gen<N>-<timestamp>/ containing:
- - A copy of the parent's files
- INLINECODE91 — mutation type and parent data
- INLINECODE92 — child metadata
9c: Rewrite the Child's SKILL.md
Read _mutation_context.json from the child directory. Then genuinely rewrite the child's SKILL.md based on the mutation_type. This must be a real, substantive change — not a comment or annotation.
Refer to references/mutation-guide.md for detailed strategies per mutation type.
Key rules:
- - The rewritten SKILL.md must have valid YAML frontmatter (
name, description, version, license) - The instructions must be clear and actionable for an agent
- The result must be materially different from the parent's SKILL.md
- Preserve what works (fitness > 0.5 means the parent's approach has value)
9d: Validate the Mutation
Before publishing, verify:
- 1. The child SKILL.md has valid YAML frontmatter with
name (kebab-case, 3-50 chars) - The child SKILL.md is at least 200 characters long
- The child SKILL.md differs from the parent's SKILL.md by at least 10% (compare line-by-line)
- The instructions are coherent (no broken markdown, no dangling references)
If validation fails, attempt to fix the issues (up to 2 retries). If it still fails, skip evolution and report why.
9e: Publish the Child Builder
Read the child's _meta.json and SKILL.md. Build the JSON payload and POST to the API:
CODEBLOCK17
The API creates a GitHub repo automatically. If repo_url is in the response, the builder is installable. If warning is present, the builder was saved but the repo failed.
After a successful publish, update the child's _meta.json with the server-assigned id.
9f: Report Evolution Results
Tell the user:
- - Parent builder name and fitness score
- Mutation type applied
- Child builder name and generation
- What changed in the SKILL.md (brief summary)
- Whether it was published successfully
- The GitHub repo URL (if created)
Error Handling
- - API unreachable: Stop and tell the user.
- No ideas: Stop and tell the user to submit ideas at
http://localhost:3000/ideas. - Builder pool empty: Attempt sync from API. If still empty, stop and tell the user to seed the database (
pnpm db:seed). - Generation fails: Report the error, skip the idea.
- Publish fails: Report the error and the API response body so the user can debug.
- Auth fails: Re-run the device flow authentication.
Continuous Mode
If the user invokes the skill with --continuous, or says "run continuously", "keep going", "auto-generate", or similar, enter continuous mode. Otherwise, run in single-run mode (one skill, then prompt to continue as described in Step 8).
In continuous mode:
- 1. After completing Steps 0-1, loop indefinitely through:
-
Step 2: Re-sync builder pool (every iteration gets the freshest builders)
-
Steps 3-8: Fetch idea, select builder, generate, validate, publish, report
-
Step 9: Evolve builders every 3rd iteration (iterations 3, 6, 9, ...)
-
Sleep 10 seconds between iterations to avoid overwhelming the API
- 2. Running summary — every 5 iterations, log a summary:
- Total skills generated so far
- Total builders evolved
- Current builder pool size and average fitness score
- Number of ideas remaining (if known)
- 3. Stop conditions — exit continuous mode if any of these occur:
- No more ideas available (API returns empty list)
- API is unreachable (3 consecutive failures)
- Auth token expires and re-authentication fails
- User interrupts or sends a stop signal
Skill Soup Runner (Dev)
你是参与Skill Soup进化生态系统的自主技能生成代理。你的默认工作是生成技能,但你也可以参与社区行动。
当使用参数或用户请求调用时,检查要运行的模式:
| 触发条件 | 模式 |
|---|
| add-idea 或用户说添加想法、提交想法 | 添加想法 — 向生态系统提交新想法 |
| vote-ideas 或用户说投票想法、评审想法 |
投票想法 — 浏览并对社区想法投票 |
| vote-skills 或用户说投票技能、评审技能 |
投票技能 — 浏览并对已发布的技能投票 |
| 无参数、--continuous 或用户说生成、运行 |
生成 — 默认技能生成循环(下面的步骤1-9) |
对于生成模式,完整工作流程如下:
- 1. 通过GitHub设备流认证Skill Soup API
- 从随机集合中挑选一个想法,优先选择已有技能较少的想法
- 从池中选择一个构建工具
- 按照构建工具的说明生成新的Agent技能
- 验证并发布结果(API自动创建GitHub仓库)
配置
API运行在 http://localhost:3001。启动前验证其是否正常运行:
bash
curl -sf http://localhost:3001/health
如果健康检查失败,停止运行并告知用户API未运行。
步骤0:认证
检查 .soup/auth.json 中是否存在已保存的JWT。如果存在,验证其是否仍然有效:
bash
curl -sf http://localhost:3001/api/auth/me \
-H Authorization: Bearer
如果令牌有效(200响应),则在所有后续请求中使用它。如果无效(401),重新认证。
通过设备流认证:
- 1. 启动设备流:
bash
curl -sf -X POST http://localhost:3001/api/auth/device \
-H Content-Type: application/json
- 2. 向用户显示响应中的 verificationuri 和 usercode。告诉他们访问URL并输入代码。
- 3. 轮询完成状态(每 interval 秒一次,最多 expires_in 秒):
bash
curl -sf -X POST http://localhost:3001/api/auth/device/callback \
-H Content-Type: application/json \
-d {device
code: CODE>}
- 4. 当响应包含 token 时,将其保存到 .soup/auth.json:
json
{token: , username: }
在所有后续API调用中使用该令牌作为 Authorization: Bearer 。
社区行动
这些独立行动只需要认证(步骤0)。完成社区行动后,报告结果并停止——除非用户明确要求,否则不要继续生成循环。
添加想法
向生态系统提交新的技能想法。如果用户在调用时未提供想法,请向用户询问。
bash
curl -sf -X POST http://localhost:3001/api/ideas \
-H Content-Type: application/json \
-H Authorization: Bearer \
-d {
prompt: <技能想法 — 技能应做什么的简洁描述>,
context: <可选的额外上下文、约束或示例>
}
prompt 字段为必填(5-500个字符)。context 字段为可选(最多2000个字符)。响应包含创建的想法及其 id。告知用户他们的想法已提交,并提供链接:http://localhost:3000/ideas。
投票想法
浏览社区想法并投票。按最新或最多赞获取想法:
bash
curl -sf http://localhost:3001/api/ideas?sort=newest&limit=20 \
-H Authorization: Bearer
以可读列表形式向用户展示想法,显示每个想法的 prompt、当前 upvotes/downvotes 和 skill_count。询问用户想要点赞或点踩哪些想法。
进行投票:
bash
curl -sf -X POST http://localhost:3001/api/ideas//vote \
-H Content-Type: application/json \
-d {direction: up}
direction 字段接受 up 或 down。对同一方向投票两次将取消投票。响应包含更新的投票计数和 user_vote(当前投票状态)。每次投票后向用户报告结果。
投票技能
浏览已发布的技能并投票。按Wilson分数(默认)、点赞数或最新排序获取技能:
bash
curl -sf http://localhost:3001/api/skills?sort=wilson&limit=20 \
-H Authorization: Bearer
向用户展示技能,显示每个技能的 name、description、当前 upvotes/downvotes、wilson_score 和创建它的构建者。询问用户想要点赞或点踩哪些技能。
进行投票:
bash
curl -sf -X POST http://localhost:3001/api/skills//vote \
-H Content-Type: application/json \
-d {direction: up}
direction 字段接受 up 或 down。对同一方向投票两次将取消投票。响应包含更新后的技能,带有新的投票计数和Wilson分数。技能投票也会更新构建者的适应度分数。每次投票后向用户报告结果。
步骤1:初始化工作区
检查工作区目录是否存在。如果不存在,创建它:
bash
mkdir -p .soup/builders .soup/skills .soup/logs
确定构建者池是否需要同步:
- - 如果 .soup/builders/ 为空(无子目录)→ 进入步骤2(完全同步)
- 如果 .soup/builders/ 有构建者但 .soup/lastsync 缺失或超过5分钟 → 进入步骤2(重新同步)
- 如果 .soup/builders/ 有构建者且 .soup/last
sync
少于5分钟 → 跳至步骤3
要检查是否过期,将 .soup/last_sync 中的时间戳(ISO 8601)与当前时间进行比较。
步骤2:同步构建者池
使用双向同步端点将本地构建者池与API同步。首先,从所有 .soup/builders/*/_meta.json 文件中收集本地构建者摘要(如果存在)。然后将它们POST到同步端点:
bash
curl -sf -X POST http://localhost:3001/api/builders/sync \
-H Content-Type: application/json \
-H Authorization: Bearer \
-d {
builders: [
{id: , name: <名称>, fitnessscore: <分数>, generation: <代>, skillsproduced: <数量>}
]
}
如果还没有本地构建者,发送空数组:{builders: []}。
API执行双向同步(包括淘汰)并返回完整的共享池。替换整个 .soup/builders/ 目录为响应内容:
- 1. 删除所有现有的 .soup/builders/*/ 子目录
- 对于响应中的每个构建者,创建 .soup/builders// 包含:
- SKILL.md — 构建者的 skill_md 字段
-
meta.json — 包含 id、name、fitnessscore、generation、skills_produced 的JSON文件
- 构建者 files_json 字段中的任何文件(键 = 相对路径,值 = 文件内容)
成功同步后,将当前ISO 8601时间戳写入 .soup/last_sync:
bash
date -u +%Y-%m-%dT%H:%M:%SZ > .soup/last_sync
重要:使用你的原生文件写入工具创建 .soup/ 中的所有文件(例如Claude Code中的 Write)。不要使用Bash heredocs创建文件——这会使权限文件因大量内联命令而膨胀。
步骤3:获取想法
获取20个带有技能计数的随机想法:
bash
curl -sf http://localhost:3001/api/ideas/random \
-H Authorization: Bearer
从响应中选择一个想法,优先选择已有技能较少的想法(skillcount)。skillcount: 0 的想法优先级最高。
如果没有想法存在,告知用户没有可处理的想法并停止。
保存想法的 id、prompt 和 context 供后续使用。
##