Skip to main content
ClaudeWave
Skill510 repo starsupdated today

ecosystem-pulse

ecosystem-pulse performs a weekly Monday scan of projects listed in ECOSYSTEM.md, matching each to a GitHub repository and reporting on stars, forks, last-commit recency, and any releases published in the prior seven days. Use this skill to maintain a current heartbeat of the ecosystem's active projects, surfacing which ones shipped updates or went quiet, without modifying the curated list itself.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/aaronjmars/aeon /tmp/ecosystem-pulse && cp -r /tmp/ecosystem-pulse/skills/ecosystem-pulse ~/.claude/skills/ecosystem-pulse
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

> **${var}** — Optional. `dry-run` skips notify (state still updates and article still writes). Empty = normal run.

Today is ${today}. `ECOSYSTEM.md` lists the projects, agents, and products building on top of Aeon (merged in #220). Today there is no skill that asks the obvious follow-up question: **are those projects actually shipping?** `fork-cohort` buckets Aeon *forks* by activation stage; `contributor-spotlight` recognises who pushes code to Aeon *itself*; `competitor-radar` watches *new* entrants on Product Hunt / HN. None of them watch the projects already in `ECOSYSTEM.md`. This skill closes that gap: a weekly Monday scan that reads `ECOSYSTEM.md`, matches each project to a GitHub repo where it can, and reports stars / forks / last-commit recency plus any new releases in the 7-day window.

Read `memory/MEMORY.md` for context.
Read the last 8 days of `memory/logs/` for prior-run context.
Read `soul/SOUL.md` + `soul/STYLE.md` if populated to match voice in the notification and article.

## Why this exists

`ECOSYSTEM.md` is a curated list of products and agents built with Aeon — 40 projects at merge time (#220). A static list answers "who claims to build on Aeon?" but not "which of them are alive this week?" Operators (and the wider community reading the ecosystem page) have no signal on whether a listed project shipped a release, went quiet, or just woke back up. Without a recurring pulse, a project can go cold for months and the list still presents it as a peer.

This skill turns the static list into a weekly heartbeat. It is **read-only** against the GitHub API and the local `ECOSYSTEM.md` — it never edits the ecosystem list itself (curation stays a human PR decision per the "Add your project" rules in that file). One Monday digest, gated on signal, sitting alongside the rest of the Monday-morning intelligence stack.

## Inputs

| Source | Purpose | Auth |
|--------|---------|------|
| `ECOSYSTEM.md` (repo root) | Project list — name + X handle, parsed from the markdown table | Local file |
| `memory/topics/ecosystem-pulse-map.json` | Operator-maintained name → GitHub repo mapping (and explicit X-only markers) | Local file (optional) |
| `gh api repos/{owner}/{repo}` | Stars, forks, `pushed_at` for a matched repo | `GH_TOKEN` (gh CLI handles auth) |
| `gh api repos/{owner}/{repo}/releases?per_page=5` | Recent releases — surface any published in the last 7 days | `GH_TOKEN` |
| `gh api -X GET search/repositories -f q=...` | Best-effort repo discovery for unmapped projects | `GH_TOKEN` |
| `memory/topics/ecosystem-pulse-state.json` | Prior-week per-project snapshot for week-over-week (WoW) deltas | Local file |

No new secrets. GitHub access uses the `gh` CLI (`GH_TOKEN`), which handles auth internally — see Sandbox note. The X handles in `ECOSYSTEM.md` are used only as display labels and as dedup keys; this skill does **not** call any X/Twitter API.

Writes:
- `memory/topics/ecosystem-pulse-state.json` — per-project snapshot keyed by project name
- `memory/topics/ecosystem-pulse-map.json` — created from an empty template on first run if absent (never auto-populated with guessed repos)
- `articles/ecosystem-pulse-${today}.md` — digest article on non-QUIET runs
- `memory/logs/${today}.md` — one log block per run, even on QUIET
- Notification via `./notify` — only when signal warrants (see step 7)

## Activity buckets

Every project that resolves to a GitHub repo is bucketed by `pushed_at` recency relative to `${today}`:

| Bucket | Heuristic | Meaning |
|--------|-----------|---------|
| `ACTIVE` | last push ≤ 7 days ago | Shipping this week |
| `RECENT` | last push ≤ 30 days ago | Alive, slower cadence |
| `COLD` | last push > 30 days ago | Gone quiet |
| `XONLY` | no GitHub repo matched | Tracked by X handle only — not a zero, an explicit "no repo" |
| `UNRESOLVED` | repo declared in map/search but the API lookup failed this run | Transient — excluded from counts, surfaced in source health |

`XONLY` is deliberately distinct from `COLD`: a project with no public GitHub repo is not inactive, it's just not measurable here. Counting it as zero-activity would slander projects that ship entirely off-GitHub.

## Mapping file schema

`memory/topics/ecosystem-pulse-map.json` is **operator-maintained** — the skill never writes guessed repos into it. It maps an `ECOSYSTEM.md` project name to either a GitHub repo or an explicit X-only marker:

```json
{
  "_comment": "Operator-maintained. Maps ECOSYSTEM.md project names to GitHub repos. Set repo to null for projects that are intentionally X-handle-only.",
  "projects": {
    "MiroShark": { "repo": "aaronjmars/MiroShark" },
    "GitBounty": { "repo": "gitlawbounty/gitbounty" },
    "Bankr": { "repo": null, "note": "product, no public repo" }
  }
}
```

Resolution order per project (first hit wins):
1. **Explicit map entry** with a non-null `repo` → use it. This is the trusted path.
2. **Explicit map entry** with `repo: null` → classify `XONLY`, do not search.
3. **No map entry** → best-effort GitHub search (step 4). A search hit is used for *this run only* and is **never** written back to the map — search results are noisy and a wrong auto-match would silently misreport a project. The article flags search-derived matches as `(auto-matched, unverified)` so the operator can promote good ones into the map by hand.

## State schema

`memory/topics/ecosystem-pulse-state.json`:

```json
{
  "last_run": "2026-05-18",
  "last_status": "ECOSYSTEM_PULSE_OK",
  "projects": {
    "MiroShark": {
      "repo": "aaronjmars/MiroShark",
      "bucket": "ACTIVE",
      "stars": 312,
      "forks": 21,
      "pushed_at": "2026-05-17T09:12:44Z",
      "latest_release": "v0.4.0",
      "snapshot_at": "2026-05-18"
    }
  }
}
```

Invariants:
- Keyed by `ECOSYSTEM.md` project name (the stable identity here — repos can be renamed, the curated name doesn't churn).
- A project that drops out of `ECOSYSTEM.md` is pruned from state on the next run (state mirrors the