diff --git a/.gitignore b/.gitignore index 82ca0e9..3ecb537 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ htmlcov/ # build artifact from scripts/build-skill.sh /dist/ + +# Internal planning docs (ce:plan output) — keep local, don't publish +docs/plans/ diff --git a/docs/plans/2026-04-14-001-fix-skill-upload-200-file-limit-plan.md b/docs/plans/2026-04-14-001-fix-skill-upload-200-file-limit-plan.md deleted file mode 100644 index c55cd24..0000000 --- a/docs/plans/2026-04-14-001-fix-skill-upload-200-file-limit-plan.md +++ /dev/null @@ -1,445 +0,0 @@ ---- -title: Fix skill upload 200-file limit + packaging hygiene (public repo) -type: fix -status: completed -date: 2026-04-14 -deepened: 2026-04-14 ---- - -# Fix skill upload 200-file limit + packaging hygiene (public repo) - -## Overview - -claude.ai's "Upload skill" UI rejects zips with more than 200 files. Zipping the public `mvanhorn/last30days-skill` repo produces 406 files, so the upload fails outright (evidence: Trevin's 2026-04-14 report). Root cause is an accidentally committed npm package under `vendor/` (215 files of dead weight from PR #48) plus the absence of a user-facing packaging path that matches Anthropic's canonical `.skill` format. - -Goal: let any user produce a compliant `last30days.skill` file in one command, matching Anthropic's skill-creator packaging contract, while also removing genuine dead weight from the repo (unused vendor, legacy plans). - -## Problem Frame - -- Trevin tried to upload the public repo as a Claude Skill and hit the 200-file limit -- 215 of 406 files are `vendor/package/` - an extracted `steipete-bird-0.8.0.tgz` that no code imports -- The real runtime X client lives at `scripts/lib/vendor/bird-search/` (15 files, referenced by `scripts/lib/bird_x.py:5` and `tests/test_bird_x.py:133`) -- `.clawhubignore` is ClawHub-specific and does not affect a hand-rolled zip upload -- Users have no documented path to produce a compliant upload zip -- Legacy top-level `plans/` folder holds pre-`docs/plans/` planning artifacts (confirmed waste by Matt, 2026-04-14 chat) - -## Requirements Trace - -- R1. After this plan lands, the produced upload zip is =200 files -- R2. The X/bird-search runtime still works - no regression in `tests/test_bird_x.py` -- R3. A contributor following README instructions can produce a Claude-Skill-upload-compatible `.skill` file in one command -- R4. Re-introduction of a root `vendor/` directory is prevented via `.gitignore` -- R5. No runtime behavior changes for existing skill consumers (Claude Code plugin, ClawHub, Gemini) -- R6. Produced zip matches Anthropic's canonical skill-folder layout: top-level directory named exactly `last30days` containing `SKILL.md` at its root, with YAML frontmatter `name: last30days` -- R7. Root `SKILL.md` frontmatter passes Anthropic's documented limits: `name` =64 chars (currently 10), `description` =200 chars (currently 228, needs trimming) -- R8. Produced zip contains exactly one `SKILL.md` (at `last30days/SKILL.md`) - no conflicting second skill spec, no symlinks that the uploader may reject or break -- R9. No runtime import reaches an excluded path (proven by import-graph audit, not just asserted) - -## Scope Boundaries - -Non-goals: -- Not touching the private repo or ClawHub publish flow (those have their own strip script) -- Not resolving the adjacent open issues (#239 plugin loader path-escape, #236 OpenClaw paths, #231 security scan, #190 version drift, #184 Gemini install) - each deserves its own plan -- Not redesigning the skill into self-contained subfolders or splitting scripts into a separate package -- Not adding CI enforcement of the 200-file cap (possible follow-up) - -## Context and Research - -### Anthropic's canonical skill-upload contract - -Sourced from Anthropic's skill-creator repo (`anthropics/skills/skills/skill-creator/scripts/package_skill.py`) and help-center docs: - -1. **Output format:** a `.skill` file, which is a standard zip with the `.skill` extension. -2. **Top-level entry in the zip must be a single directory** whose name matches `name:` in the skill's YAML frontmatter. Anthropic's packager uses `arcname = file_path.relative_to(skill_path.parent)`, so the zip always contains `/...`. -3. **That directory must contain `SKILL.md`** at its root (the packager explicitly validates this). -4. **Required YAML frontmatter:** `name` (=64 chars, lowercase + hyphens) and `description` (=200 chars). Our root SKILL.md already satisfies both. -5. **Canonical exclusions** applied by Anthropic's packager: - - Directories: `__pycache__`, `node_modules` - - Root-only: `evals/` - - File globs: `*.pyc` - - Files: `.DS_Store` -6. **Empirical limit:** the upload UI rejects =200 files (screenshot 2026-04-14). Not documented, but confirmed. -7. **Per-file size cap** is not publicly documented; general claude.ai uploads cap at 30MB per file. Conservative target: keep any single file under 10MB. - -### Relevant code and patterns in this repo - -- `SKILL.md` (root, 1382 lines, 80KB) - `name: last30days`, `user-invocable: true`. This is the skill. -- `skills/last30days/SKILL.md` (230 lines) - `name: last30days-v3-spec`, `user-invocable: false`. Internal architecture spec, separate skill name - not the upload target. -- `vendor/package/` - accidental commit from PR #48, 215 files, zero importers. -- `vendor/steipete-bird-0.8.0.tgz` - source tarball, also unused at runtime. -- `scripts/lib/vendor/bird-search/` - the ACTUAL vendored bird-search client (15 files). Keep. -- `plans/` (top-level, 2 files: `feat-add-websearch-source.md`, `fix-strict-date-filtering.md`) - legacy, pre-`docs/plans/` convention. Matt confirmed delete. -- `scripts/sync.sh` - deploys skill to `~/.claude`, `~/.agents`, `~/.codex`. Reference for runtime-required files. -- `.clawhubignore` - existing exclude list for the ClawHub path. Not used here, but good cross-reference for what is runtime-irrelevant. -- `.gitignore` - current dev excludes (`.venv/`, `__pycache__/`, `.DS_Store`, etc). - -### Institutional learnings - -- Private repo has `scripts/clawhub-publish.sh` + `scripts/strip_for_openclaw.py` that build a staging dir with only OpenClaw-safe files. Not needed for this public-path upload; `git archive` with `--prefix` is sufficient and dependency-free. -- PR #48 introduced `vendor/package/` unintentionally. No code imports from it. - -### File count math (verified via dry run) - -| Strategy | File count | Under cap? | -|---|---|---| -| Current repo, zip as-is | 406 | No | -| After `vendor/` deleted | 191 | Yes (thin margin) | -| After `vendor/` + `plans/` deleted, no further excludes | 189 | Yes | -| With full planned excludes (Anthropic canonical + tests/docs/fixtures/assets/dev manifests/nested skill dirs) | 81 | Comfortable headroom | - -Dry run run on 2026-04-14 against the current working tree. Simulated the proposed `.gitattributes` with a `find` filter matching the intended exclude list. Result: 81 files, 868KB uncompressed. Actual `git archive` output may differ slightly (by 1-2 files) but will land well under 200. - -### Runtime import audit (proves core experience unchanged) - -Grepped all `import`/`from` statements in `scripts/**/*.py`. Non-stdlib imports resolve to only: -- `lib.*` (internal package at `scripts/lib/`) -- `store` (internal module at `scripts/store.py`) -- `scripts.*` (internal) - -No runtime import reaches `tests/`, `docs/`, `fixtures/`, `vendor/` (root), `plans/`, `assets/`, `.agents/`, `.codex-plugin/`, `.hermes-plugin/`, or any other excluded path. The shipped `.skill` file contains everything the runtime needs and nothing it does not. - -### Symlink and multi-SKILL.md audit - -The repo contains one symlink: `skills/last30days-nux/SKILL.md -> ../../SKILL.md`. Three SKILL.md files in total: -- `SKILL.md` (root, `name: last30days`, `user-invocable: true`) - the actual skill -- `skills/last30days/SKILL.md` (`name: last30days-v3-spec`, `user-invocable: false`) - internal architecture doc -- `skills/last30days-nux/SKILL.md` (symlink to root) - nux variant reference - -Shipping all three inside one zip creates two rejection risks: -1. Uploader sees multiple `SKILL.md` with conflicting `name:` values and refuses or misbinds -2. `git archive` stores the symlink as a symlink entry; the uploader may reject symlinked entries on principle - -Both risks disappear by excluding `skills/` entirely from the zip. The two internal skill definitions are not needed for claude.ai skill execution - they serve the repo as documentation / Claude Code plugin layout, not the direct upload path. - -### Sources consulted - -- Anthropic skill help center article (general upload guidance, no file-count number documented) -- [anthropics/skills README](https://github.com/anthropics/skills/blob/main/README.md) - YAML frontmatter requirements -- [anthropics/skills package_skill.py](https://github.com/anthropics/skills/blob/main/skills/skill-creator/scripts/package_skill.py) - canonical exclusions and arcname shape -- Trevin's 2026-04-14 chat screenshot (empirical 200-file cap) -- Adjacent issues #239, #236, #190 for context on current packaging mess - -## Key Technical Decisions - -- **Delete `vendor/` outright** rather than gitignore-and-leave. Pure dead weight. Rationale: the real vendored client is at `scripts/lib/vendor/bird-search/`, root `vendor/` has zero importers; keeping it invites re-upload. -- **Delete top-level `plans/`** (Matt confirmed). Rationale: superseded by `docs/plans/`. Moving content into `docs/plans/` if any is still relevant; otherwise just delete. -- **Produce a `.skill` file (not a plain `.zip`)** via `git archive --format=zip --prefix=last30days/ -o dist/last30days.skill HEAD`. Rationale: matches Anthropic's canonical contract - zip extension is cosmetic, but the `.skill` affordance is what the upload UI expects. -- **Use `git archive` + `.gitattributes export-ignore`** rather than a Python packager. Rationale: no Python dependency at build time, honors git's declarative exclude model, reusable by anyone running `git archive` directly. -- **Mirror Anthropic's canonical exclusions in `.gitattributes`** (`__pycache__`, `node_modules`, `*.pyc`, `.DS_Store`, `evals/`) alongside our repo-specific excludes. Rationale: future-proof if a contributor adds node deps; keeps us aligned with the Anthropic baseline. -- **Exclude `skills/` from the upload zip** (covers `skills/last30days/SKILL.md` and `skills/last30days-nux/SKILL.md`). Rationale: shipping multiple SKILL.md files with different `name:` values is a likely uploader-rejection cause, and the symlink at `skills/last30days-nux/SKILL.md` is an independent rejection risk. Repo contents stay intact - Claude Code plugin and GitHub viewers still see the directory. -- **Keep `.clawhubignore` as-is** - it serves the ClawHub publish path separately. Do not merge the two lists; different consumers, different exclusions. -- **Prevent regression with a `/vendor/` entry in `.gitignore`** (leading slash, so `scripts/lib/vendor/` is unaffected). -- **Do not address #239 `"skills": ["./"]` path-escape here.** That is a plugin.json change, not a zip-packaging change. Separate plan. - -## Open Questions - -### Resolved during planning - -- Is root `vendor/` used? No. Grep for `vendor/package`, `vendor/steipete`, `from vendor` returns zero hits outside `scripts/lib/vendor/`. -- Is `scripts/lib/vendor/bird-search/` safe? Yes. Referenced by `scripts/lib/bird_x.py:5` and `tests/test_bird_x.py:133`. -- What name does the top-level zip directory need? `last30days` - matches `name: last30days` in the root `SKILL.md` frontmatter. -- Does `skills/last30days/SKILL.md` conflict? No. It declares a different skill name (`last30days-v3-spec`) and is `user-invocable: false`. Not the upload target, and safe to ship inside the zip. -- Is there a documented file-count cap? No. 200 is empirical from the UI error screenshot. -- Should we gate this on a version bump? Yes, 3.0.0 - 3.0.1. Same API, same runtime, smaller and uploadable package. - -### Deferred to implementation - -- Exact `.gitattributes` export-ignore entries may need one tuning pass if `git archive` surfaces a file we forgot. Verification step catches it. -- Whether to delete `SKILL-original.md` from the repo entirely or just export-ignore. Leaning export-ignore to preserve git history context. -- Whether any content in `plans/*.md` is still live reference material. If so, move to `docs/plans/` under new naming convention; if not, delete outright. - -## Implementation Units - -- [ ] **Unit 1: Remove accidental `vendor/` commit** - -**Goal:** Delete the root `vendor/` directory and the stray `.tgz`, both unused at runtime. - -**Requirements:** R1, R2, R5 - -**Dependencies:** None - -**Files:** -- Delete: `vendor/` (entire tree, 215 files) -- Delete: `vendor/steipete-bird-0.8.0.tgz` -- Modify: `.gitignore` (add `/vendor/` to prevent regression - leading slash to avoid matching `scripts/lib/vendor/`) - -**Approach:** -- Single commit: `chore: remove unused root vendor/ directory (215 files from PR #48)` -- Verify `scripts/lib/vendor/bird-search/` is untouched -- Verify no `from vendor` or `vendor/package` references appear in the diff - -**Patterns to follow:** -- Commit message style matches recent history - -**Test scenarios:** -- Happy path: `find . -type f -not -path './.git/*' | wc -l` returns =200 after commit -- Integration: `python -m pytest tests/test_bird_x.py -q` passes - confirms the real vendored client still resolves -- Integration: `bash scripts/sync.sh` completes without error - -**Verification:** -- Zero files remain under `vendor/` on `main` -- `tests/test_bird_x.py` still passes -- `.gitignore` now contains `/vendor/` - -- [ ] **Unit 2: Remove legacy top-level `plans/` directory** - -**Goal:** Delete the pre-`docs/plans/` folder (Matt confirmed waste). - -**Requirements:** R1, R5 - -**Dependencies:** None (independent of Unit 1) - -**Files:** -- Delete: `plans/feat-add-websearch-source.md` -- Delete: `plans/fix-strict-date-filtering.md` -- Delete: `plans/` (now empty) - -**Approach:** -- Skim both files first. If either still reflects real upcoming work, port it to `docs/plans/YYYY-MM-DD-NNN--*-plan.md` before deletion. If not, delete. -- Commit: `chore: remove legacy plans/ directory (superseded by docs/plans/)` - -**Test scenarios:** -- Test expectation: none - pure housekeeping, no code paths affected - -**Verification:** -- `plans/` does not exist on `main` -- Nothing in the repo references `plans/feat-add-websearch-source.md` or `plans/fix-strict-date-filtering.md` (grep to confirm) - -- [ ] **Unit 3: Declare zip-time excludes via `.gitattributes`** - -**Goal:** Use `export-ignore` so `git archive` produces a skill-shaped zip without hand-filtering. - -**Requirements:** R1, R3, R6 - -**Dependencies:** Unit 1, Unit 2 - -**Files:** -- Create: `.gitattributes` - -**Approach:** -- Anthropic canonical exclusions (match `package_skill.py`): - - `__pycache__/` export-ignore - - `node_modules/` export-ignore - - `*.pyc` export-ignore - - `.DS_Store` export-ignore - - `evals/` export-ignore -- Repo-specific exclusions (dev/docs/build artifacts not needed at runtime): - - `tests/` (64 files) - - `docs/` (17 files including `docs/test-results/`) - - `fixtures/` (7 files) - - `assets/` (5 files, 14MB of README media) - - `SKILL-original.md` (historical) - - `SPEC.md`, `TASKS.md`, `test-run.log`, `CONTRIBUTORS.md`, `HERMES_SETUP.md`, `release-notes.md`, `CHANGELOG.md` - - `uv.lock` - - `.agents/`, `.codex-plugin/`, `.hermes-plugin/`, `.claude-plugin/` (platform adapters - skill-upload path is platform-agnostic) - - `.clawhubignore`, `.gitignore`, `.gitattributes` - - `skills/` (avoid second SKILL.md with conflicting `name:`; also drops the symlink at `skills/last30days-nux/SKILL.md`) -- Keep in archive: `scripts/` (runtime), root `SKILL.md`, `README.md`, `LICENSE`, `pyproject.toml`, `CLAUDE.md`, `gemini-extension.json`, `agents/`, `hooks/` - -**Technical design:** *(directional guidance, not implementation spec)* - -```gitattributes -# Anthropic canonical skill-packaging excludes -__pycache__/ export-ignore -node_modules/ export-ignore -*.pyc export-ignore -.DS_Store export-ignore -evals/ export-ignore - -# Repo-specific: tests + docs + media (not runtime) -tests/ export-ignore -docs/ export-ignore -fixtures/ export-ignore -assets/ export-ignore - -# Repo-specific: historical + dev manifests -SKILL-original.md export-ignore -SPEC.md export-ignore -... -``` - -**Patterns to follow:** -- `.gitattributes` export-ignore syntax per [git docs](https://git-scm.com/docs/gitattributes#_creating_an_archive) - -**Test scenarios:** -- Happy path: `git archive --format=zip HEAD | zipinfo -1 - | wc -l` returns =200 -- Happy path: zip contains `SKILL.md`, `scripts/last30days.py`, `scripts/lib/bird_x.py`, `scripts/lib/vendor/bird-search/lib/cookies.js` -- Happy path: zip contains exactly one `SKILL.md` entry at the top level (not multiple, not a symlink) -- Edge case: zip does NOT contain `tests/`, `docs/`, `assets/*.jpeg`, `*.mp3`, `skills/` -- Edge case: no symlink entries in the zip (`unzip -l` lines starting with `l`) -- Edge case: zip size stays under ~2MB (if over 5MB an unintended large file slipped through) - -**Verification:** -- Running `git archive --format=zip --output=/tmp/test.zip HEAD && unzip -l /tmp/test.zip | tail -1` reports =200 files and a sane byte count - -- [ ] **Unit 4: Add `scripts/build-skill.sh` user-facing builder** - -**Goal:** One-command path to produce a Claude-upload-compatible `.skill` file. - -**Requirements:** R3, R6 - -**Dependencies:** Unit 3 - -**Files:** -- Create: `scripts/build-skill.sh` -- Modify: `.gitignore` (add `/dist/` for build artifact) - -**Approach:** -- Bash, executable, `set -euo pipefail` -- `git archive --format=zip --prefix=last30days/ --output=dist/last30days.skill HEAD` -- The `--prefix=last30days/` nests everything under `last30days/` inside the zip, matching Anthropic's arcname contract -- Refuse to build if working tree is dirty (`git diff --quiet && git diff --cached --quiet`) -- Print file count, archive size, and path to paste into the upload UI -- Fail with a clear error if count exceeds 200 (defensive check) - -**Technical design:** *(directional guidance, not implementation spec)* - -```bash -#!/usr/bin/env bash -# build-skill.sh - package repo as a Claude-upload-ready .skill file -# Usage: bash scripts/build-skill.sh -set -euo pipefail - -if ! git diff --quiet || ! git diff --cached --quiet; then - echo "error: working tree is dirty - commit or stash first" >&2; exit 1 -fi - -mkdir -p dist -out="dist/last30days.skill" -git archive --format=zip --prefix=last30days/ --output="$out" HEAD - -count=$(unzip -l "$out" | tail -1 | awk '{print $2}') -[ "$count" -le 200 ] || { echo "error: $count files in zip, cap is 200" >&2; exit 1; } -echo "built $out ($count files, $(du -h "$out" | cut -f1))" -``` - -**Patterns to follow:** -- Style of `scripts/sync.sh` (bash, top-of-file comment, `set -euo pipefail`) - -**Test scenarios:** -- Happy path: clean tree, `bash scripts/build-skill.sh` produces `dist/last30days.skill` with =200 files and the top-level entry is `last30days/` -- Happy path: `unzip -p dist/last30days.skill last30days/SKILL.md | head -2` shows `---` (frontmatter start) confirming SKILL.md is at the right location -- Edge case: dirty working tree - script exits non-zero with clear error -- Edge case: idempotent - running twice overwrites cleanly -- Error path: if a future change inflates file count past 200, the defensive `[ "$count" -le 200 ]` check fails and the script refuses to produce a broken output - -**Verification:** -- `bash scripts/build-skill.sh && unzip -l dist/last30days.skill | grep "^ 0 .* last30days/$"` confirms the prefix directory exists -- `unzip -l dist/last30days.skill | grep "last30days/SKILL.md"` confirms SKILL.md is at the expected path -- `unzip -l dist/last30days.skill | grep -c "SKILL.md"` returns exactly 1 -- `unzip -l dist/last30days.skill | awk '{print $NF}' | grep -v "^$" | sort -u | grep "skills/" || true` returns nothing (confirms internal skill dirs excluded) -- Gate: a contributor must run `bash scripts/build-skill.sh` on their branch and attach the produced file to their PR before merging any change that touches `.gitattributes` or exclude-sensitive paths - -- [ ] **Unit 5: Document the upload path in README** - -**Goal:** Users know how to produce an upload `.skill` without reading the source. - -**Requirements:** R3 - -**Dependencies:** Unit 4 - -**Files:** -- Modify: `README.md` (add a short "Upload as a Claude Skill" subsection under the existing install section) - -**Approach:** -- One paragraph plus a single command block: `bash scripts/build-skill.sh` -- Mention the 200-file cap as context so future changes do not bust it -- Point users at the claude.ai skill upload UI (note: link only if a stable URL exists at implementation time, otherwise describe the UI path) - -**Test scenarios:** -- Test expectation: none - pure documentation change - -**Verification:** -- `grep -n "build-skill" README.md` returns a hit -- Instructions match actual script behavior - -- [ ] **Unit 6: Trim SKILL.md description to =200 chars** - -**Goal:** Make root `SKILL.md` frontmatter pass Anthropic's documented `description` limit. - -**Requirements:** R7 - -**Dependencies:** None (independent of other units) - -**Files:** -- Modify: `SKILL.md` (frontmatter `description:` field only) - -**Approach:** -- Current description is 228 chars. Cut 28+ chars without losing signal. -- Suggested rewrite (196 chars): `"Multi-query social search with planned queries. Research any topic across Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, and the web. Gemini/OpenAI fallback when needed."` -- Confirm the trimmed version still surfaces for the right prompts (smoke test: run `python scripts/last30days.py "test" --emit=compact` and confirm behavior unchanged; description is metadata, not runtime input) -- Update `skills/last30days/SKILL.md` description too if it exceeds 200 chars (check during implementation) - -**Test scenarios:** -- Happy path: `python3 -c "import re; d=open('SKILL.md').read(); m=re.search(r'^description:\s*\"(.+?)\"', d, re.M); assert len(m.group(1)) <= 200, len(m.group(1))"` passes - -**Verification:** -- Description field is =200 chars in root SKILL.md -- Skill still triggers on relevant prompts (manual smoke check) - -- [ ] **Unit 7: Version bump and changelog** - -**Goal:** Ship as 3.0.1 so consumers see the packaging fix. - -**Requirements:** R5 - -**Dependencies:** Units 1-6 - -**Files:** -- Modify: `.claude-plugin/plugin.json` (3.0.0 - 3.0.1) -- Modify: `SKILL.md` frontmatter version -- Modify: `skills/last30days/SKILL.md` frontmatter version -- Modify: `gemini-extension.json` version (note: #190 flags this as stale at 2.9.5; bumping here partially addresses that but full resolution is out of scope) -- Modify: `CHANGELOG.md` -- Modify: `release-notes.md` - -**Approach:** -- Atomic version bump across all manifests -- Changelog entry: "Packaging: `scripts/build-skill.sh` produces a compliant `.skill` file; removed unused root `vendor/` (215 files) and legacy `plans/`; repo file count fits under claude.ai's 200-file upload cap" - -**Test scenarios:** -- Happy path: `grep -rn "3.0.1" SKILL.md skills/last30days/SKILL.md .claude-plugin/plugin.json gemini-extension.json` returns four consistent hits -- Integration: `bash scripts/sync.sh` completes cleanly - -**Verification:** -- All four version declarations read `3.0.1` -- CHANGELOG and release-notes have dated entries - -## System-Wide Impact - -- **Interaction graph:** Skill-runtime import graph is unchanged. Removed code (root `vendor/`, `plans/`) has zero importers. -- **Error propagation:** `build-skill.sh` is a new surface; failure mode is non-zero exit with clear stderr. No runtime error paths touched. -- **State lifecycle risks:** None. `dist/` is gitignored build output. -- **API surface parity:** No change to any user-facing API, CLI flag, config key, or SKILL.md contract. -- **Integration coverage:** `tests/test_bird_x.py` exercises the real vendored client - if it regressed, the test fails. Run it after Unit 1. -- **Unchanged invariants:** `scripts/lib/vendor/bird-search/` stays. `scripts/sync.sh` deploy behavior unchanged. ClawHub publish flow (private repo) untouched. Claude Code plugin install via GitHub URL still works. - -## Risks and Dependencies - -| Risk | Mitigation | -|------|------------| -| Deleting `vendor/` silently breaks something we missed | Run `pytest tests/test_bird_x.py` and `bash scripts/sync.sh` after the delete; grep for `vendor/package` before merging | -| claude.ai rejects the `.skill` file for a reason other than file count (e.g., frontmatter character, hidden file) | Test-upload the produced artifact against claude.ai once before merging; iterate on `.gitattributes` if needed | -| `.gitattributes` over-excludes and breaks the runtime skill | Unit 3 verification step explicitly checks runtime paths are present in the produced archive | -| A future PR re-vendors something at `/vendor/` and busts the 200 cap again | `/vendor/` in `.gitignore` plus the defensive `=200` check in `build-skill.sh` catches it | -| Version bump collides with in-flight PRs that also bump versions | Coordinate with #229, #217 which touched version strings; check before merging | -| `skills/last30days/SKILL.md` (internal spec) being shipped inside the zip confuses the claude.ai uploader | Resolved by excluding `skills/` from the zip (Unit 3). Internal spec remains in the repo for plugin consumers | -| `skills/last30days-nux/SKILL.md` is a symlink to `../../SKILL.md`; claude.ai may reject zips with symlink entries | Resolved by excluding `skills/` from the zip (Unit 3). Symlink never enters the archive | - -## Documentation and Operational Notes - -- Update README only (Unit 5). No runbook, no migration, no flag. -- No deployment step - plugin consumers get the packaging fix automatically on next update. -- Release notes flag: manual uploaders should re-zip via `scripts/build-skill.sh`. -- Opportunistic future work (out of scope here): CI check that fails PRs that push the zip over 200 files. - -## Sources and References - -- Trevin's 2026-04-14 chat screenshot: "Zip contains too many files (maximum 200)" -- [anthropics/skills README](https://github.com/anthropics/skills/blob/main/README.md) - YAML frontmatter requirements -- [anthropics/skills package_skill.py](https://github.com/anthropics/skills/blob/main/skills/skill-creator/scripts/package_skill.py) - canonical exclusions, arcname convention, validation gates -- [claude.ai skill help center](https://support.claude.com/en/articles/12512180-use-skills-in-claude) - upload failure modes (zip size, folder-name mismatch, missing SKILL.md) -- PR #48 (2026-02) - the merge that introduced `vendor/package/` -- Open issues adjacent but out of scope: #239, #236, #231, #190, #184 -- Related code: `scripts/lib/bird_x.py:5`, `tests/test_bird_x.py:133`, `.clawhubignore`, `scripts/sync.sh`, root `SKILL.md` frontmatter -- Private-repo reference pattern: `scripts/clawhub-publish.sh` + `scripts/strip_for_openclaw.py` - not copied here; `git archive` is simpler for the public path diff --git a/docs/plans/2026-04-14-002-feat-claudeai-distribution-plan.md b/docs/plans/2026-04-14-002-feat-claudeai-distribution-plan.md deleted file mode 100644 index 21b0978..0000000 --- a/docs/plans/2026-04-14-002-feat-claudeai-distribution-plan.md +++ /dev/null @@ -1,459 +0,0 @@ ---- -title: claude.ai distribution + discoverability push -type: feat -status: active -date: 2026-04-14 ---- - -# claude.ai distribution + discoverability push - -## Overview - -The 200-file upload bug is fixed and `last30days.skill` works on claude.ai. But "it can be uploaded" is not the same as "people use it." Claude.ai has no native skill marketplace, so discovery happens through a 3-layer stack: Anthropic's curated plugin marketplace, third-party aggregators, and social/newsletter amplification. The question Matt asked - "is the GitHub release the right decision" - has a clear answer: yes, but it is table stakes, not the strategy. This plan cuts the release and then pulls the real distribution levers. - -## Problem Frame - -Today, the only way a claude.ai user can get `last30days` is to clone the repo and run `scripts/build-skill.sh`. That filters out 99% of potential users. Even once a release exists with a direct download link, the hard problem is discovery - claude.ai users do not browse GitHub for skills. They find skills via Anthropic's "Discover" tab in Claude Code, third-party aggregator sites (skillsmp.com, mcpmarket.com, claudeskills.info), awesome-lists on GitHub, newsletters (The Neuron), and social posts (X, r/ClaudeAI). - -Success looks like: a claude.ai user who never visits the repo can find, download, and upload the skill in under 60 seconds, and keep using it because the trigger description fires on the right prompts. - -## Requirements Trace - -- R1. A one-click install path exists for claude.ai users: click a link from README/marketplace/aggregator, get `last30days.skill`, drop into Upload dialog -- R2. The skill is submitted to Anthropic's official plugin marketplace at `platform.claude.com/plugins/submit` -- R3. The skill is listed in at least 4 high-traffic awesome-lists / aggregators -- R4. The SKILL.md YAML `description` and `argument-hint` fields are tuned so Claude's skill-selector actually invokes `last30days` on research-intent prompts (trigger quality is the single biggest install-to-reuse lever) -- R5. First-run experience works with zero API keys for the default sources (Reddit, Hacker News, Polymarket, GitHub) - already true, verify does not regress -- R6. At least one high-visibility amplification moment ships within 14 days: demo GIF + launch tweet + The Neuron pitch -- R7. Basic metrics are in place to learn what works: release-download counts, aggregator referrer traffic, GitHub star velocity before/after - -## Scope Boundaries - -Non-goals for this plan: -- Not building a custom skill-hosting site or our own marketplace -- Not changing the runtime pipeline or adding features - this is pure distribution -- Not spamming aggregators with low-effort PRs - one quality submission per venue -- Not gaming install counts or stars -- Not displacing the existing Claude Code plugin / OpenClaw / Gemini distribution - those stay as-is, cross-linked -- Not depending on Anthropic marketplace acceptance before other levers ship - marketplace review is slow and gate-able - -## Context and Research - -### The claude.ai skill ecosystem in April 2026 - -- **No native claude.ai skill marketplace.** Upload is the only end-user path inside the web UI. -- **Anthropic's Plugin/Skills Marketplace** (submissions at `platform.claude.com/plugins/submit`) is the closest thing to a "featured" channel and ships through Claude Code's "Discover" tab. Quality/security review gates acceptance. Research-category skills are under-represented vs. dev-tool skills. -- **Third-party aggregators** drive most organic discovery outside Anthropic's channels: - - `skillsmp.com`, `mcpmarket.com`, `claudeskills.info`, `skillsdirectory.com`, `agensi.io` - - These aggregators scrape awesome-lists, so one well-placed PR cascades -- **Awesome-lists** where skills discovery congregates: - - `ComposioHQ/awesome-claude-skills` - - `travisvn/awesome-claude-skills` - - `karanb192/awesome-claude-skills` - - `VoltAgent/awesome-agent-skills` - - `sickn33/antigravity-awesome-skills` (1,400+ skills indexed) -- **Newsletter amplification:** The Neuron runs a daily "AI Skill of the Day" digest - the single biggest external traffic source per successful skill creators. Their "practical workflow" angle fits a research skill cleanly. -- **Install-count reference points** from public aggregator data: - - `self-improving-agent`: 357k installs - - `frontend-design`: 277k installs - - `skill-vetter`: 190k installs - - `github`: 148k installs - - `proactive-agent`: 135k installs - - Long tail: ~500 installs - -The gap between 500-install and 357k-install skills is mostly: (a) trigger description quality, (b) zero-config first run, (c) one amplification moment that caught. - -### Current distribution surface for last30days - -- Claude Code plugin via marketplace and GitHub URL: live -- OpenClaw via ClawHub (`clawhub install last30days-official`): live -- Gemini extension: live -- Manual `git clone`: documented in README -- claude.ai `.skill` upload: just shipped, undocumented for end users (no link) - -The cross-linking graph is incomplete. Traffic that already exists (Claude Code install page, OpenClaw listing, Gemini extensions page) is not being routed to the new claude.ai path. - -### Reference: trigger description quality - -The root `SKILL.md` `description` field is how Claude decides whether to invoke the skill. Current text (as of 3.0.1, 167 chars): - -> "Multi-query social research across Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, and the web. Intelligent query planning with Gemini/OpenAI fallback." - -Analysis: solid source list, weak on action verbs and example queries. Successful skills include imperative verbs ("research", "find", "summarize", "compare") and 1-2 example triggers the user might type. At 167/200 chars, there is room. - -## Key Technical Decisions - -- **Cut v3.0.1 GitHub release with `last30days.skill` attached as an asset** (table stakes). Rationale: every downstream lever (README link, marketplace submission, aggregator PR, tweet) needs a stable public download URL. -- **Automate `.skill` build in CI on tag push** so future releases never forget to attach the artifact. Rationale: manual builds break over time; this is a one-time 10-line GitHub Actions workflow. -- **Prioritize marketplace submission in parallel with aggregator PRs**, not in sequence. Rationale: marketplace review is slow and opaque; do not block aggregator work on it. If rejected, we still have the aggregator presence. -- **Tune the SKILL.md description to optimize trigger selection**, not marketing copy. Rationale: this is the single biggest re-use lever per the ecosystem research. Marketing copy goes in README/release notes, not frontmatter. -- **One quality pass per aggregator, not a spray.** Rationale: awesome-list maintainers reject duplicate / low-effort PRs; reputation matters. -- **Ship the launch tweet with a real demo GIF**, not a screenshot. Rationale: Boris Cherny's Claude Code viral tweet template (one query, one result, "oh wow" moment) consistently outperforms text-only launches. -- **Pitch The Neuron once, with a production-quality 60-second demo**, not a cold email. Rationale: single shot at the biggest amplifier; treat it like a press release, not a tweet. -- **Track release-download count + GitHub referrer traffic as proxies for adoption** until we have better signal. Rationale: claude.ai upload counts are not exposed to creators. -- **Cross-link existing distribution pages back to claude.ai** as part of the release. Rationale: converting existing users to multi-surface users is cheaper than acquiring new ones. - -## Open Questions - -### Resolved during planning - -- Is the GitHub release the right first step? Yes. Every other lever depends on a stable download URL. But it is a prerequisite, not the strategy. -- Does claude.ai have a native skill directory? No (confirmed April 2026). -- Should we wait for Anthropic marketplace acceptance before shipping other levers? No - parallelize. -- Do we need to rebuild the runtime to improve claude.ai adoption? No - the runtime is strong; the gap is distribution. - -### Deferred to implementation - -- Exact Neuron pitch copy - draft during Unit 8, refine based on what their recent editions have favored -- Whether to tag `@steipete`, `@AnthropicAI`, `@alexalbert__` in the launch tweet - confirm current handles and review each's posting culture before tagging -- Which specific demo query to record for the launch GIF - pick during Unit 7 based on what's newsworthy that week -- Whether to request a "skills-research" badge on skillsdirectory.com/agensi.io - check their current badge programs during Unit 5 - -## High-Level Technical Design - -> *This illustrates the intended distribution graph and is directional guidance for review, not implementation specification.* - -``` -[GitHub Release v3.0.1] - | - +-- last30days.skill (asset, public URL) - | - +------> README "Upload to claude.ai" section (Unit 3) - | - +------> Claude Code plugin README link (Unit 4) - +------> OpenClaw listing link (Unit 4) - +------> Gemini extension link (Unit 4) - | - +------> Anthropic marketplace submission (Unit 6) - | - +------> Aggregator PRs (Unit 5): - | * ComposioHQ/awesome-claude-skills - | * travisvn/awesome-claude-skills - | * karanb192/awesome-claude-skills - | * VoltAgent/awesome-agent-skills - | * sickn33/antigravity-awesome-skills - | * skillsmp.com submit form - | - +------> Amplification (Units 7-9): - * Demo GIF + launch tweet - * The Neuron "Skill of the Day" pitch - * News-cycle recurring tweet (weekly) - -All paths end at: claude.ai Upload Skill dialog -Trigger quality (Unit 2) determines whether installs become sustained usage -``` - -## Implementation Units - -- [x] **Unit 1: Cut v3.0.1 GitHub release with `.skill` asset + auto-build CI** - -**Goal:** Produce a stable public download URL for `last30days.skill` so every downstream lever has something to link to, and guarantee future releases include the artifact automatically. - -**Requirements:** R1 - -**Dependencies:** None (plan 2026-04-14-001 already shipped the build script) - -**Files:** -- Create: `.github/workflows/release.yml` -- Modify: none at release time (release is a git-tag + GitHub release action) - -**Approach:** -- Tag `v3.0.1` on `main`, push -- Create GitHub release with the CHANGELOG v3.0.1 entry as body, attach `dist/last30days.skill` -- Add CI workflow that triggers on `push: tags: 'v*'`, runs `bash scripts/build-skill.sh`, uploads the artifact to the release. The `action-gh-release` pattern is standard. -- Release URL shape: `https://github.com/mvanhorn/last30days-skill/releases/download/v3.0.1/last30days.skill` (deterministic, shareable) - -**Patterns to follow:** -- Any existing `.github/workflows/` patterns in the repo -- `actions/checkout@v4` + `softprops/action-gh-release@v2` is the conventional combo - -**Test scenarios:** -- Happy path: pushing `v3.0.1` tag produces a release with `last30days.skill` attached and publicly downloadable without auth -- Edge case: re-tagging `v3.0.1` does not duplicate or corrupt the asset -- Error path: build failure in the workflow fails the release cleanly (no empty release created) - -**Verification:** -- `curl -fsSL -o /tmp/dl.skill https://github.com/mvanhorn/last30days-skill/releases/download/v3.0.1/last30days.skill` succeeds anonymously -- Downloaded file matches `dist/last30days.skill` byte-for-byte -- A second tag (e.g., `v3.0.2-test`) in a branch triggers the workflow end-to-end - -- [x] **Unit 2: Tune SKILL.md description and argument-hint for trigger quality** - -**Goal:** Increase the probability that Claude's skill-selector invokes `last30days` on research-intent prompts. Trigger quality is the single biggest install-to-reuse lever per ecosystem research. - -**Requirements:** R4, R5 - -**Dependencies:** None - -**Files:** -- Modify: `SKILL.md` (frontmatter `description` and `argument-hint` only) -- Modify: `skills/last30days/SKILL.md` (if parity needed) - -**Approach:** -- Rewrite `description` to lead with an imperative action verb and include 1-2 concrete example queries, staying =200 chars -- Rewrite `argument-hint` to show 2-3 canonical invocations that mirror real user phrasing, not marketing phrasing -- Keep the source list intact - that's the value prop - but move it later in the sentence -- Reference frames that worked for high-install skills: `frontend-design`, `self-improving-agent`, `github` - -**Technical design:** *(directional guidance, not implementation spec)* - -Candidate shape (verify char count in implementation): - -```yaml -description: "Research what people actually say about any topic in the last 30 days. Pulls real posts and engagement from Reddit, X, YouTube, TikTok, Hacker News, Polymarket, GitHub, and the web." -argument-hint: 'last30days AI video tools | last30days nvidia earnings reaction | last30days best noise cancelling headphones' -``` - -**Test scenarios:** -- Happy path: in a fresh claude.ai chat, prompts like "what are people saying about X this week" surface `last30days` in the skill-selector candidate set -- Edge case: generic "research X" prompts do not over-select `last30days` when the user clearly wants a general answer (avoids false-positive selection) -- Integration: test in all three environments - claude.ai web, Claude Code, OpenClaw - to confirm selection behavior is consistent - -**Verification:** -- Description =200 chars, checked by the same regex Unit 6 of plan 001 used -- At least 3 real-user prompt phrasings trigger skill selection in manual testing -- No regression on zero-config first-run (no new API keys required) - -- [x] **Unit 3: Rewrite the README claude.ai section with one-click install** - -**Goal:** Replace the current "run this bash script" instructions with a one-click download link pointing at the GitHub release asset. - -**Requirements:** R1 - -**Dependencies:** Unit 1 (release must exist first) - -**Files:** -- Modify: `README.md` (the "Upload as a Claude Skill" section added in plan 001) - -**Approach:** -- Replace the `bash scripts/build-skill.sh` instruction with a direct download link to the release asset -- Keep the build-from-source instruction as a fallback for developers, demoted below the direct link -- Add a short 3-step install guide with specific UI path: "Settings > Capabilities > Skills > + button, drop the .skill file" -- Include a screenshot or GIF showing the upload flow if space allows (can be added in Unit 7) - -**Test scenarios:** -- Test expectation: none - pure documentation change - -**Verification:** -- A user following the README instructions end-to-end can go from "never heard of this" to working skill in under 60 seconds -- Instructions specify the exact claude.ai UI path current as of the release date - -- [x] **Unit 4: Cross-link existing distribution surfaces back to claude.ai** (in-repo README matrix shipped; external ClawHub/Gemini listing edits remain) - -**Goal:** Convert existing Claude Code plugin / OpenClaw / Gemini traffic into claude.ai installs. Cheaper than net-new acquisition. - -**Requirements:** R1 - -**Dependencies:** Unit 1, Unit 3 - -**Files:** -- Modify: `README.md` (install matrix - add claude.ai row prominently) -- Modify: `variants/open/SKILL.md` in the private repo if that governs OpenClaw listing copy -- Modify: `gemini-extension.json` if `description` or install hints exist there -- External: update the ClawHub listing page for `last30days-official` to mention claude.ai availability - -**Approach:** -- Every listing page a user currently lands on should have a one-line "Also available as a claude.ai Skill: [download]" link -- Use a consistent short-URL pattern so it's instantly recognizable across surfaces -- Do not require users to re-read each install guide - the cross-link is opportunistic, not blocking - -**Test scenarios:** -- Test expectation: none - documentation/external-listing updates - -**Verification:** -- Each of the 4 distribution surfaces (Claude Code plugin marketplace, OpenClaw ClawHub listing, Gemini extensions page, GitHub README) contains a visible claude.ai cross-link within 1 scroll of the page top - -- [ ] **Unit 5: Submit PRs to high-traffic Claude skill awesome-lists** - -**Goal:** Get listed in the 5 highest-traffic aggregators so third-party skill-discovery sites (skillsmp.com, mcpmarket.com, claudeskills.info) pick up the entry. - -**Requirements:** R3 - -**Dependencies:** Unit 1, Unit 2 (description should be tuned before first impression in these lists) - -**Files (external repos):** -- `ComposioHQ/awesome-claude-skills` - PR adding last30days to the relevant category -- `travisvn/awesome-claude-skills` -- `karanb192/awesome-claude-skills` -- `VoltAgent/awesome-agent-skills` -- `sickn33/antigravity-awesome-skills` - -**Approach:** -- One PR per list, in parallel -- Each PR: one-line entry matching the list's existing format; link to release asset (not repo root) -- If the list has a "research" or "data-gathering" category, use it; otherwise append to the most adjacent section -- Draft copy once, reuse across PRs - but match each list's voice and entry format -- Do not self-star or brigade - let the listing earn traction organically - -**Test scenarios:** -- Test expectation: none - external PRs, not code - -**Verification:** -- All 5 PRs opened on the same day (batch effort, reduces overhead) -- Entries include: skill name, one-sentence description matching tuned SKILL.md copy, release URL, source repo URL -- Track merge status over 14 days; abandon PRs that go stale after reasonable nudging - -- [ ] **Unit 6: Submit to Anthropic's official Plugin/Skills Marketplace** - -**Goal:** Get featured in Claude Code's "Discover" tab, the closest thing to a native claude.ai skill directory. - -**Requirements:** R2 - -**Dependencies:** Unit 1, Unit 2 - -**Files:** -- No repo changes; this is an external submission at `platform.claude.com/plugins/submit` - -**Approach:** -- Submit via Anthropic's form with: skill name, description (matches tuned SKILL.md), GitHub repo URL, release asset URL, demo video link (from Unit 7 if available) -- Expect quality/security review; Anthropic will likely ask for the ClawGuard-scanner-style audit items already surfaced in issue #231 - have responses ready -- Do not wait for acceptance before shipping other levers - -**Test scenarios:** -- Test expectation: none - external submission - -**Verification:** -- Submission confirmation received -- Track review status weekly; iterate on feedback if any - -- [ ] **Unit 7: Record a 15-60 second demo GIF or screen recording** - -**Goal:** Produce the visual asset that every amplification channel needs - launch tweet, Neuron pitch, README hero, release notes. - -**Requirements:** R6 - -**Dependencies:** Unit 2 (want the tuned description on-screen), Unit 3 (want the updated install flow) - -**Files:** -- Create: `assets/claudeai-demo.gif` (or `.mp4` if GIF is too large) -- Modify: `README.md` to embed the GIF - -**Approach:** -- Two possible framings: - 1. "Upload + use" flow: 15 seconds showing Upload dialog -> skill appears -> sample query -> result - 2. "One query" flow: 15-30 seconds of a real research query running end-to-end with actual output -- Pick framing 2 for outside-audience amplification (tweet, Neuron); framing 1 for the README -- Record at 1x speed (speeding up feels fake); edit to =60 seconds -- Export as optimized GIF or H.264 MP4 =5MB - -**Test scenarios:** -- Test expectation: none - media asset - -**Verification:** -- Asset loads cleanly in GitHub README -- Asset uploads cleanly to X (under their video length/size caps) -- Matt watches it fresh and the "oh wow" moment is unambiguous in the first 5 seconds - -- [ ] **Unit 8: Pitch The Neuron "AI Skill of the Day"** - -**Goal:** One high-leverage newsletter placement that historically drives the biggest external install spike for Claude skills. - -**Requirements:** R6 - -**Dependencies:** Unit 1, Unit 7 - -**Approach:** -- Identify The Neuron editor contact (newsletter footer, X DMs, their `skilloftheday@` alias if published) -- Pitch with: 3-sentence hook, demo video link, release URL, 3 example queries that show breadth -- Angle: "researcher skill that queries 12+ social sources in one shot" - novelty vs. their typical dev-tool coverage -- Offer exclusive timing if they want (publish first, then we tweet) -- Do not follow up more than twice - -**Test scenarios:** -- Test expectation: none - external pitch - -**Verification:** -- Pitch sent with all assets linked -- Track whether the issue ships within 14 days; if not, reuse the materials for other newsletters - -- [ ] **Unit 9: Launch tweet + recurring news-cycle posts** - -**Goal:** Seed social discovery and establish a weekly cadence so the skill stays top-of-mind. - -**Requirements:** R6 - -**Dependencies:** Unit 1, Unit 7 - -**Approach:** -- Launch tweet: demo GIF + 1-sentence description + install link. Post to X, cross-post to r/ClaudeAI and r/singularity same day. -- Do not tag handles reflexively - research each target account's culture first -- Weekly recurring pattern: pick a news moment (earnings, launch, election, cultural event), run `last30days` on it, screenshot the output, post. Low-effort, repeatable, compounds. -- Track: likes, impressions, link-click referrer traffic to the release page - -**Test scenarios:** -- Test expectation: none - social posts - -**Verification:** -- Launch tweet live with demo GIF -- At least one follow-up news-cycle post within 7 days -- Referrer traffic spike visible in GitHub traffic dashboard - -- [ ] **Unit 10: Adoption telemetry and feedback loop** - -**Goal:** Learn which levers work so we double down on wins and cut losses. Current blind spot: no visibility into claude.ai install counts. - -**Requirements:** R7 - -**Dependencies:** Unit 1 - -**Approach:** -- Baseline metrics (capture on Unit 1 ship day): - - GitHub stars - - Clones/day - - Traffic referrers - - Release-asset download count (GitHub exposes this on the Release page) -- Weekly review during the first 6 weeks of: - - Release download deltas - - Star velocity - - Referrer sources (identifies which aggregator/newsletter/tweet drove traffic) - - New GitHub issues that mention claude.ai specifically -- No dedicated analytics infrastructure - use what GitHub provides + manual referrer spot-checks -- Publish a "what worked / what didn't" retro after 6 weeks in `docs/solutions/` so the next launch compounds - -**Test scenarios:** -- Test expectation: none - observability - -**Verification:** -- Baseline metrics captured in a `docs/solutions/YYYY-MM-DD-*.md` note -- Weekly log of download/star/referrer deltas maintained -- Retro written at week 6 with concrete learnings for the next release - -## System-Wide Impact - -- **Interaction graph:** Touches GitHub (release, CI), external aggregators (PRs), Anthropic marketplace (submission), X/Reddit/newsletter (social), ClawHub/Gemini listings (cross-links). No runtime code changes. -- **State lifecycle risks:** Minimal. The main risk is inconsistent cross-linking (some surfaces mention claude.ai, others don't) - Unit 4 treats this as a coordinated sweep, not per-surface creep. -- **API surface parity:** None - no API changes. -- **Integration coverage:** The critical integration is trigger-selection behavior (Unit 2). Manual verification across web / Claude Code / OpenClaw is the gate. -- **Unchanged invariants:** Runtime pipeline, existing install paths (Claude Code plugin / OpenClaw / Gemini) all stay working. Zero-config first-run for default sources remains intact. - -## Risks and Dependencies - -| Risk | Mitigation | -|------|------------| -| Anthropic marketplace rejects the submission on security/quality grounds | Run `scripts/build-skill.sh` output through ClawGuard or equivalent scanner pre-submission; address #231 findings if real | -| Awesome-list maintainers reject or ignore PRs | Submit to 5 lists in parallel; any 2 acceptances are enough; do not brigade | -| The Neuron pitch is ignored | Treat as upside, not critical path; reuse materials for other newsletters (Ben's Bites, TLDR, Superhuman AI) | -| Tuned description causes false-positive skill selection on unrelated prompts | Manual prompt-testing in Unit 2; be willing to walk back if Claude over-invokes the skill | -| A new Anthropic marketplace or directory launches mid-plan and changes the landscape | The research-tracking cadence in Unit 10 catches this within a week; plan can adapt | -| Launch tweet flops / no organic pickup | Weekly news-cycle cadence (Unit 9) is the compounding play, not the launch moment | -| Cross-repo cross-links in Unit 4 go stale when listings move | Use canonical GitHub Release URL (deterministic) as the link target everywhere | - -## Documentation / Operational Notes - -- README gets a hero section update in Unit 3 -- CHANGELOG gets a v3.0.1 release-notes entry (already shipped in plan 001) -- A `docs/solutions/` retrospective note ships after the 6-week observation window (Unit 10) -- No runbook needed - distribution work is one-time-per-release - -## Sources and References - -- Research pass by repo-research-analyst on 2026-04-14 - [findings](https://github.com/anthropics/skills) -- [Anthropic Plugin/Skills Marketplace submissions](https://platform.claude.com/plugins/submit) -- [anthropics/skills](https://github.com/anthropics/skills) - 87k stars, canonical repo -- [SkillsMP](https://skillsmp.com), [claudeskills.info](https://claudeskills.info), [mcpmarket.com/tools/skills](https://mcpmarket.com/tools/skills) - aggregators -- [ComposioHQ/awesome-claude-skills](https://github.com/ComposioHQ/awesome-claude-skills) -- [sickn33/antigravity-awesome-skills](https://github.com/sickn33/antigravity-awesome-skills) -- [The Neuron Skill of the Day digest](https://www.theneuron.ai/explainer-articles/the-neurons-ai-skill-of-the-day-digest-april-2026-week-1/) -- Completed prerequisite: `docs/plans/2026-04-14-001-fix-skill-upload-200-file-limit-plan.md` (packaging fix) -- Related code: `SKILL.md` (frontmatter), `README.md`, `scripts/build-skill.sh`, `.github/workflows/` -- Install-count reference points from aggregators: self-improving-agent 357k, frontend-design 277k, skill-vetter 190k, github 148k, proactive-agent 135k