Compare commits
13
Commits
497fbabbbd
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59c4633723 | ||
|
|
2ff7f3c1e8 | ||
|
|
8467e584dd | ||
|
|
ebda8c7a05 | ||
|
|
eeff00b5e7 | ||
|
|
a5f907e9cf | ||
|
|
8400f41419 | ||
|
|
f25f2e8abc | ||
|
|
9b0c76a95c | ||
|
|
63314a0284 | ||
|
|
625ae5f56f | ||
|
|
4b1b3c3a19 | ||
|
|
ce2a82d1a8 |
@@ -8,6 +8,10 @@
|
|||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "caveman",
|
"name": "caveman",
|
||||||
|
"description": "Ultra-compressed communication mode from JuliusBrussee/caveman \u2014 cuts output tokens while keeping full technical accuracy. Installed straight from the upstream repo, not vendored here.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"source": "github",
|
"source": "github",
|
||||||
"repo": "JuliusBrussee/caveman"
|
"repo": "JuliusBrussee/caveman"
|
||||||
@@ -15,30 +19,77 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "core-essentials",
|
"name": "core-essentials",
|
||||||
|
"description": "Core cross-tool utilities, including delegation to the Antigravity CLI (agy) for grounded research and large multi-file audits.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/core-essentials"
|
"source": "./dist/claude-code/core-essentials"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "date-time",
|
"name": "date-time",
|
||||||
|
"description": "Retrieves the exact current date and time for time-sensitive queries, scheduling, duration calculations, and validating chronological context.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/date-time"
|
"source": "./dist/claude-code/date-time"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "docs-sync-audit",
|
"name": "docs-sync-audit",
|
||||||
|
"description": "Analyzes repository delta since the last documentation update and synchronizes the Single Source of Truth (docs/, wiki, or README) with the current codebase state.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/docs-sync-audit"
|
"source": "./dist/claude-code/docs-sync-audit"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "git-publish-workflow",
|
"name": "git-publish-workflow",
|
||||||
|
"description": "Automates branching, conventional commits, testing, and PR creation for uncommitted or staged work. Handles both independent and stacked PRs.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/git-publish-workflow"
|
"source": "./dist/claude-code/git-publish-workflow"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "gitea-mcp",
|
"name": "gitea-mcp",
|
||||||
|
"description": "Connects Claude Code/agy to a Gitea instance via the official gitea-mcp server, authenticated with GITEA_HOST/GITEA_ACCESS_TOKEN you set locally.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/gitea-mcp"
|
"source": "./dist/claude-code/gitea-mcp"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "github-mcp",
|
"name": "github-mcp",
|
||||||
|
"description": "Connects Claude Code/agy to GitHub via the official MCP server, authenticated with a GITHUB_PERSONAL_ACCESS_TOKEN you set locally.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/github-mcp"
|
"source": "./dist/claude-code/github-mcp"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "mattpocock-skills",
|
||||||
|
"description": "Matt Pocock's agent skills for real engineering from mattpocock/skills \u2014 grilling, spec/ticket flows, TDD, code review, domain modelling and more. Installed straight from the upstream repo, not vendored here.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"source": "github",
|
||||||
|
"repo": "mattpocock/skills"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mirror-it",
|
||||||
|
"description": "Configures a Gitea repository to automatically push-mirror its contents to GitHub using the tea CLI and jq.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
|
"source": "./dist/claude-code/mirror-it"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "ponytail",
|
"name": "ponytail",
|
||||||
|
"description": "Lazy senior dev mode from DietrichGebert/ponytail \u2014 forces the simplest, shortest solution that actually works (YAGNI, stdlib first, no unrequested abstractions). Installed straight from the upstream repo, not vendored here.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": {
|
"source": {
|
||||||
"source": "github",
|
"source": "github",
|
||||||
"repo": "DietrichGebert/ponytail"
|
"repo": "DietrichGebert/ponytail"
|
||||||
@@ -46,22 +97,39 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "readme-sync-audit",
|
"name": "readme-sync-audit",
|
||||||
|
"description": "Analyzes repository delta since the last documentation update and synchronizes the README.md with the current codebase state.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/readme-sync-audit"
|
"source": "./dist/claude-code/readme-sync-audit"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ship-it",
|
"name": "ship-it",
|
||||||
|
"description": "Runs a comprehensive pre-flight audit, syncs the README, and publishes the changes to a new PR.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/ship-it"
|
"source": "./dist/claude-code/ship-it"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "systematic-enumeration",
|
"name": "systematic-enumeration",
|
||||||
|
"description": "Forces element-by-element verification for finite sets to prevent counting errors.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/systematic-enumeration"
|
"source": "./dist/claude-code/systematic-enumeration"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "technical-devlog-scribe",
|
"name": "technical-devlog-scribe",
|
||||||
|
"description": "Generates a highly structured, objective technical summary of a development session.",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
},
|
||||||
"source": "./dist/claude-code/technical-devlog-scribe"
|
"source": "./dist/claude-code/technical-devlog-scribe"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "rootiest-ai-all",
|
"name": "rootiest-ai-all",
|
||||||
|
"description": "Reusable AI skills for Claude Code and Antigravity CLI (all skills)",
|
||||||
"source": "./dist/claude-code/rootiest-ai-all"
|
"source": "./dist/claude-code/rootiest-ai-all"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -125,3 +125,6 @@ dist-private/
|
|||||||
# ─────────────────────────── Python ──────────────────────────
|
# ─────────────────────────── Python ──────────────────────────
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
|
# ───────────────────────── Environment ──────────────────────
|
||||||
|
.env*
|
||||||
|
|||||||
@@ -18,11 +18,13 @@ from one source tree and published as a native marketplace for both tools.
|
|||||||
- [date-time](#date-time)
|
- [date-time](#date-time)
|
||||||
- [technical-devlog-scribe](#technical-devlog-scribe)
|
- [technical-devlog-scribe](#technical-devlog-scribe)
|
||||||
- [ship-it](#ship-it)
|
- [ship-it](#ship-it)
|
||||||
|
- [mirror-it](#mirror-it)
|
||||||
- [core-essentials](#core-essentials)
|
- [core-essentials](#core-essentials)
|
||||||
- [github-mcp](#github-mcp)
|
- [github-mcp](#github-mcp)
|
||||||
- [gitea-mcp](#gitea-mcp)
|
- [gitea-mcp](#gitea-mcp)
|
||||||
- [caveman](#caveman)
|
- [caveman](#caveman)
|
||||||
- [ponytail](#ponytail)
|
- [ponytail](#ponytail)
|
||||||
|
- [mattpocock-skills](#mattpocock-skills)
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
- [Claude Code](#claude-code)
|
- [Claude Code](#claude-code)
|
||||||
- [Antigravity CLI (agy)](#antigravity-cli-agy)
|
- [Antigravity CLI (agy)](#antigravity-cli-agy)
|
||||||
@@ -39,95 +41,165 @@ from one source tree and published as a native marketplace for both tools.
|
|||||||
|
|
||||||
### `systematic-enumeration`
|
### `systematic-enumeration`
|
||||||
|
|
||||||
**Purpose:** Eliminate counting and membership errors caused by the model's tendency toward holistic pattern recognition.
|
**Purpose:** Eliminate counting and membership errors caused by the model's
|
||||||
|
tendency toward holistic pattern recognition.
|
||||||
|
|
||||||
When invoked, the AI is required to work through three explicit phases:
|
When invoked, the AI is required to work through three explicit phases:
|
||||||
|
|
||||||
1. **Set Definition** — enumerate every member of the finite set before any analysis begins.
|
1. **Set Definition** — enumerate every member of the finite set before any
|
||||||
2. **Atomic Element Testing** — test each item individually, producing a `[Item] → [Logic] → [Boolean]` record for every element. For character-level checks, the string is split into individual characters to bypass tokenization bias.
|
analysis begins.
|
||||||
3. **Reduction & Summation** — aggregate results and self-verify that the number of items tested exactly matches the set size; if there is a mismatch, Phase 2 restarts.
|
2. **Atomic Element Testing** — test each item individually, producing a
|
||||||
|
`[Item] → [Logic] → [Boolean]` record for every element. For
|
||||||
|
character-level checks, the string is split into individual characters to
|
||||||
|
bypass tokenization bias.
|
||||||
|
3. **Reduction & Summation** — aggregate results and self-verify that the number
|
||||||
|
of items tested exactly matches the set size; if there is a mismatch, Phase 2
|
||||||
|
restarts.
|
||||||
|
|
||||||
**Use when:** counting characters in a string, verifying a property across a list of files or variables, or any membership test where a false negative carries real cost.
|
**Use when:** counting characters in a string, verifying a property across a
|
||||||
|
list of files or variables, or any membership test where a false negative
|
||||||
|
carries real cost.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `git-publish-workflow`
|
### `git-publish-workflow`
|
||||||
|
|
||||||
**Purpose:** Automate the full lifecycle from uncommitted local work to an open Pull Request, with built-in quality gates.
|
**Purpose:** Automate the full lifecycle from uncommitted local work to an open
|
||||||
|
Pull Request, with built-in quality gates.
|
||||||
|
|
||||||
The workflow runs three phases:
|
The workflow runs three phases:
|
||||||
|
|
||||||
1. **Scope Determination** — if staged changes exist, operate only on those; otherwise operate on all modified/untracked files.
|
1. **Scope Determination** — if staged changes exist, operate only on those;
|
||||||
2. **Safe-Commit Sequence** — generate a `kebab-case` branch name, compose a [Conventional Commits](https://www.conventionalcommits.org/) message, then run the project's primary test/lint/build command. If verification fails, the sequence stops — nothing is pushed.
|
otherwise operate on all modified/untracked files.
|
||||||
3. **Remote Integration** — push the branch, open a PR against the default branch, and populate the description with a "Why/What" summary and a manual verification checklist (`- [ ]` items).
|
2. **Safe-Commit Sequence** — generate a `kebab-case` branch name, compose a
|
||||||
|
[Conventional Commits](https://www.conventionalcommits.org/) message, then
|
||||||
|
run the project's primary test/lint/build command. If verification fails, the
|
||||||
|
sequence stops — nothing is pushed.
|
||||||
|
3. **Remote Integration** — push the branch, open a PR against the default
|
||||||
|
branch, and populate the description with a "Why/What" summary and a manual
|
||||||
|
verification checklist (`- [ ]` items).
|
||||||
|
|
||||||
**Use when:** you say "Ship this," "Make a PR," or invoke `/git-publish-workflow`.
|
**Use when:** you say "Ship this," "Make a PR," or invoke
|
||||||
|
`/git-publish-workflow`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `readme-sync-audit`
|
### `readme-sync-audit`
|
||||||
|
|
||||||
**Purpose:** Keep `README.md` accurate by programmatically aligning it with the current state of the codebase.
|
**Purpose:** Keep `README.md` accurate by programmatically aligning it with the
|
||||||
|
current state of the codebase.
|
||||||
|
|
||||||
Three-phase execution:
|
Three-phase execution:
|
||||||
|
|
||||||
1. **Delta Analysis** — locate the last commit that touched `README.md`, diff all code changes from that point to `HEAD`, and extract undocumented environment variables, CLI flags, or API changes.
|
1. **Delta Analysis** — locate the last commit that touched `README.md`, diff
|
||||||
2. **Pruning & Update Audit** — remove stale setup steps or "Coming Soon" notes, correct version numbers and file paths, and synthesize documentation for newly discovered features.
|
all code changes from that point to `HEAD`, and extract undocumented
|
||||||
3. **Structural Integrity Check** — verify that Quick Start commands still work, all config keys are listed, and code snippets match the current API.
|
environment variables, CLI flags, or API changes.
|
||||||
|
2. **Pruning & Update Audit** — remove stale setup steps or "Coming Soon" notes,
|
||||||
|
correct version numbers and file paths, and synthesize documentation for
|
||||||
|
newly discovered features.
|
||||||
|
3. **Structural Integrity Check** — verify that Quick Start commands still work,
|
||||||
|
all config keys are listed, and code snippets match the current API.
|
||||||
|
|
||||||
**Use when:** you say "Update the docs," "Sync the README," or invoke `/readme-sync-audit`.
|
**Use when:** you say "Update the docs," "Sync the README," or invoke
|
||||||
|
`/readme-sync-audit`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `docs-sync-audit`
|
### `docs-sync-audit`
|
||||||
|
|
||||||
**Purpose:** Keep documentation accurate by aligning the project's Single Source of Truth (SSoT) with the current state of the codebase.
|
**Purpose:** Keep documentation accurate by aligning the project's Single
|
||||||
|
Source of Truth (SSoT) with the current state of the codebase.
|
||||||
|
|
||||||
Unlike `readme-sync-audit`, this skill first discovers the documentation root. If a dedicated `docs/`, `wiki/`, or site config (e.g. `mkdocs.yml`) exists, it is treated as the SSoT and receives the detailed updates; the `README.md` is then kept as a high-level landing page that links into it. If no docs directory exists, it falls back to `README.md` as the SSoT.
|
Unlike `readme-sync-audit`, this skill first discovers the documentation root.
|
||||||
|
If a dedicated `docs/`, `wiki/`, or site config (e.g. `mkdocs.yml`) exists, it is
|
||||||
|
treated as the SSoT and receives the detailed updates; the `README.md` is then
|
||||||
|
kept as a high-level landing page that links into it. If no docs directory
|
||||||
|
exists, it falls back to `README.md` as the SSoT.
|
||||||
|
|
||||||
Three-phase execution:
|
Three-phase execution:
|
||||||
|
|
||||||
1. **Delta Analysis** — locate the last commit that touched the SSoT, diff all code changes to `HEAD`, and extract undocumented environment variables, CLI flags, or API changes.
|
1. **Delta Analysis** — locate the last commit that touched the SSoT, diff all
|
||||||
2. **Pruning & Update Audit** — route detailed changes to the correct files, remove stale steps, correct versions and paths, and synthesize docs for new features.
|
code changes to `HEAD`, and extract undocumented environment variables, CLI
|
||||||
3. **Structural Integrity Check** — verify Quick Start commands, configuration keys, and usage examples still match the implementation.
|
flags, or API changes.
|
||||||
|
2. **Pruning & Update Audit** — route detailed changes to the correct files,
|
||||||
|
remove stale steps, correct versions and paths, and synthesize docs for new
|
||||||
|
features.
|
||||||
|
3. **Structural Integrity Check** — verify Quick Start commands, configuration
|
||||||
|
keys, and usage examples still match the implementation.
|
||||||
|
|
||||||
**Use when:** you say "Update the docs," "Sync the wiki," or invoke `/docs-sync-audit`.
|
**Use when:** you say "Update the docs," "Sync the wiki," or invoke
|
||||||
|
`/docs-sync-audit`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `date-time`
|
### `date-time`
|
||||||
|
|
||||||
**Purpose:** Retrieve the exact, real-time current date and time when a task depends on the present moment.
|
**Purpose:** Retrieve the exact, real-time current date and time when a task
|
||||||
|
depends on the present moment.
|
||||||
|
|
||||||
The skill runs the system `date` command rather than guessing, then uses the result for time-sensitive reasoning.
|
The skill runs the system `date` command rather than guessing, then uses the
|
||||||
|
result for time-sensitive reasoning.
|
||||||
|
|
||||||
**Use when:** the request asks for the current date/time, uses relative expressions ("today", "next week", "recently"), or needs an age, duration, countdown, or check of whether an event has already occurred.
|
**Use when:** the request asks for the current date/time, uses relative
|
||||||
|
expressions ("today", "next week", "recently"), or needs an age, duration,
|
||||||
|
countdown, or check of whether an event has already occurred.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `technical-devlog-scribe`
|
### `technical-devlog-scribe`
|
||||||
|
|
||||||
**Purpose:** Produce a dense, objective technical summary of a development session as a durable historical record optimized for future context loading.
|
**Purpose:** Produce a dense, objective technical summary of a development
|
||||||
|
session as a durable historical record optimized for future context loading.
|
||||||
|
|
||||||
The skill writes a structured Markdown file to `AGENTS/devlogs/<kebab-case-short-description>.md`, with YAML frontmatter (date, title, tags, status) followed by the session summary. It relies strictly on what happened in the session — no hallucinated external constraints — and avoids conversational filler.
|
The skill writes a structured Markdown file to
|
||||||
|
`AGENTS/devlogs/<kebab-case-short-description>.md`, with YAML frontmatter (date,
|
||||||
|
title, tags, status) followed by the session summary. It relies strictly on
|
||||||
|
what happened in the session — no hallucinated external constraints — and
|
||||||
|
avoids conversational filler.
|
||||||
|
|
||||||
**Use when:** you say "session wrap-up," "write a devlog," "done for the day," or want an auditable record of what changed and why.
|
**Use when:** you say "session wrap-up," "write a devlog," "done for the day,"
|
||||||
|
or want an auditable record of what changed and why.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### `ship-it`
|
### `ship-it`
|
||||||
|
|
||||||
**Purpose:** Run a comprehensive pre-flight audit and publish changes to a new PR in a single command.
|
**Purpose:** Run a comprehensive pre-flight audit and publish changes to a new
|
||||||
|
PR in a single command.
|
||||||
|
|
||||||
Two sequential phases — Phase 2 is blocked until Phase 1 succeeds:
|
Two sequential phases — Phase 2 is blocked until Phase 1 succeeds:
|
||||||
|
|
||||||
1. **Documentation Sync & Code Audit** — acts as `/docs-sync-audit`: scans all file changes since the last documentation edit, updates the docs/README to match the current codebase, and audits code files for syntax errors or regressions. **Halts the entire workflow** if any breaking issue is found.
|
1. **Documentation Sync & Code Audit** — acts as `/docs-sync-audit`: scans all
|
||||||
2. **Git Publish Workflow** — acts as `/git-publish-workflow`: creates a descriptively named branch, commits all pending changes (including the README updates from Phase 1), pushes to the remote, and opens a Pull Request against `main`.
|
file changes since the last documentation edit, updates the docs/README to
|
||||||
|
match the current codebase, and audits code files for syntax errors or
|
||||||
|
regressions. **Halts the entire workflow** if any breaking issue is found.
|
||||||
|
2. **Git Publish Workflow** — acts as `/git-publish-workflow`: creates a
|
||||||
|
descriptively named branch, commits all pending changes (including the
|
||||||
|
README updates from Phase 1), pushes to the remote, and opens a Pull Request
|
||||||
|
against `main`.
|
||||||
|
|
||||||
**Use when:** you say "Ship this," "Publish my changes," or invoke `/ship-it`.
|
**Use when:** you say "Ship this," "Publish my changes," or invoke `/ship-it`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `mirror-it`
|
||||||
|
|
||||||
|
**Purpose:** Register a Gitea push mirror so a repository's commits are
|
||||||
|
automatically forwarded to a corresponding GitHub repository.
|
||||||
|
|
||||||
|
Uses `tea api` against Gitea's `push_mirrors` endpoint, with credentials passed
|
||||||
|
as `remote_username`/`remote_password` fields — never embedded in the mirror
|
||||||
|
URL. Defaults to an `8h` sync interval with sync-on-commit enabled; both are
|
||||||
|
overridable per request, as is the destination repository name.
|
||||||
|
`GITHUB_USER`/`GITHUB_TOKEN` can come from the environment or, as a fallback, a
|
||||||
|
repo-root `.env` file.
|
||||||
|
|
||||||
|
**Use when:** you say "Mirror this repository to GitHub," or invoke
|
||||||
|
`/mirror-it`. Only relevant for repositories hosted on Gitea — GitHub can't
|
||||||
|
push-mirror to itself.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### `core-essentials`
|
### `core-essentials`
|
||||||
|
|
||||||
**Purpose:** Cross-tool utilities that don't belong to a single workflow.
|
**Purpose:** Cross-tool utilities that don't belong to a single workflow.
|
||||||
@@ -187,6 +259,17 @@ installed the same external-source way as `caveman` above. Claude Code-only.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### `mattpocock-skills`
|
||||||
|
|
||||||
|
**Purpose:** Matt Pocock's agent skills for real engineering — grilling,
|
||||||
|
spec/ticket flows, TDD, code review, domain modelling and more.
|
||||||
|
|
||||||
|
Also third-party, from
|
||||||
|
[mattpocock/skills](https://github.com/mattpocock/skills), installed the
|
||||||
|
same external-source way as `caveman`/`ponytail` above. Claude Code-only.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
This repository is a native plugin marketplace for both tools — there is no
|
This repository is a native plugin marketplace for both tools — there is no
|
||||||
@@ -195,11 +278,26 @@ install script. Each plugin can be installed individually, or as one bundle
|
|||||||
|
|
||||||
### Claude Code
|
### Claude Code
|
||||||
|
|
||||||
|
From inside a Claude Code session:
|
||||||
|
|
||||||
```
|
```
|
||||||
/plugin marketplace add https://git.rootiest.dev/rootiest/rootiest-ai.git
|
/plugin marketplace add rootiest/rootiest-ai
|
||||||
/plugin install git-publish-workflow@rootiest-ai
|
/plugin install git-publish-workflow@rootiest-ai
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Or from a regular shell, before starting a session:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude plugin marketplace add rootiest/rootiest-ai
|
||||||
|
```
|
||||||
|
|
||||||
|
The `owner/repo` shorthand resolves against GitHub, so it works because
|
||||||
|
this repo is mirrored to
|
||||||
|
[github.com/rootiest/rootiest-ai](https://github.com/rootiest/rootiest-ai)
|
||||||
|
on every push to our canonical Gitea remote. If you're pointing at a fork
|
||||||
|
or a private mirror instead, use the full clone URL:
|
||||||
|
`/plugin marketplace add https://git.rootiest.dev/rootiest/rootiest-ai.git`.
|
||||||
|
|
||||||
Install everything at once:
|
Install everything at once:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"name": "mirror-it"
|
||||||
|
}
|
||||||
+133
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
name: mirror-it
|
||||||
|
description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`.
|
||||||
|
version: 1.1.0
|
||||||
|
user-invocable: true
|
||||||
|
author: Rootiest
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gitea to GitHub Push Mirror
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
Register a Gitea push mirror so a repository's commits are automatically forwarded to a
|
||||||
|
corresponding GitHub repository, via `tea api` against Gitea's `push_mirrors` endpoint.
|
||||||
|
|
||||||
|
## Trigger Conditions
|
||||||
|
Activate this skill ONLY when one of the following is met:
|
||||||
|
1. The user explicitly types the command `/mirror-it`.
|
||||||
|
2. The user makes a natural-language request to mirror the repository (e.g., "Mirror this
|
||||||
|
repository to GitHub", "Mirror this example-config repo...").
|
||||||
|
3. You confidently infer the user intends to mirror the current repository, AND have
|
||||||
|
verified that a GitHub repository does not already exist at the target address.
|
||||||
|
|
||||||
|
## Constraints & Relevance
|
||||||
|
- **Gitea only**: this skill is relevant ONLY for repositories hosted on a Gitea instance
|
||||||
|
(e.g., `git.rootiest.dev`). Do NOT trigger it for repositories natively hosted on GitHub —
|
||||||
|
GitHub does not support push-mirroring to itself.
|
||||||
|
- **Security**: never read, print, or otherwise expose the value of `$GITHUB_TOKEN` (whether it
|
||||||
|
comes from the environment or a `.env` file — see Prerequisites). Pass the variable reference
|
||||||
|
directly into shell commands so it is only ever expanded by the shell, never written out by you.
|
||||||
|
- **Shell environment**: the snippet below is POSIX-compatible (`var=$(command)`), since the
|
||||||
|
command executes through whatever shell the tool invokes it with (bash/zsh/sh) — never assume
|
||||||
|
Fish syntax is available. An exported variable (`set -gx` in Fish, `export` in bash/zsh) is
|
||||||
|
inherited by every child process regardless of which shell that child happens to run, so
|
||||||
|
variables from the user's interactive shell config are already present without any special
|
||||||
|
handling.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
- `tea` is installed and already authenticated against the target Gitea instance (`tea login list`).
|
||||||
|
- `jq` is installed.
|
||||||
|
- `$GITHUB_USER` and `$GITHUB_TOKEN` (a GitHub PAT with `repo` scope) are available before step 3
|
||||||
|
below — either already exported in the environment, or defined in a `.env` file at the
|
||||||
|
repository root (see step 1).
|
||||||
|
- Optionally, one of the following for the target-repo check/creation in step 4: the `gh` CLI
|
||||||
|
(authenticated — `gh auth status`), a GitHub MCP server, or plain `$GITHUB_TOKEN` used directly
|
||||||
|
against the GitHub REST API via `curl`. The first of these that's available is used; if none
|
||||||
|
are, step 4 degrades to a warning instead of blocking the skill.
|
||||||
|
|
||||||
|
## Defaults & Overrides
|
||||||
|
Unless the user says otherwise, assume:
|
||||||
|
- **Target name (`$TARGET_REPO`)**: the exact name of the current Gitea repository.
|
||||||
|
- **Interval (`$INTERVAL`)**: `"8h"`.
|
||||||
|
- **Sync on commit (`$SYNC_ON_COMMIT`)**: `true`.
|
||||||
|
|
||||||
|
*Example override:* "Mirror this example-config repo, but don't sync on commit and use the
|
||||||
|
name 'exmpl_cfg'" → `$TARGET_REPO` becomes `exmpl_cfg`, `$SYNC_ON_COMMIT` becomes `false`.
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
1. If `$GITHUB_USER` or `$GITHUB_TOKEN` is not already set, and a `.env` file exists at the
|
||||||
|
repository root, load it before doing anything else — without ever printing or `cat`-ing its
|
||||||
|
contents:
|
||||||
|
```sh
|
||||||
|
set -a; . ./.env; set +a
|
||||||
|
```
|
||||||
|
Variables already present in the environment take priority: only fall back to `.env` for
|
||||||
|
whichever of the two is still unset. If neither source provides both, stop and tell the user
|
||||||
|
what's missing.
|
||||||
|
2. Identify the current Gitea repository's owner (`$OWNER`) and name (`$SOURCE_REPO`).
|
||||||
|
3. Determine `$TARGET_REPO`, `$INTERVAL`, and `$SYNC_ON_COMMIT` from the defaults above,
|
||||||
|
applying any user overrides.
|
||||||
|
4. **Ensure the GitHub target repository exists.** GitHub, unlike Gitea, does not create a
|
||||||
|
repository on first push — if `$GITHUB_USER/$TARGET_REPO` doesn't exist yet, the mirror will
|
||||||
|
register successfully but every sync attempt will fail. Check for the repo and create it if
|
||||||
|
missing, using whichever of these is available (in order of preference):
|
||||||
|
|
||||||
|
- **`gh` CLI** (preferred if authenticated — `gh auth status`):
|
||||||
|
```sh
|
||||||
|
if ! gh repo view "$GITHUB_USER/$TARGET_REPO" >/dev/null 2>&1; then
|
||||||
|
gh repo create "$GITHUB_USER/$TARGET_REPO" --private --description "Push mirror of $OWNER/$SOURCE_REPO"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
Match visibility to the source repo where you can determine it (e.g. via `tea api
|
||||||
|
"repos/$OWNER/$SOURCE_REPO"` → `.private`); otherwise default to `--private` and mention the
|
||||||
|
choice when reporting the outcome.
|
||||||
|
- **GitHub MCP server**, if one is connected: use its repo-lookup tool to check for
|
||||||
|
`$GITHUB_USER/$TARGET_REPO`, and its repo-creation tool to create it (private by default) if
|
||||||
|
absent.
|
||||||
|
- **Plain REST API via `curl`**, using `$GITHUB_TOKEN` directly, if neither of the above is
|
||||||
|
available:
|
||||||
|
```sh
|
||||||
|
status=$(curl -s -o /dev/null -w '%{http_code}' \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
"https://api.github.com/repos/$GITHUB_USER/$TARGET_REPO")
|
||||||
|
if [ "$status" = "404" ]; then
|
||||||
|
curl -s -X POST \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
https://api.github.com/user/repos \
|
||||||
|
-d "$(jq -n --arg name "$TARGET_REPO" '{name: $name, private: true}')" \
|
||||||
|
>/dev/null
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
- **If none of these are available**, don't block on it — proceed to step 5, but warn the user
|
||||||
|
clearly that they must create `$GITHUB_USER/$TARGET_REPO` on GitHub themselves before the
|
||||||
|
mirror's first sync will succeed.
|
||||||
|
|
||||||
|
If a repo already exists at the target address, leave it as-is and continue — do not treat this
|
||||||
|
as an error.
|
||||||
|
|
||||||
|
5. Run the following snippet, substituting the values from steps 2–3. Credentials are passed as
|
||||||
|
separate `remote_username`/`remote_password` fields — never embedded in the mirror URL — per
|
||||||
|
Gitea's `CreatePushMirrorOption` schema.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# $OWNER / $SOURCE_REPO identify the local Gitea API endpoint.
|
||||||
|
# $TARGET_REPO is the destination repository name on GitHub.
|
||||||
|
# $INTERVAL and $SYNC_ON_COMMIT come from the Defaults & Overrides step above.
|
||||||
|
|
||||||
|
payload=$(jq -n \
|
||||||
|
--arg addr "https://github.com/$GITHUB_USER/$TARGET_REPO.git" \
|
||||||
|
--arg user "$GITHUB_USER" \
|
||||||
|
--arg pass "$GITHUB_TOKEN" \
|
||||||
|
--arg interval "$INTERVAL" \
|
||||||
|
--argjson sync $SYNC_ON_COMMIT \
|
||||||
|
'{remote_address: $addr, remote_username: $user, remote_password: $pass, interval: $interval, sync_on_commit: $sync}'
|
||||||
|
)
|
||||||
|
|
||||||
|
tea api --method POST --data "$payload" "repos/$OWNER/$SOURCE_REPO/push_mirrors"
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Report the outcome to the user, without echoing the request body, `.env` contents, or token —
|
||||||
|
including whether the GitHub repo already existed or was just created, and, if step 4 had no
|
||||||
|
capability to check/create it, a reminder that they need to create it manually.
|
||||||
+133
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
name: mirror-it
|
||||||
|
description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`.
|
||||||
|
version: 1.1.0
|
||||||
|
user-invocable: true
|
||||||
|
author: Rootiest
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gitea to GitHub Push Mirror
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
Register a Gitea push mirror so a repository's commits are automatically forwarded to a
|
||||||
|
corresponding GitHub repository, via `tea api` against Gitea's `push_mirrors` endpoint.
|
||||||
|
|
||||||
|
## Trigger Conditions
|
||||||
|
Activate this skill ONLY when one of the following is met:
|
||||||
|
1. The user explicitly types the command `/mirror-it`.
|
||||||
|
2. The user makes a natural-language request to mirror the repository (e.g., "Mirror this
|
||||||
|
repository to GitHub", "Mirror this example-config repo...").
|
||||||
|
3. You confidently infer the user intends to mirror the current repository, AND have
|
||||||
|
verified that a GitHub repository does not already exist at the target address.
|
||||||
|
|
||||||
|
## Constraints & Relevance
|
||||||
|
- **Gitea only**: this skill is relevant ONLY for repositories hosted on a Gitea instance
|
||||||
|
(e.g., `git.rootiest.dev`). Do NOT trigger it for repositories natively hosted on GitHub —
|
||||||
|
GitHub does not support push-mirroring to itself.
|
||||||
|
- **Security**: never read, print, or otherwise expose the value of `$GITHUB_TOKEN` (whether it
|
||||||
|
comes from the environment or a `.env` file — see Prerequisites). Pass the variable reference
|
||||||
|
directly into shell commands so it is only ever expanded by the shell, never written out by you.
|
||||||
|
- **Shell environment**: the snippet below is POSIX-compatible (`var=$(command)`), since the
|
||||||
|
command executes through whatever shell the tool invokes it with (bash/zsh/sh) — never assume
|
||||||
|
Fish syntax is available. An exported variable (`set -gx` in Fish, `export` in bash/zsh) is
|
||||||
|
inherited by every child process regardless of which shell that child happens to run, so
|
||||||
|
variables from the user's interactive shell config are already present without any special
|
||||||
|
handling.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
- `tea` is installed and already authenticated against the target Gitea instance (`tea login list`).
|
||||||
|
- `jq` is installed.
|
||||||
|
- `$GITHUB_USER` and `$GITHUB_TOKEN` (a GitHub PAT with `repo` scope) are available before step 3
|
||||||
|
below — either already exported in the environment, or defined in a `.env` file at the
|
||||||
|
repository root (see step 1).
|
||||||
|
- Optionally, one of the following for the target-repo check/creation in step 4: the `gh` CLI
|
||||||
|
(authenticated — `gh auth status`), a GitHub MCP server, or plain `$GITHUB_TOKEN` used directly
|
||||||
|
against the GitHub REST API via `curl`. The first of these that's available is used; if none
|
||||||
|
are, step 4 degrades to a warning instead of blocking the skill.
|
||||||
|
|
||||||
|
## Defaults & Overrides
|
||||||
|
Unless the user says otherwise, assume:
|
||||||
|
- **Target name (`$TARGET_REPO`)**: the exact name of the current Gitea repository.
|
||||||
|
- **Interval (`$INTERVAL`)**: `"8h"`.
|
||||||
|
- **Sync on commit (`$SYNC_ON_COMMIT`)**: `true`.
|
||||||
|
|
||||||
|
*Example override:* "Mirror this example-config repo, but don't sync on commit and use the
|
||||||
|
name 'exmpl_cfg'" → `$TARGET_REPO` becomes `exmpl_cfg`, `$SYNC_ON_COMMIT` becomes `false`.
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
1. If `$GITHUB_USER` or `$GITHUB_TOKEN` is not already set, and a `.env` file exists at the
|
||||||
|
repository root, load it before doing anything else — without ever printing or `cat`-ing its
|
||||||
|
contents:
|
||||||
|
```sh
|
||||||
|
set -a; . ./.env; set +a
|
||||||
|
```
|
||||||
|
Variables already present in the environment take priority: only fall back to `.env` for
|
||||||
|
whichever of the two is still unset. If neither source provides both, stop and tell the user
|
||||||
|
what's missing.
|
||||||
|
2. Identify the current Gitea repository's owner (`$OWNER`) and name (`$SOURCE_REPO`).
|
||||||
|
3. Determine `$TARGET_REPO`, `$INTERVAL`, and `$SYNC_ON_COMMIT` from the defaults above,
|
||||||
|
applying any user overrides.
|
||||||
|
4. **Ensure the GitHub target repository exists.** GitHub, unlike Gitea, does not create a
|
||||||
|
repository on first push — if `$GITHUB_USER/$TARGET_REPO` doesn't exist yet, the mirror will
|
||||||
|
register successfully but every sync attempt will fail. Check for the repo and create it if
|
||||||
|
missing, using whichever of these is available (in order of preference):
|
||||||
|
|
||||||
|
- **`gh` CLI** (preferred if authenticated — `gh auth status`):
|
||||||
|
```sh
|
||||||
|
if ! gh repo view "$GITHUB_USER/$TARGET_REPO" >/dev/null 2>&1; then
|
||||||
|
gh repo create "$GITHUB_USER/$TARGET_REPO" --private --description "Push mirror of $OWNER/$SOURCE_REPO"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
Match visibility to the source repo where you can determine it (e.g. via `tea api
|
||||||
|
"repos/$OWNER/$SOURCE_REPO"` → `.private`); otherwise default to `--private` and mention the
|
||||||
|
choice when reporting the outcome.
|
||||||
|
- **GitHub MCP server**, if one is connected: use its repo-lookup tool to check for
|
||||||
|
`$GITHUB_USER/$TARGET_REPO`, and its repo-creation tool to create it (private by default) if
|
||||||
|
absent.
|
||||||
|
- **Plain REST API via `curl`**, using `$GITHUB_TOKEN` directly, if neither of the above is
|
||||||
|
available:
|
||||||
|
```sh
|
||||||
|
status=$(curl -s -o /dev/null -w '%{http_code}' \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
"https://api.github.com/repos/$GITHUB_USER/$TARGET_REPO")
|
||||||
|
if [ "$status" = "404" ]; then
|
||||||
|
curl -s -X POST \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
https://api.github.com/user/repos \
|
||||||
|
-d "$(jq -n --arg name "$TARGET_REPO" '{name: $name, private: true}')" \
|
||||||
|
>/dev/null
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
- **If none of these are available**, don't block on it — proceed to step 5, but warn the user
|
||||||
|
clearly that they must create `$GITHUB_USER/$TARGET_REPO` on GitHub themselves before the
|
||||||
|
mirror's first sync will succeed.
|
||||||
|
|
||||||
|
If a repo already exists at the target address, leave it as-is and continue — do not treat this
|
||||||
|
as an error.
|
||||||
|
|
||||||
|
5. Run the following snippet, substituting the values from steps 2–3. Credentials are passed as
|
||||||
|
separate `remote_username`/`remote_password` fields — never embedded in the mirror URL — per
|
||||||
|
Gitea's `CreatePushMirrorOption` schema.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# $OWNER / $SOURCE_REPO identify the local Gitea API endpoint.
|
||||||
|
# $TARGET_REPO is the destination repository name on GitHub.
|
||||||
|
# $INTERVAL and $SYNC_ON_COMMIT come from the Defaults & Overrides step above.
|
||||||
|
|
||||||
|
payload=$(jq -n \
|
||||||
|
--arg addr "https://github.com/$GITHUB_USER/$TARGET_REPO.git" \
|
||||||
|
--arg user "$GITHUB_USER" \
|
||||||
|
--arg pass "$GITHUB_TOKEN" \
|
||||||
|
--arg interval "$INTERVAL" \
|
||||||
|
--argjson sync $SYNC_ON_COMMIT \
|
||||||
|
'{remote_address: $addr, remote_username: $user, remote_password: $pass, interval: $interval, sync_on_commit: $sync}'
|
||||||
|
)
|
||||||
|
|
||||||
|
tea api --method POST --data "$payload" "repos/$OWNER/$SOURCE_REPO/push_mirrors"
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Report the outcome to the user, without echoing the request body, `.env` contents, or token —
|
||||||
|
including whether the GitHub repo already existed or was just created, and, if step 4 had no
|
||||||
|
capability to check/create it, a reminder that they need to create it manually.
|
||||||
@@ -2,5 +2,7 @@
|
|||||||
"name": "core-essentials",
|
"name": "core-essentials",
|
||||||
"description": "Core cross-tool utilities, including delegation to the Antigravity CLI (agy) for grounded research and large multi-file audits.",
|
"description": "Core cross-tool utilities, including delegation to the Antigravity CLI (agy) for grounded research and large multi-file audits.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -2,5 +2,7 @@
|
|||||||
"name": "date-time",
|
"name": "date-time",
|
||||||
"description": "Retrieves the exact current date and time for time-sensitive queries, scheduling, duration calculations, and validating chronological context.",
|
"description": "Retrieves the exact current date and time for time-sensitive queries, scheduling, duration calculations, and validating chronological context.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,7 @@
|
|||||||
"name": "docs-sync-audit",
|
"name": "docs-sync-audit",
|
||||||
"description": "Analyzes repository delta since the last documentation update and synchronizes the Single Source of Truth (docs/, wiki, or README) with the current codebase state.",
|
"description": "Analyzes repository delta since the last documentation update and synchronizes the Single Source of Truth (docs/, wiki, or README) with the current codebase state.",
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,7 @@
|
|||||||
"name": "git-publish-workflow",
|
"name": "git-publish-workflow",
|
||||||
"description": "Automates branching, conventional commits, testing, and PR creation for uncommitted or staged work. Handles both independent and stacked PRs.",
|
"description": "Automates branching, conventional commits, testing, and PR creation for uncommitted or staged work. Handles both independent and stacked PRs.",
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -2,5 +2,7 @@
|
|||||||
"name": "gitea-mcp",
|
"name": "gitea-mcp",
|
||||||
"description": "Connects Claude Code/agy to a Gitea instance via the official gitea-mcp server, authenticated with GITEA_HOST/GITEA_ACCESS_TOKEN you set locally.",
|
"description": "Connects Claude Code/agy to a Gitea instance via the official gitea-mcp server, authenticated with GITEA_HOST/GITEA_ACCESS_TOKEN you set locally.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -2,5 +2,7 @@
|
|||||||
"name": "github-mcp",
|
"name": "github-mcp",
|
||||||
"description": "Connects Claude Code/agy to GitHub via the official MCP server, authenticated with a GITHUB_PERSONAL_ACCESS_TOKEN you set locally.",
|
"description": "Connects Claude Code/agy to GitHub via the official MCP server, authenticated with a GITHUB_PERSONAL_ACCESS_TOKEN you set locally.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "mirror-it",
|
||||||
|
"description": "Configures a Gitea repository to automatically push-mirror its contents to GitHub using the tea CLI and jq.",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
name: mirror-it
|
||||||
|
description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`.
|
||||||
|
version: 1.1.0
|
||||||
|
user-invocable: true
|
||||||
|
author: Rootiest
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gitea to GitHub Push Mirror
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
Register a Gitea push mirror so a repository's commits are automatically forwarded to a
|
||||||
|
corresponding GitHub repository, via `tea api` against Gitea's `push_mirrors` endpoint.
|
||||||
|
|
||||||
|
## Trigger Conditions
|
||||||
|
Activate this skill ONLY when one of the following is met:
|
||||||
|
1. The user explicitly types the command `/mirror-it`.
|
||||||
|
2. The user makes a natural-language request to mirror the repository (e.g., "Mirror this
|
||||||
|
repository to GitHub", "Mirror this example-config repo...").
|
||||||
|
3. You confidently infer the user intends to mirror the current repository, AND have
|
||||||
|
verified that a GitHub repository does not already exist at the target address.
|
||||||
|
|
||||||
|
## Constraints & Relevance
|
||||||
|
- **Gitea only**: this skill is relevant ONLY for repositories hosted on a Gitea instance
|
||||||
|
(e.g., `git.rootiest.dev`). Do NOT trigger it for repositories natively hosted on GitHub —
|
||||||
|
GitHub does not support push-mirroring to itself.
|
||||||
|
- **Security**: never read, print, or otherwise expose the value of `$GITHUB_TOKEN` (whether it
|
||||||
|
comes from the environment or a `.env` file — see Prerequisites). Pass the variable reference
|
||||||
|
directly into shell commands so it is only ever expanded by the shell, never written out by you.
|
||||||
|
- **Shell environment**: the snippet below is POSIX-compatible (`var=$(command)`), since the
|
||||||
|
command executes through whatever shell the tool invokes it with (bash/zsh/sh) — never assume
|
||||||
|
Fish syntax is available. An exported variable (`set -gx` in Fish, `export` in bash/zsh) is
|
||||||
|
inherited by every child process regardless of which shell that child happens to run, so
|
||||||
|
variables from the user's interactive shell config are already present without any special
|
||||||
|
handling.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
- `tea` is installed and already authenticated against the target Gitea instance (`tea login list`).
|
||||||
|
- `jq` is installed.
|
||||||
|
- `$GITHUB_USER` and `$GITHUB_TOKEN` (a GitHub PAT with `repo` scope) are available before step 3
|
||||||
|
below — either already exported in the environment, or defined in a `.env` file at the
|
||||||
|
repository root (see step 1).
|
||||||
|
- Optionally, one of the following for the target-repo check/creation in step 4: the `gh` CLI
|
||||||
|
(authenticated — `gh auth status`), a GitHub MCP server, or plain `$GITHUB_TOKEN` used directly
|
||||||
|
against the GitHub REST API via `curl`. The first of these that's available is used; if none
|
||||||
|
are, step 4 degrades to a warning instead of blocking the skill.
|
||||||
|
|
||||||
|
## Defaults & Overrides
|
||||||
|
Unless the user says otherwise, assume:
|
||||||
|
- **Target name (`$TARGET_REPO`)**: the exact name of the current Gitea repository.
|
||||||
|
- **Interval (`$INTERVAL`)**: `"8h"`.
|
||||||
|
- **Sync on commit (`$SYNC_ON_COMMIT`)**: `true`.
|
||||||
|
|
||||||
|
*Example override:* "Mirror this example-config repo, but don't sync on commit and use the
|
||||||
|
name 'exmpl_cfg'" → `$TARGET_REPO` becomes `exmpl_cfg`, `$SYNC_ON_COMMIT` becomes `false`.
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
1. If `$GITHUB_USER` or `$GITHUB_TOKEN` is not already set, and a `.env` file exists at the
|
||||||
|
repository root, load it before doing anything else — without ever printing or `cat`-ing its
|
||||||
|
contents:
|
||||||
|
```sh
|
||||||
|
set -a; . ./.env; set +a
|
||||||
|
```
|
||||||
|
Variables already present in the environment take priority: only fall back to `.env` for
|
||||||
|
whichever of the two is still unset. If neither source provides both, stop and tell the user
|
||||||
|
what's missing.
|
||||||
|
2. Identify the current Gitea repository's owner (`$OWNER`) and name (`$SOURCE_REPO`).
|
||||||
|
3. Determine `$TARGET_REPO`, `$INTERVAL`, and `$SYNC_ON_COMMIT` from the defaults above,
|
||||||
|
applying any user overrides.
|
||||||
|
4. **Ensure the GitHub target repository exists.** GitHub, unlike Gitea, does not create a
|
||||||
|
repository on first push — if `$GITHUB_USER/$TARGET_REPO` doesn't exist yet, the mirror will
|
||||||
|
register successfully but every sync attempt will fail. Check for the repo and create it if
|
||||||
|
missing, using whichever of these is available (in order of preference):
|
||||||
|
|
||||||
|
- **`gh` CLI** (preferred if authenticated — `gh auth status`):
|
||||||
|
```sh
|
||||||
|
if ! gh repo view "$GITHUB_USER/$TARGET_REPO" >/dev/null 2>&1; then
|
||||||
|
gh repo create "$GITHUB_USER/$TARGET_REPO" --private --description "Push mirror of $OWNER/$SOURCE_REPO"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
Match visibility to the source repo where you can determine it (e.g. via `tea api
|
||||||
|
"repos/$OWNER/$SOURCE_REPO"` → `.private`); otherwise default to `--private` and mention the
|
||||||
|
choice when reporting the outcome.
|
||||||
|
- **GitHub MCP server**, if one is connected: use its repo-lookup tool to check for
|
||||||
|
`$GITHUB_USER/$TARGET_REPO`, and its repo-creation tool to create it (private by default) if
|
||||||
|
absent.
|
||||||
|
- **Plain REST API via `curl`**, using `$GITHUB_TOKEN` directly, if neither of the above is
|
||||||
|
available:
|
||||||
|
```sh
|
||||||
|
status=$(curl -s -o /dev/null -w '%{http_code}' \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
"https://api.github.com/repos/$GITHUB_USER/$TARGET_REPO")
|
||||||
|
if [ "$status" = "404" ]; then
|
||||||
|
curl -s -X POST \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
https://api.github.com/user/repos \
|
||||||
|
-d "$(jq -n --arg name "$TARGET_REPO" '{name: $name, private: true}')" \
|
||||||
|
>/dev/null
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
- **If none of these are available**, don't block on it — proceed to step 5, but warn the user
|
||||||
|
clearly that they must create `$GITHUB_USER/$TARGET_REPO` on GitHub themselves before the
|
||||||
|
mirror's first sync will succeed.
|
||||||
|
|
||||||
|
If a repo already exists at the target address, leave it as-is and continue — do not treat this
|
||||||
|
as an error.
|
||||||
|
|
||||||
|
5. Run the following snippet, substituting the values from steps 2–3. Credentials are passed as
|
||||||
|
separate `remote_username`/`remote_password` fields — never embedded in the mirror URL — per
|
||||||
|
Gitea's `CreatePushMirrorOption` schema.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# $OWNER / $SOURCE_REPO identify the local Gitea API endpoint.
|
||||||
|
# $TARGET_REPO is the destination repository name on GitHub.
|
||||||
|
# $INTERVAL and $SYNC_ON_COMMIT come from the Defaults & Overrides step above.
|
||||||
|
|
||||||
|
payload=$(jq -n \
|
||||||
|
--arg addr "https://github.com/$GITHUB_USER/$TARGET_REPO.git" \
|
||||||
|
--arg user "$GITHUB_USER" \
|
||||||
|
--arg pass "$GITHUB_TOKEN" \
|
||||||
|
--arg interval "$INTERVAL" \
|
||||||
|
--argjson sync $SYNC_ON_COMMIT \
|
||||||
|
'{remote_address: $addr, remote_username: $user, remote_password: $pass, interval: $interval, sync_on_commit: $sync}'
|
||||||
|
)
|
||||||
|
|
||||||
|
tea api --method POST --data "$payload" "repos/$OWNER/$SOURCE_REPO/push_mirrors"
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Report the outcome to the user, without echoing the request body, `.env` contents, or token —
|
||||||
|
including whether the GitHub repo already existed or was just created, and, if step 4 had no
|
||||||
|
capability to check/create it, a reminder that they need to create it manually.
|
||||||
@@ -2,5 +2,7 @@
|
|||||||
"name": "readme-sync-audit",
|
"name": "readme-sync-audit",
|
||||||
"description": "Analyzes repository delta since the last documentation update and synchronizes the README.md with the current codebase state.",
|
"description": "Analyzes repository delta since the last documentation update and synchronizes the README.md with the current codebase state.",
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
name: mirror-it
|
||||||
|
description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`.
|
||||||
|
version: 1.1.0
|
||||||
|
user-invocable: true
|
||||||
|
author: Rootiest
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gitea to GitHub Push Mirror
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
Register a Gitea push mirror so a repository's commits are automatically forwarded to a
|
||||||
|
corresponding GitHub repository, via `tea api` against Gitea's `push_mirrors` endpoint.
|
||||||
|
|
||||||
|
## Trigger Conditions
|
||||||
|
Activate this skill ONLY when one of the following is met:
|
||||||
|
1. The user explicitly types the command `/mirror-it`.
|
||||||
|
2. The user makes a natural-language request to mirror the repository (e.g., "Mirror this
|
||||||
|
repository to GitHub", "Mirror this example-config repo...").
|
||||||
|
3. You confidently infer the user intends to mirror the current repository, AND have
|
||||||
|
verified that a GitHub repository does not already exist at the target address.
|
||||||
|
|
||||||
|
## Constraints & Relevance
|
||||||
|
- **Gitea only**: this skill is relevant ONLY for repositories hosted on a Gitea instance
|
||||||
|
(e.g., `git.rootiest.dev`). Do NOT trigger it for repositories natively hosted on GitHub —
|
||||||
|
GitHub does not support push-mirroring to itself.
|
||||||
|
- **Security**: never read, print, or otherwise expose the value of `$GITHUB_TOKEN` (whether it
|
||||||
|
comes from the environment or a `.env` file — see Prerequisites). Pass the variable reference
|
||||||
|
directly into shell commands so it is only ever expanded by the shell, never written out by you.
|
||||||
|
- **Shell environment**: the snippet below is POSIX-compatible (`var=$(command)`), since the
|
||||||
|
command executes through whatever shell the tool invokes it with (bash/zsh/sh) — never assume
|
||||||
|
Fish syntax is available. An exported variable (`set -gx` in Fish, `export` in bash/zsh) is
|
||||||
|
inherited by every child process regardless of which shell that child happens to run, so
|
||||||
|
variables from the user's interactive shell config are already present without any special
|
||||||
|
handling.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
- `tea` is installed and already authenticated against the target Gitea instance (`tea login list`).
|
||||||
|
- `jq` is installed.
|
||||||
|
- `$GITHUB_USER` and `$GITHUB_TOKEN` (a GitHub PAT with `repo` scope) are available before step 3
|
||||||
|
below — either already exported in the environment, or defined in a `.env` file at the
|
||||||
|
repository root (see step 1).
|
||||||
|
- Optionally, one of the following for the target-repo check/creation in step 4: the `gh` CLI
|
||||||
|
(authenticated — `gh auth status`), a GitHub MCP server, or plain `$GITHUB_TOKEN` used directly
|
||||||
|
against the GitHub REST API via `curl`. The first of these that's available is used; if none
|
||||||
|
are, step 4 degrades to a warning instead of blocking the skill.
|
||||||
|
|
||||||
|
## Defaults & Overrides
|
||||||
|
Unless the user says otherwise, assume:
|
||||||
|
- **Target name (`$TARGET_REPO`)**: the exact name of the current Gitea repository.
|
||||||
|
- **Interval (`$INTERVAL`)**: `"8h"`.
|
||||||
|
- **Sync on commit (`$SYNC_ON_COMMIT`)**: `true`.
|
||||||
|
|
||||||
|
*Example override:* "Mirror this example-config repo, but don't sync on commit and use the
|
||||||
|
name 'exmpl_cfg'" → `$TARGET_REPO` becomes `exmpl_cfg`, `$SYNC_ON_COMMIT` becomes `false`.
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
1. If `$GITHUB_USER` or `$GITHUB_TOKEN` is not already set, and a `.env` file exists at the
|
||||||
|
repository root, load it before doing anything else — without ever printing or `cat`-ing its
|
||||||
|
contents:
|
||||||
|
```sh
|
||||||
|
set -a; . ./.env; set +a
|
||||||
|
```
|
||||||
|
Variables already present in the environment take priority: only fall back to `.env` for
|
||||||
|
whichever of the two is still unset. If neither source provides both, stop and tell the user
|
||||||
|
what's missing.
|
||||||
|
2. Identify the current Gitea repository's owner (`$OWNER`) and name (`$SOURCE_REPO`).
|
||||||
|
3. Determine `$TARGET_REPO`, `$INTERVAL`, and `$SYNC_ON_COMMIT` from the defaults above,
|
||||||
|
applying any user overrides.
|
||||||
|
4. **Ensure the GitHub target repository exists.** GitHub, unlike Gitea, does not create a
|
||||||
|
repository on first push — if `$GITHUB_USER/$TARGET_REPO` doesn't exist yet, the mirror will
|
||||||
|
register successfully but every sync attempt will fail. Check for the repo and create it if
|
||||||
|
missing, using whichever of these is available (in order of preference):
|
||||||
|
|
||||||
|
- **`gh` CLI** (preferred if authenticated — `gh auth status`):
|
||||||
|
```sh
|
||||||
|
if ! gh repo view "$GITHUB_USER/$TARGET_REPO" >/dev/null 2>&1; then
|
||||||
|
gh repo create "$GITHUB_USER/$TARGET_REPO" --private --description "Push mirror of $OWNER/$SOURCE_REPO"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
Match visibility to the source repo where you can determine it (e.g. via `tea api
|
||||||
|
"repos/$OWNER/$SOURCE_REPO"` → `.private`); otherwise default to `--private` and mention the
|
||||||
|
choice when reporting the outcome.
|
||||||
|
- **GitHub MCP server**, if one is connected: use its repo-lookup tool to check for
|
||||||
|
`$GITHUB_USER/$TARGET_REPO`, and its repo-creation tool to create it (private by default) if
|
||||||
|
absent.
|
||||||
|
- **Plain REST API via `curl`**, using `$GITHUB_TOKEN` directly, if neither of the above is
|
||||||
|
available:
|
||||||
|
```sh
|
||||||
|
status=$(curl -s -o /dev/null -w '%{http_code}' \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
"https://api.github.com/repos/$GITHUB_USER/$TARGET_REPO")
|
||||||
|
if [ "$status" = "404" ]; then
|
||||||
|
curl -s -X POST \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
https://api.github.com/user/repos \
|
||||||
|
-d "$(jq -n --arg name "$TARGET_REPO" '{name: $name, private: true}')" \
|
||||||
|
>/dev/null
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
- **If none of these are available**, don't block on it — proceed to step 5, but warn the user
|
||||||
|
clearly that they must create `$GITHUB_USER/$TARGET_REPO` on GitHub themselves before the
|
||||||
|
mirror's first sync will succeed.
|
||||||
|
|
||||||
|
If a repo already exists at the target address, leave it as-is and continue — do not treat this
|
||||||
|
as an error.
|
||||||
|
|
||||||
|
5. Run the following snippet, substituting the values from steps 2–3. Credentials are passed as
|
||||||
|
separate `remote_username`/`remote_password` fields — never embedded in the mirror URL — per
|
||||||
|
Gitea's `CreatePushMirrorOption` schema.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# $OWNER / $SOURCE_REPO identify the local Gitea API endpoint.
|
||||||
|
# $TARGET_REPO is the destination repository name on GitHub.
|
||||||
|
# $INTERVAL and $SYNC_ON_COMMIT come from the Defaults & Overrides step above.
|
||||||
|
|
||||||
|
payload=$(jq -n \
|
||||||
|
--arg addr "https://github.com/$GITHUB_USER/$TARGET_REPO.git" \
|
||||||
|
--arg user "$GITHUB_USER" \
|
||||||
|
--arg pass "$GITHUB_TOKEN" \
|
||||||
|
--arg interval "$INTERVAL" \
|
||||||
|
--argjson sync $SYNC_ON_COMMIT \
|
||||||
|
'{remote_address: $addr, remote_username: $user, remote_password: $pass, interval: $interval, sync_on_commit: $sync}'
|
||||||
|
)
|
||||||
|
|
||||||
|
tea api --method POST --data "$payload" "repos/$OWNER/$SOURCE_REPO/push_mirrors"
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Report the outcome to the user, without echoing the request body, `.env` contents, or token —
|
||||||
|
including whether the GitHub repo already existed or was just created, and, if step 4 had no
|
||||||
|
capability to check/create it, a reminder that they need to create it manually.
|
||||||
+3
-1
@@ -2,5 +2,7 @@
|
|||||||
"name": "ship-it",
|
"name": "ship-it",
|
||||||
"description": "Runs a comprehensive pre-flight audit, syncs the README, and publishes the changes to a new PR.",
|
"description": "Runs a comprehensive pre-flight audit, syncs the README, and publishes the changes to a new PR.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,7 @@
|
|||||||
"name": "systematic-enumeration",
|
"name": "systematic-enumeration",
|
||||||
"description": "Forces element-by-element verification for finite sets to prevent counting errors.",
|
"description": "Forces element-by-element verification for finite sets to prevent counting errors.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,7 @@
|
|||||||
"name": "technical-devlog-scribe",
|
"name": "technical-devlog-scribe",
|
||||||
"description": "Generates a highly structured, objective technical summary of a development session.",
|
"description": "Generates a highly structured, objective technical summary of a development session.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": {
|
||||||
|
"name": "Rootiest"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "caveman",
|
"name": "caveman",
|
||||||
"description": "Ultra-compressed communication mode from JuliusBrussee/caveman — cuts output tokens while keeping full technical accuracy. Installed straight from the upstream repo, not vendored here.",
|
"description": "Ultra-compressed communication mode from JuliusBrussee/caveman — cuts output tokens while keeping full technical accuracy. Installed straight from the upstream repo, not vendored here.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest",
|
"author": { "name": "Rootiest" },
|
||||||
"targets": ["claude-code"],
|
"targets": ["claude-code"],
|
||||||
"external": {
|
"external": {
|
||||||
"claude-code": {
|
"claude-code": {
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "core-essentials",
|
"name": "core-essentials",
|
||||||
"description": "Core cross-tool utilities, including delegation to the Antigravity CLI (agy) for grounded research and large multi-file audits.",
|
"description": "Core cross-tool utilities, including delegation to the Antigravity CLI (agy) for grounded research and large multi-file audits.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "date-time",
|
"name": "date-time",
|
||||||
"description": "Retrieves the exact current date and time for time-sensitive queries, scheduling, duration calculations, and validating chronological context.",
|
"description": "Retrieves the exact current date and time for time-sensitive queries, scheduling, duration calculations, and validating chronological context.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "docs-sync-audit",
|
"name": "docs-sync-audit",
|
||||||
"description": "Analyzes repository delta since the last documentation update and synchronizes the Single Source of Truth (docs/, wiki, or README) with the current codebase state.",
|
"description": "Analyzes repository delta since the last documentation update and synchronizes the Single Source of Truth (docs/, wiki, or README) with the current codebase state.",
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "git-publish-workflow",
|
"name": "git-publish-workflow",
|
||||||
"description": "Automates branching, conventional commits, testing, and PR creation for uncommitted or staged work. Handles both independent and stacked PRs.",
|
"description": "Automates branching, conventional commits, testing, and PR creation for uncommitted or staged work. Handles both independent and stacked PRs.",
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "gitea-mcp",
|
"name": "gitea-mcp",
|
||||||
"description": "Connects Claude Code/agy to a Gitea instance via the official gitea-mcp server, authenticated with GITEA_HOST/GITEA_ACCESS_TOKEN you set locally.",
|
"description": "Connects Claude Code/agy to a Gitea instance via the official gitea-mcp server, authenticated with GITEA_HOST/GITEA_ACCESS_TOKEN you set locally.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "github-mcp",
|
"name": "github-mcp",
|
||||||
"description": "Connects Claude Code/agy to GitHub via the official MCP server, authenticated with a GITHUB_PERSONAL_ACCESS_TOKEN you set locally.",
|
"description": "Connects Claude Code/agy to GitHub via the official MCP server, authenticated with a GITHUB_PERSONAL_ACCESS_TOKEN you set locally.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "mattpocock-skills",
|
||||||
|
"description": "Matt Pocock's agent skills for real engineering from mattpocock/skills — grilling, spec/ticket flows, TDD, code review, domain modelling and more. Installed straight from the upstream repo, not vendored here.",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": { "name": "Rootiest" },
|
||||||
|
"targets": ["claude-code"],
|
||||||
|
"external": {
|
||||||
|
"claude-code": {
|
||||||
|
"source": "github",
|
||||||
|
"repo": "mattpocock/skills"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "mirror-it",
|
||||||
|
"description": "Configures a Gitea repository to automatically push-mirror its contents to GitHub using the tea CLI and jq.",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"author": { "name": "Rootiest" }
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
name: mirror-it
|
||||||
|
description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`.
|
||||||
|
version: 1.1.0
|
||||||
|
user-invocable: true
|
||||||
|
author: Rootiest
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gitea to GitHub Push Mirror
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
Register a Gitea push mirror so a repository's commits are automatically forwarded to a
|
||||||
|
corresponding GitHub repository, via `tea api` against Gitea's `push_mirrors` endpoint.
|
||||||
|
|
||||||
|
## Trigger Conditions
|
||||||
|
Activate this skill ONLY when one of the following is met:
|
||||||
|
1. The user explicitly types the command `/mirror-it`.
|
||||||
|
2. The user makes a natural-language request to mirror the repository (e.g., "Mirror this
|
||||||
|
repository to GitHub", "Mirror this example-config repo...").
|
||||||
|
3. You confidently infer the user intends to mirror the current repository, AND have
|
||||||
|
verified that a GitHub repository does not already exist at the target address.
|
||||||
|
|
||||||
|
## Constraints & Relevance
|
||||||
|
- **Gitea only**: this skill is relevant ONLY for repositories hosted on a Gitea instance
|
||||||
|
(e.g., `git.rootiest.dev`). Do NOT trigger it for repositories natively hosted on GitHub —
|
||||||
|
GitHub does not support push-mirroring to itself.
|
||||||
|
- **Security**: never read, print, or otherwise expose the value of `$GITHUB_TOKEN` (whether it
|
||||||
|
comes from the environment or a `.env` file — see Prerequisites). Pass the variable reference
|
||||||
|
directly into shell commands so it is only ever expanded by the shell, never written out by you.
|
||||||
|
- **Shell environment**: the snippet below is POSIX-compatible (`var=$(command)`), since the
|
||||||
|
command executes through whatever shell the tool invokes it with (bash/zsh/sh) — never assume
|
||||||
|
Fish syntax is available. An exported variable (`set -gx` in Fish, `export` in bash/zsh) is
|
||||||
|
inherited by every child process regardless of which shell that child happens to run, so
|
||||||
|
variables from the user's interactive shell config are already present without any special
|
||||||
|
handling.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
- `tea` is installed and already authenticated against the target Gitea instance (`tea login list`).
|
||||||
|
- `jq` is installed.
|
||||||
|
- `$GITHUB_USER` and `$GITHUB_TOKEN` (a GitHub PAT with `repo` scope) are available before step 3
|
||||||
|
below — either already exported in the environment, or defined in a `.env` file at the
|
||||||
|
repository root (see step 1).
|
||||||
|
- Optionally, one of the following for the target-repo check/creation in step 4: the `gh` CLI
|
||||||
|
(authenticated — `gh auth status`), a GitHub MCP server, or plain `$GITHUB_TOKEN` used directly
|
||||||
|
against the GitHub REST API via `curl`. The first of these that's available is used; if none
|
||||||
|
are, step 4 degrades to a warning instead of blocking the skill.
|
||||||
|
|
||||||
|
## Defaults & Overrides
|
||||||
|
Unless the user says otherwise, assume:
|
||||||
|
- **Target name (`$TARGET_REPO`)**: the exact name of the current Gitea repository.
|
||||||
|
- **Interval (`$INTERVAL`)**: `"8h"`.
|
||||||
|
- **Sync on commit (`$SYNC_ON_COMMIT`)**: `true`.
|
||||||
|
|
||||||
|
*Example override:* "Mirror this example-config repo, but don't sync on commit and use the
|
||||||
|
name 'exmpl_cfg'" → `$TARGET_REPO` becomes `exmpl_cfg`, `$SYNC_ON_COMMIT` becomes `false`.
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
1. If `$GITHUB_USER` or `$GITHUB_TOKEN` is not already set, and a `.env` file exists at the
|
||||||
|
repository root, load it before doing anything else — without ever printing or `cat`-ing its
|
||||||
|
contents:
|
||||||
|
```sh
|
||||||
|
set -a; . ./.env; set +a
|
||||||
|
```
|
||||||
|
Variables already present in the environment take priority: only fall back to `.env` for
|
||||||
|
whichever of the two is still unset. If neither source provides both, stop and tell the user
|
||||||
|
what's missing.
|
||||||
|
2. Identify the current Gitea repository's owner (`$OWNER`) and name (`$SOURCE_REPO`).
|
||||||
|
3. Determine `$TARGET_REPO`, `$INTERVAL`, and `$SYNC_ON_COMMIT` from the defaults above,
|
||||||
|
applying any user overrides.
|
||||||
|
4. **Ensure the GitHub target repository exists.** GitHub, unlike Gitea, does not create a
|
||||||
|
repository on first push — if `$GITHUB_USER/$TARGET_REPO` doesn't exist yet, the mirror will
|
||||||
|
register successfully but every sync attempt will fail. Check for the repo and create it if
|
||||||
|
missing, using whichever of these is available (in order of preference):
|
||||||
|
|
||||||
|
- **`gh` CLI** (preferred if authenticated — `gh auth status`):
|
||||||
|
```sh
|
||||||
|
if ! gh repo view "$GITHUB_USER/$TARGET_REPO" >/dev/null 2>&1; then
|
||||||
|
gh repo create "$GITHUB_USER/$TARGET_REPO" --private --description "Push mirror of $OWNER/$SOURCE_REPO"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
Match visibility to the source repo where you can determine it (e.g. via `tea api
|
||||||
|
"repos/$OWNER/$SOURCE_REPO"` → `.private`); otherwise default to `--private` and mention the
|
||||||
|
choice when reporting the outcome.
|
||||||
|
- **GitHub MCP server**, if one is connected: use its repo-lookup tool to check for
|
||||||
|
`$GITHUB_USER/$TARGET_REPO`, and its repo-creation tool to create it (private by default) if
|
||||||
|
absent.
|
||||||
|
- **Plain REST API via `curl`**, using `$GITHUB_TOKEN` directly, if neither of the above is
|
||||||
|
available:
|
||||||
|
```sh
|
||||||
|
status=$(curl -s -o /dev/null -w '%{http_code}' \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
"https://api.github.com/repos/$GITHUB_USER/$TARGET_REPO")
|
||||||
|
if [ "$status" = "404" ]; then
|
||||||
|
curl -s -X POST \
|
||||||
|
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
https://api.github.com/user/repos \
|
||||||
|
-d "$(jq -n --arg name "$TARGET_REPO" '{name: $name, private: true}')" \
|
||||||
|
>/dev/null
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
- **If none of these are available**, don't block on it — proceed to step 5, but warn the user
|
||||||
|
clearly that they must create `$GITHUB_USER/$TARGET_REPO` on GitHub themselves before the
|
||||||
|
mirror's first sync will succeed.
|
||||||
|
|
||||||
|
If a repo already exists at the target address, leave it as-is and continue — do not treat this
|
||||||
|
as an error.
|
||||||
|
|
||||||
|
5. Run the following snippet, substituting the values from steps 2–3. Credentials are passed as
|
||||||
|
separate `remote_username`/`remote_password` fields — never embedded in the mirror URL — per
|
||||||
|
Gitea's `CreatePushMirrorOption` schema.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# $OWNER / $SOURCE_REPO identify the local Gitea API endpoint.
|
||||||
|
# $TARGET_REPO is the destination repository name on GitHub.
|
||||||
|
# $INTERVAL and $SYNC_ON_COMMIT come from the Defaults & Overrides step above.
|
||||||
|
|
||||||
|
payload=$(jq -n \
|
||||||
|
--arg addr "https://github.com/$GITHUB_USER/$TARGET_REPO.git" \
|
||||||
|
--arg user "$GITHUB_USER" \
|
||||||
|
--arg pass "$GITHUB_TOKEN" \
|
||||||
|
--arg interval "$INTERVAL" \
|
||||||
|
--argjson sync $SYNC_ON_COMMIT \
|
||||||
|
'{remote_address: $addr, remote_username: $user, remote_password: $pass, interval: $interval, sync_on_commit: $sync}'
|
||||||
|
)
|
||||||
|
|
||||||
|
tea api --method POST --data "$payload" "repos/$OWNER/$SOURCE_REPO/push_mirrors"
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Report the outcome to the user, without echoing the request body, `.env` contents, or token —
|
||||||
|
including whether the GitHub repo already existed or was just created, and, if step 4 had no
|
||||||
|
capability to check/create it, a reminder that they need to create it manually.
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "ponytail",
|
"name": "ponytail",
|
||||||
"description": "Lazy senior dev mode from DietrichGebert/ponytail — forces the simplest, shortest solution that actually works (YAGNI, stdlib first, no unrequested abstractions). Installed straight from the upstream repo, not vendored here.",
|
"description": "Lazy senior dev mode from DietrichGebert/ponytail — forces the simplest, shortest solution that actually works (YAGNI, stdlib first, no unrequested abstractions). Installed straight from the upstream repo, not vendored here.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest",
|
"author": { "name": "Rootiest" },
|
||||||
"targets": ["claude-code"],
|
"targets": ["claude-code"],
|
||||||
"external": {
|
"external": {
|
||||||
"claude-code": {
|
"claude-code": {
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "readme-sync-audit",
|
"name": "readme-sync-audit",
|
||||||
"description": "Analyzes repository delta since the last documentation update and synchronizes the README.md with the current codebase state.",
|
"description": "Analyzes repository delta since the last documentation update and synchronizes the README.md with the current codebase state.",
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "ship-it",
|
"name": "ship-it",
|
||||||
"description": "Runs a comprehensive pre-flight audit, syncs the README, and publishes the changes to a new PR.",
|
"description": "Runs a comprehensive pre-flight audit, syncs the README, and publishes the changes to a new PR.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "systematic-enumeration",
|
"name": "systematic-enumeration",
|
||||||
"description": "Forces element-by-element verification for finite sets to prevent counting errors.",
|
"description": "Forces element-by-element verification for finite sets to prevent counting errors.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
"name": "technical-devlog-scribe",
|
"name": "technical-devlog-scribe",
|
||||||
"description": "Generates a highly structured, objective technical summary of a development session.",
|
"description": "Generates a highly structured, objective technical summary of a development session.",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"author": "Rootiest"
|
"author": { "name": "Rootiest" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,6 +159,17 @@ def validate_targets(value: "list | None", valid_targets: list[str], context: st
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def validate_author(value: "dict | str | None", context: str) -> None:
|
||||||
|
"""Validate an optional 'author' field. The Claude Code marketplace/plugin
|
||||||
|
schemas both require an object ({"name": ...}), not a bare string."""
|
||||||
|
if value is None:
|
||||||
|
return
|
||||||
|
if not isinstance(value, dict) or not value.get("name"):
|
||||||
|
raise ValidationError(
|
||||||
|
f'{context}: \'author\' must be an object with a \'name\' field, e.g. {{"name": "..."}}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def validate_external(value: "dict | None", valid_targets: list[str], context: str) -> "dict | None":
|
def validate_external(value: "dict | None", valid_targets: list[str], context: str) -> "dict | None":
|
||||||
"""Validate an optional 'external' map of target -> marketplace source object."""
|
"""Validate an optional 'external' map of target -> marketplace source object."""
|
||||||
if value is None:
|
if value is None:
|
||||||
@@ -189,6 +200,7 @@ def discover_plugins(merged_root: Path, valid_targets: list[str]) -> list[dict]:
|
|||||||
for field in REQUIRED_PLUGIN_FIELDS:
|
for field in REQUIRED_PLUGIN_FIELDS:
|
||||||
if not meta.get(field):
|
if not meta.get(field):
|
||||||
raise ValidationError(f"{manifest_path}: missing required field '{field}'")
|
raise ValidationError(f"{manifest_path}: missing required field '{field}'")
|
||||||
|
validate_author(meta.get("author"), str(manifest_path))
|
||||||
plugin_targets = validate_targets(meta.get("targets"), valid_targets, str(manifest_path))
|
plugin_targets = validate_targets(meta.get("targets"), valid_targets, str(manifest_path))
|
||||||
plugin_external = validate_external(meta.get("external"), valid_targets, str(manifest_path))
|
plugin_external = validate_external(meta.get("external"), valid_targets, str(manifest_path))
|
||||||
if plugin_external is not None:
|
if plugin_external is not None:
|
||||||
@@ -399,16 +411,25 @@ def gen_claude_code(manifest: dict, plugins: list[dict], out_dir: Path) -> None:
|
|||||||
shutil.rmtree(plugins_out)
|
shutil.rmtree(plugins_out)
|
||||||
plugins_out.mkdir(parents=True)
|
plugins_out.mkdir(parents=True)
|
||||||
|
|
||||||
|
def marketplace_entry(name: str, meta: dict, source) -> dict:
|
||||||
|
entry: dict = {"name": name}
|
||||||
|
if meta.get("description"):
|
||||||
|
entry["description"] = meta["description"]
|
||||||
|
if meta.get("author"):
|
||||||
|
entry["author"] = meta["author"]
|
||||||
|
entry["source"] = source
|
||||||
|
return entry
|
||||||
|
|
||||||
marketplace_entries = []
|
marketplace_entries = []
|
||||||
for p in plugins:
|
for p in plugins:
|
||||||
name = p["meta"]["name"]
|
name = p["meta"]["name"]
|
||||||
external_source = (p["external"] or {}).get("claude-code") if p["external"] else None
|
external_source = (p["external"] or {}).get("claude-code") if p["external"] else None
|
||||||
if external_source is not None:
|
if external_source is not None:
|
||||||
if plugin_supports(p, "claude-code"):
|
if plugin_supports(p, "claude-code"):
|
||||||
marketplace_entries.append({"name": name, "source": external_source})
|
marketplace_entries.append(marketplace_entry(name, p["meta"], external_source))
|
||||||
continue
|
continue
|
||||||
if write_claude_plugin(p, plugins_out / name):
|
if write_claude_plugin(p, plugins_out / name):
|
||||||
marketplace_entries.append({"name": name, "source": f"./dist/claude-code/{name}"})
|
marketplace_entries.append(marketplace_entry(name, p["meta"], f"./dist/claude-code/{name}"))
|
||||||
|
|
||||||
bundle_id = manifest["bundle"]["id"]
|
bundle_id = manifest["bundle"]["id"]
|
||||||
bundle_skills = [(p, s) for p in plugins for s in active_skills(p, "claude-code")]
|
bundle_skills = [(p, s) for p in plugins for s in active_skills(p, "claude-code")]
|
||||||
@@ -426,7 +447,13 @@ def gen_claude_code(manifest: dict, plugins: list[dict], out_dir: Path) -> None:
|
|||||||
bundle_skills_dir = bundle_dest / "skills"
|
bundle_skills_dir = bundle_dest / "skills"
|
||||||
for _, s in bundle_skills:
|
for _, s in bundle_skills:
|
||||||
shutil.copytree(s["dir"], bundle_skills_dir / s["frontmatter"]["name"])
|
shutil.copytree(s["dir"], bundle_skills_dir / s["frontmatter"]["name"])
|
||||||
marketplace_entries.append({"name": bundle_id, "source": f"./dist/claude-code/{bundle_id}"})
|
marketplace_entries.append(
|
||||||
|
marketplace_entry(
|
||||||
|
bundle_id,
|
||||||
|
{"description": f"{manifest['marketplace']['description']} (all skills)"},
|
||||||
|
f"./dist/claude-code/{bundle_id}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
marketplace = {
|
marketplace = {
|
||||||
"name": manifest["marketplace"]["name"],
|
"name": manifest["marketplace"]["name"],
|
||||||
|
|||||||
Reference in New Issue
Block a user