[Discuss] Mirror .agents to Drupal-AI/ai-skills on stable tag releases
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3585202. -->
Reported by: [marcus_johansson](https://www.drupal.org/user/385947)
>>>
<p>[Tracker]<br>
<strong>Update Summary: </strong>[One-line status update for stakeholders]<br>
<strong>Short Description: </strong>On every stable-version tag on drupal.org, mirror the .agents directory to the Drupal-AI/ai-skills GitHub repo under the matching version branch/tag.<br>
<strong>Check-in Date: </strong>MM/DD/YYYY<br>
[/Tracker]</p>
<h3 id="summary-problem-motivation">Problem/Motivation</h3>
<p>The <code>.agents</code> directory in the ai module ships agent skill files that are useful outside the Drupal context (the generic skill format is picked up by Claude Code, Copilot CLI, Gemini CLI, etc., independent of Drupal). Today the only way to consume those skills is to clone the entire ai module repo. That's heavy for agent-tooling users and means there is no canonical "just the skills" artifact they can subscribe to.</p>
<p>We want a parallel GitHub repo at <code>Drupal-AI/ai-skills</code> that mirrors the contents of <code>.agents</code> from a tagged stable release on drupal.org. Agent tooling users can then point at that repo without pulling in any Drupal code.</p>
<p><strong>Distribution target: skills.sh.</strong> <code>skills.sh</code> (run by Vercel) is emerging as the de-facto directory where developers find agent skills. It carries a leaderboard (ranked by install counts, with trending and hot filters) that drives discovery, and ships a generic CLI that works across 15+ agent harnesses/coding tools (Claude Code, Cursor, GitHub Copilot, Cline, VSCode, and more). That CLI treats any owner/repo on GitHub, GitLab, git URL, or local path as an installable skill source - so publishing <code>Drupal-AI/ai-skills</code> on GitHub is what makes our skills show up in the directory and installable with a single standard command, without users having to clone the ai module. This is where the ecosystem is converging; we want to meet users there rather than invent a Drupal-specific distribution channel.</p>
<p><strong>Removal is as important as install - context hygiene.</strong> Every skill loaded into an agent's context has a token cost and raises the chance of spurious matches. Users <em>must</em> be able to cleanly remove a Drupal skill they no longer need, as easily as they added it. Any documentation we publish needs to cover both <code>npx skills add</code> and <code>npx skills remove</code> as equal first-class commands, with a worked example for each. Advertising only the install path encourages users to accumulate unused skill context over time, which degrades their agent's behaviour.</p>
<p>The mirror should happen on tag events only, and only for "pure" semver tags (optionally with an <code>-rc.N</code> suffix). Tags with <code>-alpha</code>, <code>-beta</code>, <code>-dev</code>, or similar pre-release qualifiers are not considered stable enough for this mirror.</p>
<p>The job should also be a no-op when <code>.agents</code> does not exist on the tagged commit (older versions, or branches where the directory has not been added yet), so running it against legacy tags does not fail CI.</p>
<h3 id="summary-proposed-resolution">Proposed resolution</h3>
<ul>
<li>Discuss should we do it - then scope the following</li>
<li>Add a new shell script at <code>scripts/mirror-agents-to-github.sh</code> (or similar) that performs the mirror. Keeping it in its own file means <code>.gitlab-ci.yml</code> stays thin and the script can be linted and tested separately.</li>
<li>The script should: (1) verify the current ref is a pure semver tag - regex along the lines of <code>^\d+\.\d+\.\d+(-rc\.\d+)?$</code>; exit 0 otherwise so the job is a clean no-op. (2) verify <code>.agents/</code> exists in the current checkout; exit 0 otherwise. (3) clone the <code>Drupal-AI/ai-skills</code> GitHub repo using the token. (4) create or check out a branch/tag matching the semver. (5) replace the destination contents with the current <code>.agents/*</code> contents. (6) commit with a message referencing the tag and the source commit sha. (7) push the commit and the tag.</li>
<li>Add a <code>mirror-agents</code> job in <code>.gitlab-ci.yml</code> that runs only on tag events (<code>rules: - if: $CI_COMMIT_TAG</code>) and invokes the script.</li>
<li>Use a GitHub fine-grained personal access token (or deploy key) stored as a protected, masked CI/CD variable (e.g. <code>GITHUB_AI_SKILLS_TOKEN</code>). Scope it narrowly to <code>contents: write</code> on the single <code>Drupal-AI/ai-skills</code> repo. Document where the token lives and who can rotate it.</li>
<li>Decide with the maintainers how versioning maps: should each stable tag push a matching annotated tag to the GitHub repo, a long-lived branch per minor (e.g. <code>1.4.x</code>), or both? Propose: annotated tag on every run, plus a <code>main</code> branch fast-forwarded to the latest non-rc stable tag.</li>
<li>Add a job-level concurrency/retry guard so two near-simultaneous tag pushes do not race.</li>
<li>Document the full mechanism under <code>docs/developers/</code> (new page, e.g. <code>agents_skills_mirror.md</code>) covering: what the mirror does, which tags trigger it, how the token is configured, how to bootstrap the GitHub repo if it does not yet exist, and the end-user install/remove workflow through skills.sh.</li>
<li>In the end-user-facing docs, give the exact commands as a pair: <code>npx skills add Drupal-AI/ai-skills</code> to install and <code>npx skills remove Drupal-AI/ai-skills</code> (or the specific skill name) to uninstall. Mention that the CLI also supports <code>list</code>, <code>update</code>, and <code>find</code> so users can manage Drupal skills alongside their other installed skills. Frame removal as a routine hygiene action, not an afterthought.</li>
<li>Investigate whether skills.sh indexes the repo automatically or if we need to submit <code>Drupal-AI/ai-skills</code> to it. If submission is required, include it as a one-off action item when the repo is bootstrapped.</li>
<li>Add an explicit operator note in the docs: <strong>whenever the latest stable minor changes on drupal.org, the <code>main</code> branch on the GitHub mirror must be re-pointed at the new stable</strong>. Decide whether this is automated by the same script (preferred, as part of the "fast-forward main to latest non-rc stable" step) or a manual checklist item. Capture whichever we pick in the docs.</li>
<li>Consider whether the mirror should also publish a short README at the root of the GitHub repo describing what it is, how to use the skills files, and linking back to the source ai module - committed once as part of repo bootstrap and left alone after that, so the mirror does not stomp on it.</li>
</ul>
<p>Open questions:</p>
<ul>
<li>Fine-grained PAT vs GitHub App vs deploy key? A GitHub App is the most rotatable but adds setup cost; a fine-grained PAT is simplest.</li>
<li>Should the script delete files in the GitHub repo that no longer exist in <code>.agents</code>, or only additively sync? Preference: full mirror (deletions propagate) so the GitHub repo is always a faithful snapshot.</li>
<li>Do we want the mirror job to block the release pipeline if it fails, or warn only? Release pipelines usually prefer non-blocking, with monitoring.</li>
<li>skills.sh documents that the CLI also accepts GitLab URLs as a source. Would pointing users directly at the drupal.org GitLab be viable and let us skip the GitHub mirror entirely? Downside: drupal.org GitLab is not where most agent-tool users already look, and the leaderboard lives on skills.sh which pulls from public repos - a canonical GitHub repo is still the path of least friction for discovery. Likely answer: still mirror to GitHub, treat GitLab source support as a fallback for advanced users.</li>
</ul>
<h3 id="summary-ai-usage">AI usage (if applicable)</h3>
<p>[x] AI Assisted Issue<br>
This issue was generated with AI assistance, but was reviewed and refined by the creator.</p>
<p>[ ] AI Assisted Code</p>
<p>[ ] AI Generated Code</p>
<p>[ ] Vibe Coded</p>
<p>- <strong>This issue was created with the help of AI</strong></p>
issue