| name | feature |
| description | Build, enhance, or revive GitHub repos - ship one feature PR per watched repo (watched), make the best single enhancement on one external repo (external), or revive the top dormant repo (dormant). |
| metadata | {"title":"Feature","category":"dev","var":"","mode":"write","commits":true,"permissions":["contents:write","pull-requests:write"],"requires":["GH_GLOBAL?"],"tags":["dev","build","growth"]} |
When the run prompt supplies a Workflow correlation ID, include the exact marker <!-- aeon-dispatch:<ID> --> in every PR body you create. This is a machine-checked chain receipt: do not alter, omit, or place it only in the final response.
${var} — Selector target[:arg] [--fix-issues], target ∈ {watched, external, dormant}. Empty or watched = build a feature on every watched repo (one PR each); external:<owner/repo> = one best enhancement on that external repo; dormant = revive the highest-scoring dormant repo. A leading build:<owner/repo | issue-url | free-text instruction> — the shape the Telegram "ship which opportunity?" force-reply sends via repo-scanner's offer — is intercepted first and routed into the external branch on that target/instruction. --fix-issues biases the chosen branch toward fixing an open GitHub issue. Full grammar below.
This skill merges three repo-work modes behind one selector so no capability is lost:
| Branch | Selector | Per run | Repo source | Use it for |
|---|
| watched (§A) | empty / watched | Iterates every watched repo, ships one PR per repo | memory/watched-repos.md | Weekly broad sweep — keep every repo moving |
| external (§B) | external[:owner/repo[#N]] | Single repo per run | memory/topics/repos.md catalog (or ${var} override) | Targeted enhancement / issue fix on one repo |
| dormant (§C) | dormant[:owner/repo] | Single dormant repo per run | memory/watched-repos.md scored by dormancy | Reactivate a stale high-★ repo with one visible fix |
Today is ${today}. Read memory/MEMORY.md and the last 7 days of memory/logs/ before starting — and before notifying, drop anything already reported in the last ~3 days of logs.
Selector
Telegram force-reply interception — check this FIRST, before parsing anything else. If ${var} starts with build:, it is the "ship which opportunity?" force-reply that repo-scanner offers (routed here as feature with var="build:<the operator's reply>"). Strip the prefix with ${var#build:} and treat the remainder as an external build target/instruction — route it straight into the external branch (§B), reusing that branch's existing logic (do not run the watched or dormant branches for a build: value, and do not duplicate §B). Normalize the remainder into a §B target:
owner/repo → run §B as if external:owner/repo (B2 "clone that repo").
- an issue URL (
https://github.com/owner/repo/issues/N) or owner/repo#N → run §B as if external:owner/repo#N (B2 "fetch that issue").
- free text like
owner/repo: add retry to the client → run §B on owner/repo, using the trailing text as the explicit enhancement to build (see §B4's "requested enhancement" note — skip the auto-pick).
- anything else with no parseable repo → run §B passing the whole remainder as the enhancement instruction; §B B2/B4 already reason about selecting and scoping a target.
The remainder may itself contain colons — keep them. This is a complete run once §B ships its PR (or cleanly skips); do not then fall through to the normal selector.
Parse ${var} into a target and optional flags:
- Empty or
watched → watched branch (§A): sweep every watched repo, ship one feature PR each.
watched:<feature-spec> → watched branch, but build <feature-spec> on the FIRST watched repo only.
external → external branch (§B): auto-pick one catalog/watched repo and make the best single enhancement.
external:<owner/repo> → external branch on that specific repo.
external:<owner/repo>#N → external branch on that specific issue.
dormant → dormant branch (§C): auto-select the highest-scoring dormant repo and revive it.
dormant:<owner/repo> → dormant branch on that specific repo (skip selection).
- Trailing
--fix-issues (with any target) → bias the branch toward fixing an OPEN GitHub issue rather than a proactive change (see each branch's "with --fix-issues" note).
Example values: `` (empty → watched sweep), watched, watched:add a dark-mode toggle, external, external:acme/api, external:acme/api#42, dormant, dormant:acme/legacy-lib, external --fix-issues, dormant --fix-issues.
Dispatch to exactly one branch. Do not run branches you weren't selected into.
Voice
If soul/SOUL.md and soul/STYLE.md are populated, read both and match the operator's voice in every written output — per-repo notifications (§A), and the revival tweet draft (§C step 5). If they are empty templates or absent, use a clear, direct, neutral tone — short sentences, no hashtags, no emojis, no corporate launch-language.
Config
All branches read operator-controlled files under memory/ (runtime config — reference the paths exactly, never edit them here):
-
memory/watched-repos.md — candidate repo pool. One owner/repo per line (markdown bullets like - owner/repo are fine; comment lines starting with # are ignored). Used by watched and dormant; also the OWNER fallback for external. If missing or empty on the watched branch, log FEATURE_NO_CONFIG and exit cleanly (no notification — empty config is not an error). On dormant, log REPO_REVIVE_NO_CONFIG and exit cleanly.
-
memory/topics/repos.md — full repo catalog with descriptions, stack, and opportunities. Preferred repo source for the external branch; if absent, fall back to memory/watched-repos.md.
-
memory/topics/stale-models.md — stale AI model names and their current replacements. Used only by the dormant branch's stale-model audit. Example shape:
# Stale Models
## Considered stale (flag if a watched repo's README/config still references these)
- gpt-3.5
- claude-2
- claude-instant
- gpt-4 (without version suffix)
- text-davinci
## Current models (suggest these as replacements)
- claude-sonnet-5
- claude-opus-4-8
- gpt-5
- gemini-3
- grok-4.6
If the file is missing, the dormant branch skips the "stale model" fix category entirely (other categories still apply) and logs REPO_REVIVE_NO_MODEL_CONFIG: skipping model audit.
§A — Watched branch (build a feature on every watched repo)
Runs when ${var} is empty or watched[:<feature-spec>]. Ships one PR per watched repo in a single run.
A1. Load the target list
Parse memory/watched-repos.md into a list of owner/repo entries. If the file is missing or empty, log FEATURE_NO_CONFIG and exit cleanly (no notification).
If ${var} is watched:<feature-spec>, restrict the list to the first repo only and use <feature-spec> as the feature spec for it.
A2. For each repo in the list, run steps A3–A10 independently
A failure on one repo must NOT stop the others — catch the failure, log it, continue. Use a fresh working directory per repo (e.g. /tmp/feature-build-${repo-name}).
A3. Pick what to build for this repo
In this priority order:
a. If ${var} is watched:<feature-spec> AND this is the first repo, build that.
b. Check yesterday's repo-actions output in output/articles/repo-actions-*.md (most recent file) for ideas scoped to THIS repo. Pick the highest-impact idea that's autonomously implementable.
c. Check open GitHub issues labelled ai-build on this repo:
gh issue list -R owner/repo --label ai-build --state open
d. Check memory/MEMORY.md for planned features or next priorities tied to this repo.
e. If none of the above yields anything for this repo, log FEATURE_SKIP: <repo> — no suitable feature found and skip to the next repo. Do NOT send a notification for skipped repos.
With --fix-issues: promote step (c) — open ai-build issues — to the top priority ahead of (a)/(b), and only build from an open issue. If this repo has no open ai-build issue, log FEATURE_SKIP: <repo> — no open ai-build issue and skip it.
A4. Clone the repo
Into a per-repo temp directory:
gh repo clone owner/repo /tmp/feature-build-${repo-name}
cd /tmp/feature-build-${repo-name}
A5. Read the codebase
Understand the project structure, README, package.json/config files, recent commits, and the area you'll modify:
git log --oneline -20
Read the area you'll modify in full before changing anything.
A6. Implement the feature
Write clean, complete code. No TODOs or placeholders. Match the existing code style exactly — indentation, naming, patterns. Don't introduce new dependencies unless absolutely necessary. Don't refactor unrelated code — stay focused on one improvement.
Content-filter-sensitive documents. A few standard governance files are built almost entirely from sensitive-term-heavy boilerplate — CODE_OF_CONDUCT.md, abuse/moderation policies, harassment-reporting docs (terms like harassment, sexualized language, violence, abuse). Free-generating that body can trip the model's output content-filter, which aborts the entire run with API Error: Output blocked by content filtering policy (exit 1) even when the work is otherwise done. For these files do NOT free-generate the body:
- Fetch the canonical upstream text straight to disk with
curl so the body never passes through model output — curl -fsSL https://www.contributor-covenant.org/version/2/1/code_of_conduct/code_of_conduct.md -o CODE_OF_CONDUCT.md. Don't route it through WebFetch: that pulls the text into context, and you would still have to re-emit the whole body in a Write call — the filter scores generated tokens, so transcribing it can trip the abort just like free-generating it. curl -o writes the file without the model ever emitting the body.
- Then customize only the enforcement-contact line with a single targeted
Edit (that one line is not sensitive); pull the contact convention from the repo's existing SECURITY.md/CONTRIBUTING.md.
- Keep your final
## Summary and every ./notify message descriptive — name the file, say it's the Contributor Covenant, and link the PR. Never paste the document body into the result text; the verbose final output is the most likely filter trigger.
A7. Branch and push
git checkout -b feat/<short-feature-name>
git add -A
git commit -m "feat: <description of what was built>"
git push -u origin feat/<short-feature-name>
A8. Open a PR
gh pr create -R owner/repo \
--title "feat: <short description>" \
--body "## What
<Description of the feature>
## Why
<What triggered this — repo-actions idea, issue, or gap identified>
## Changes
- file1: what changed
- file2: what changed
${AEON_DISPATCH_ID:+<!-- aeon-dispatch:$AEON_DISPATCH_ID -->}
---
*Built autonomously by Aeon*"
A9. Update memory
Log what was built (per repo) to memory/logs/${today}.md under the consolidated ### feature heading (see Log below). Include the repo name in every log line so per-repo history stays distinct.
A10. Notify — one per successfully built feature (gated)
For each repo with a shipped PR, send a separate ./notify so the operator gets a detailed per-repo message. The notification should be rich enough that a reader understands exactly what was built, why it matters, and how it works WITHOUT clicking the PR link. Skipped/failed repos send no notification.
Do NOT compress into 1–2 lines. Every section below is REQUIRED.
*Feature Built — ${today} — owner/repo*
<Feature name>
<2–3 sentence description of what the feature does in plain language. Explain it like you're telling a non-technical reader in the community what just got added to the project.>
Why this matters:
<2–3 sentences on why this is relevant to the project RIGHT NOW. What problem did users/developers have before? What triggered this — a repo-actions idea, a GitHub issue, a gap in the codebase? How does it move the project forward?>
What was built:
- <file/component>: <what was added/modified — be specific about the functionality, not just "added endpoint">
- <file/component>: <same level of detail>
- <file/component (if applicable)>: ...
How it works:
<3–4 sentences on the technical implementation. Approach taken and why. Libraries/APIs used. How it integrates with existing code. Any interesting design decisions.>
What's next:
<1–2 sentences on follow-up work or how this connects to the broader roadmap.>
PR: <url>
BAD (too short — do NOT do this):
"Feature Built: Data Export. Users can download results as JSON/CSV. PR: url"
GOOD level of detail:
Per-section answers like the template above. A reader who never clicks the PR should still come away knowing what changed and why.
A11. Final wrap-up
After iterating every repo, end with a ## Summary listing each watched repo and its outcome: PR url, skipped, or failed. If every repo was skipped, do NOT send a notification at all — just log the per-repo skip lines.
§B — External branch (best single enhancement on one repo)
Runs when ${var} starts with external. Ships one enhancement PR to one repo per run. Needs cross-repo access — GH_GLOBAL must be present.
B1. Read context
Read memory/MEMORY.md for current priorities.
B2. Pick a target
-
If ${var} is external:<owner/repo>#N — fetch that issue and work on it.
-
If ${var} is external:<owner/repo> — clone that repo, skip to step B3.
-
If ${var} is external (no arg) — find a repo to improve:
- Read
memory/topics/repos.md for the full repo catalog with descriptions, stack, and opportunities.
- If it doesn't exist, fall back to reading
memory/watched-repos.md for the OWNER, then:
gh repo list ${OWNER} --limit 30 --json name,pushedAt,description,primaryLanguage \
--jq 'sort_by(.pushedAt) | reverse | .[:15]'
- Also check
memory/watched-repos.md if it exists.
Pick a repo that:
- Is listed as active or maintained in the catalog
- Has identified opportunities (TODOs, missing tests, open issues, feature gaps)
- Aligns with topics tracked in MEMORY.md
- Hasn't been enhanced by this skill recently (check last 7 days of logs)
B3. Clone and understand the repo
REPO="owner/repo"
WORK_DIR="/tmp/external-work"
rm -rf "$WORK_DIR"
gh repo clone "$REPO" "$WORK_DIR" -- --depth 50
cd "$WORK_DIR"
Before doing anything, deeply understand the codebase:
- Read README.md, CLAUDE.md, CONTRIBUTING.md if they exist
- Check the project structure, language, framework
- Read
package.json / Cargo.toml / pyproject.toml / go.mod etc.
- Read recent commits:
git log --oneline -20
- Check open issues:
gh issue list --repo "$REPO" --state open --limit 10
- Check open PRs:
gh pr list --repo "$REPO" --state open --limit 5
- Understand the test setup if tests exist
B4. Decide what to do