Claude Code's plugin/marketplace schemas require author to be an object
({"name": ...}), not a bare string — installing any plugin from this
marketplace failed validation ("author: Invalid input: expected object,
received string"). Convert every plugins/*/plugin.json author field
accordingly, and add a build-time check so this can't regress.
Also propagate each plugin's description/author into the generated
marketplace.json entries (not just its own nested plugin.json), matching
Anthropic's official marketplace shape, so the Discover UI shows a
description before install instead of a blank "Plugin details" pane.
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.
This repo mirrors to github.com/rootiest/rootiest-ai on every push, so
/plugin marketplace add rootiest/rootiest-ai resolves fine and is
shorter than the full Gitea clone URL. Also documents the standalone
`claude plugin marketplace add` form for use outside a session.
Lets a plugin.json declare an `external` target->source map instead of
carrying local content, so the generator emits that Claude Code
marketplace source (e.g. a GitHub repo) verbatim rather than a local
dist path. Adds caveman and ponytail as external entries, installed
straight from their upstream repos with nothing vendored or copied.
Claude Code-only for now — agy has no equivalent external-source
mechanism, and both plugins' hooks/MCP assume Claude Code's runtime.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YVWWAnvR5TDQzmfY3RXG9
Split the GitHub/Gitea MCP servers out of core-essentials into their own
github-mcp/gitea-mcp plugins, so a user can install either, both, or
neither independently instead of always getting both bundled together.
Add an optional "targets" field, honored at both levels:
- plugin.json: restricts the whole plugin (including any hooks/mcp/
rules/commands/agents it bundles) to specific targets.
- a skill's own SKILL.md frontmatter: restricts just that one skill,
independent of its plugin's sibling skills (narrowed to, never wider
than, the plugin's own targets).
Omitting it (the default everywhere) means every target in manifest.yaml,
so this is fully backward compatible. A plugin left with no content at
all for a given target is now skipped entirely for that target rather
than emitting an empty output directory / marketplace entry.
Applies this to the actual motivating case: delegate-agy only makes sense
run from Claude Code (it shells out to `agy`), so it's now marked
targets: [claude-code] and no longer ships into dist/agy at all — it was
previously being installed into agy for no reason.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YVWWAnvR5TDQzmfY3RXG9
Testing against a live agy session confirmed the plugins.json "entries"
mechanism documented for agy does not reliably surface a plugins/<name>/
bundle as a plugin: hooks and MCP servers inside it are never loaded, and
only a stray skill occasionally surfaces via agy's generic skill-walk
("No plugins are currently loaded or discoverable in the active context").
Add scripts/install_agy.py, which instead pushes a generated dist/agy
into the locations confirmed to actually work: symlinks each skill into
~/.gemini/config/skills/<name>/ (or a project's .agents/skills/ with
--project) and merges each plugin's mcpServers/hooks into the shared
global mcp_config.json/hooks.json without touching unrelated entries.
Supports --uninstall to cleanly remove exactly what was added.
generate_plugins.py's --install-local now shells out to it for the agy
side instead of printing the broken plugins.json instructions.
Also fixes plugins/core-essentials/mcp.json, which had been hand-added
directly under the repo root (never discovered by the generator) with
invalid JSON (missing the outer object) and no env-var indirection for
its GitHub/Gitea tokens; moved under the plugin and wired up with
${VAR} placeholders instead.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YVWWAnvR5TDQzmfY3RXG9
Replace the skills-only SSoT (skills/<name>/SKILL.md) with plugins/<name>/,
where a plugin can bundle skills, MCP servers, lifecycle hooks, rules,
commands, and agents. scripts/generate_plugins.py now discovers plugins
from one or more layered --source roots and emits real per-target trees
(dist/claude-code/** + .claude-plugin/marketplace.json, dist/agy/**),
translating hooks.json/mcp.json between Claude Code's and agy's actual
schemas instead of only fanning out flat skill lists.
Adds a private-overlay build path (--source/--private-repo/--out/
--install-local) so a second, non-public repo (PII, tokens, personal-only
plugins) can extend or override the public plugin set without either repo
touching the other's history — private builds default to a gitignored
dist-private/ and never land in tracked output.
Drops install.sh and descriptions.json: both only ever covered skills and
pre-date the native plugin marketplace; both tools now install the plugin
marketplace the documented way (Claude Code's /plugin marketplace add,
agy's plugins.json entries). CI path filters move to plugins/**, and the
workflow gains workflow_dispatch for a manual re-trigger.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014YVWWAnvR5TDQzmfY3RXG9
Document docs-sync-audit, date-time, and technical-devlog-scribe; update the stale ship-it phase 1 reference from readme-sync-audit to docs-sync-audit.
Give every skill a consistent name/description/version/user-invocable header. Add missing frontmatter to date-time and ship-it; normalize systematic-enumeration name to kebab-case and version to semver.
Functions almost exactly as the readme-sync-audit, but attempts to
identify existing documentation and use that as the "Single Source of
Truth" instead of the README. README will also be updated only when
changes are relevant to the README layout/content.
- Replace Gemini CLI with Antigravity CLI throughout (--gemini kept as
hidden fallback flag; GEMINI_SKILLS_DIR honoured as legacy env var)
- Default install dir updated to ~/.gemini/antigravity-cli/skills
- Add ANTIGRAVITY_SKILLS_DIR env var with GEMINI_SKILLS_DIR fallback
- Add -l/--list flag: lists available skills with one-line descriptions
- Add descriptions.json mapping skill names to short descriptions;
fetch_descriptions() prefers a local copy when running from a clone,
falls back to remote URL for curl-pipe installs
- Document ship-it skill in README (was missing since its addition)
- Fix Manual Install cd path: claude-skills → ai-skills
Adds a [!TIP] callout above the curl examples noting that
https://url.rootiest.dev/skills can be substituted for the full raw
URL, with a short e.g. showing the pattern.
Both Claude Code and Gemini CLI expect skills at:
<skills-dir>/<skill-name>/SKILL.md
rather than the flat:
<skills-dir>/<skill-name>.md
Update install_to_claude and install_to_gemini to create the skill
subdirectory and write the file as SKILL.md within it.
Introduces a standalone skill installer script and project landing page
documentation covering all three skills in the repository.
install.sh:
- Downloads and installs SKILL.md files from the remote repository into
the appropriate local directory for Claude Code (~/.claude/skills/) and/or
Gemini CLI (~/.gemini/skills/)
- Supports --claude/-c and --gemini/-g flags to target one or both tools;
defaults to both when neither is specified
- Accepts positional skill name arguments or --all/-a to install every
available skill; named arguments always take precedence over --all
- Discovers available skills at runtime via the Gitea contents API, with
automatic fallback to a depth-1 sparse git clone when the API is
unreachable or returns no results; JSON parsing uses jq, then python3,
then an awk fallback in order of availability
- Validates skill names against path traversal (../) and slash injection
before any download is attempted
- Supports CLAUDE_SKILLS_DIR and GEMINI_SKILLS_DIR environment variable
overrides for non-default install locations
- Checks for curl and git dependencies at startup and exits with a clear
error listing any missing tools
- Cleans up any temporary clone directory on exit via a trap on EXIT
- Displays colorized output (Bold/Cyan headers, Green success, Yellow
warnings, Red errors) when stdout is a terminal; disables all ANSI codes
automatically when piped or redirected
- Includes a fully formatted --help/-h page documenting all flags,
environment variables, and usage examples
README.md:
- Landing page covering project purpose, all three skills with per-skill
purpose and execution protocol summaries, and a full Installation section
- Installation section documents the standard curl pipe form
(curl -sL URL | bash -s -- args) with six ready-to-use one-liner examples
covering all major flag combinations
- Flags & Options table, Environment Variables table, and a Manual Install
section for users who prefer to inspect before running
- Table of contents with anchor links for all major sections
- License section referencing GPL-3.0-or-later