From 9b0c76a95c059f54672d00d71e3c9cdf30c867bb Mon Sep 17 00:00:00 2001 From: Rootiest Date: Mon, 24 Aug 2026 23:35:34 -0400 Subject: [PATCH] feat: add mirror-it plugin for Gitea to GitHub push mirroring Adds a mirror-it skill that registers a Gitea push mirror via `tea api` against the push_mirrors endpoint, using Gitea's actual remote_address/remote_username/remote_password fields (never embedding credentials in the mirror URL). Credentials can come from the environment or fall back to a repo-root .env file, and all shell snippets are POSIX-compatible so the skill isn't tied to any one shell. Also ignores .env* files repo-wide. --- .claude-plugin/marketplace.json | 4 + .gitignore | 3 + README.md | 11 +++ dist/agy/mirror-it/plugin.json | 3 + dist/agy/mirror-it/skills/mirror-it/SKILL.md | 88 +++++++++++++++++++ .../rootiest-ai-all/skills/mirror-it/SKILL.md | 88 +++++++++++++++++++ .../mirror-it/.claude-plugin/plugin.json | 6 ++ .../mirror-it/skills/mirror-it/SKILL.md | 88 +++++++++++++++++++ .../rootiest-ai-all/skills/mirror-it/SKILL.md | 88 +++++++++++++++++++ plugins/mirror-it/plugin.json | 6 ++ plugins/mirror-it/skills/mirror-it/SKILL.md | 88 +++++++++++++++++++ 11 files changed, 473 insertions(+) create mode 100644 dist/agy/mirror-it/plugin.json create mode 100644 dist/agy/mirror-it/skills/mirror-it/SKILL.md create mode 100644 dist/agy/rootiest-ai-all/skills/mirror-it/SKILL.md create mode 100644 dist/claude-code/mirror-it/.claude-plugin/plugin.json create mode 100644 dist/claude-code/mirror-it/skills/mirror-it/SKILL.md create mode 100644 dist/claude-code/rootiest-ai-all/skills/mirror-it/SKILL.md create mode 100644 plugins/mirror-it/plugin.json create mode 100644 plugins/mirror-it/skills/mirror-it/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index c8c95c3..46890af 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -44,6 +44,10 @@ "repo": "mattpocock/skills" } }, + { + "name": "mirror-it", + "source": "./dist/claude-code/mirror-it" + }, { "name": "ponytail", "source": { diff --git a/.gitignore b/.gitignore index bda58eb..497d3cb 100644 --- a/.gitignore +++ b/.gitignore @@ -125,3 +125,6 @@ dist-private/ # ─────────────────────────── Python ────────────────────────── __pycache__/ *.pyc + +# ───────────────────────── Environment ────────────────────── +.env* diff --git a/README.md b/README.md index ccb4fa1..862a165 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ from one source tree and published as a native marketplace for both tools. - [date-time](#date-time) - [technical-devlog-scribe](#technical-devlog-scribe) - [ship-it](#ship-it) + - [mirror-it](#mirror-it) - [core-essentials](#core-essentials) - [github-mcp](#github-mcp) - [gitea-mcp](#gitea-mcp) @@ -129,6 +130,16 @@ Two sequential phases — Phase 2 is blocked until Phase 1 succeeds: --- +### `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. All shell snippets are POSIX-compatible so the skill works under bash, zsh, or any shell the agent's tool happens to invoke — not just Fish. + +**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` **Purpose:** Cross-tool utilities that don't belong to a single workflow. diff --git a/dist/agy/mirror-it/plugin.json b/dist/agy/mirror-it/plugin.json new file mode 100644 index 0000000..fc8baa9 --- /dev/null +++ b/dist/agy/mirror-it/plugin.json @@ -0,0 +1,3 @@ +{ + "name": "mirror-it" +} diff --git a/dist/agy/mirror-it/skills/mirror-it/SKILL.md b/dist/agy/mirror-it/skills/mirror-it/SKILL.md new file mode 100644 index 0000000..300a01e --- /dev/null +++ b/dist/agy/mirror-it/skills/mirror-it/SKILL.md @@ -0,0 +1,88 @@ +--- +name: mirror-it +description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`. +version: 1.0.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). + +## 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. Run the following snippet, substituting those values. 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" +``` + +5. Report the outcome to the user, without echoing the request body, `.env` contents, or token. diff --git a/dist/agy/rootiest-ai-all/skills/mirror-it/SKILL.md b/dist/agy/rootiest-ai-all/skills/mirror-it/SKILL.md new file mode 100644 index 0000000..300a01e --- /dev/null +++ b/dist/agy/rootiest-ai-all/skills/mirror-it/SKILL.md @@ -0,0 +1,88 @@ +--- +name: mirror-it +description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`. +version: 1.0.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). + +## 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. Run the following snippet, substituting those values. 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" +``` + +5. Report the outcome to the user, without echoing the request body, `.env` contents, or token. diff --git a/dist/claude-code/mirror-it/.claude-plugin/plugin.json b/dist/claude-code/mirror-it/.claude-plugin/plugin.json new file mode 100644 index 0000000..4515e22 --- /dev/null +++ b/dist/claude-code/mirror-it/.claude-plugin/plugin.json @@ -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.0.0", + "author": "Rootiest" +} diff --git a/dist/claude-code/mirror-it/skills/mirror-it/SKILL.md b/dist/claude-code/mirror-it/skills/mirror-it/SKILL.md new file mode 100644 index 0000000..300a01e --- /dev/null +++ b/dist/claude-code/mirror-it/skills/mirror-it/SKILL.md @@ -0,0 +1,88 @@ +--- +name: mirror-it +description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`. +version: 1.0.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). + +## 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. Run the following snippet, substituting those values. 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" +``` + +5. Report the outcome to the user, without echoing the request body, `.env` contents, or token. diff --git a/dist/claude-code/rootiest-ai-all/skills/mirror-it/SKILL.md b/dist/claude-code/rootiest-ai-all/skills/mirror-it/SKILL.md new file mode 100644 index 0000000..300a01e --- /dev/null +++ b/dist/claude-code/rootiest-ai-all/skills/mirror-it/SKILL.md @@ -0,0 +1,88 @@ +--- +name: mirror-it +description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`. +version: 1.0.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). + +## 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. Run the following snippet, substituting those values. 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" +``` + +5. Report the outcome to the user, without echoing the request body, `.env` contents, or token. diff --git a/plugins/mirror-it/plugin.json b/plugins/mirror-it/plugin.json new file mode 100644 index 0000000..4515e22 --- /dev/null +++ b/plugins/mirror-it/plugin.json @@ -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.0.0", + "author": "Rootiest" +} diff --git a/plugins/mirror-it/skills/mirror-it/SKILL.md b/plugins/mirror-it/skills/mirror-it/SKILL.md new file mode 100644 index 0000000..300a01e --- /dev/null +++ b/plugins/mirror-it/skills/mirror-it/SKILL.md @@ -0,0 +1,88 @@ +--- +name: mirror-it +description: Configures a Gitea repository to automatically push-mirror its contents to GitHub using the `tea` CLI and `jq`. +version: 1.0.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). + +## 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. Run the following snippet, substituting those values. 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" +``` + +5. Report the outcome to the user, without echoing the request body, `.env` contents, or token. -- 2.54.0