Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions .agents/skills/skillrig-init/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ description: >-
and understand how skillrig resolves the active origin. Use when the user wants to
"point this repo at our skills library", "set the origin", configure where skills come
from, set up `skillrig` in a repo, choose between a project vs global default origin,
use the `SKILLRIG_ORIGIN` environment variable, or fix a "no origin configured" /
"no origin given" error. Triggers on `skillrig init`, origin binding (OWNER/REPO),
and origin-resolution precedence questions.
track a specific branch of the origin (OWNER/REPO@branch), use the `SKILLRIG_ORIGIN`
environment variable, or fix a "no origin configured" / "no origin given" error.
Triggers on `skillrig init`, origin binding (OWNER/REPO[@REF]), pointing at a branch
of the skills repo, and origin-resolution precedence questions.
license: MIT
metadata:
author: skillrig
Expand All @@ -29,6 +30,13 @@ metadata:
**consume-only** — it never creates or scaffolds an origin, never reaches the network,
and binding the same origin twice is a no-op.

The origin reference is `OWNER/REPO[@REF]`. The optional `@REF` tracks a specific
**branch** of the library (e.g. `my-org/my-skills@staging`); omit it to track the
default branch. The `@REF` is validated for shape only (offline) — it is **not** checked
against the remote — and is stored combined in the single `origin` key. (Note: an
origin's `@ref` is a moving branch pointer; pinning an individual *skill* to an immutable
tag/SHA is a separate, later concern.)

It writes one of two config files:

- **Project** (default): `.skillrig/config.toml` at the **git repository root** (located
Expand All @@ -44,7 +52,7 @@ It writes one of two config files:

| Flag | Purpose | When to use |
|------|---------|-------------|
| `--origin OWNER/REPO` | The origin to bind | Always prefer passing it explicitly (scripts/agents) |
| `--origin OWNER/REPO[@REF]` | The origin to bind; optional `@REF` tracks a branch | Always prefer passing it explicitly (scripts/agents); add `@branch` to track a non-default branch |
| `--global` | Write the per-user default instead of the repo config | Setting a fallback used across all your repos |
| `--non-interactive` | Never prompt; fail fast if `--origin` is missing | CI/agents that must not block on input |
| `--json` | Emit a complete result object on stdout | Machine consumption |
Expand Down Expand Up @@ -93,16 +101,18 @@ present; branch on `written` to tell a fresh bind from an idempotent no-op:

1. **Bind a repo**: `skillrig init --origin my-org/my-skills` → run from anywhere in the
repo; config lands at the repo root.
2. **Personal default**: `skillrig init --origin my-org/my-skills --global`.
3. **CI / agent**: pass `--origin` (or set `SKILLRIG_ORIGIN`) **and** `--non-interactive`
2. **Track a branch**: `skillrig init --origin my-org/my-skills@staging` → records the
origin pinned to the `staging` branch (stored as `origin = 'my-org/my-skills@staging'`).
3. **Personal default**: `skillrig init --origin my-org/my-skills --global`.
4. **CI / agent**: pass `--origin` (or set `SKILLRIG_ORIGIN`) **and** `--non-interactive`
so the command never prompts.
4. **One-off override**: `SKILLRIG_ORIGIN=ci-org/ci-skills skillrig <cmd>` — no file edit.
5. **One-off override**: `SKILLRIG_ORIGIN=ci-org/ci-skills skillrig <cmd>` — no file edit.

## Error Handling

| Symptom (stderr) | Cause | Fix |
|------------------|-------|-----|
| `invalid origin "<value>": expected OWNER/REPO` | Origin not in `OWNER/REPO` shape | Pass a valid `--origin my-org/my-skills` |
| `invalid origin "<value>": expected OWNER/REPO[@REF]` | Origin (or its `@REF`) not in `OWNER/REPO[@REF]` shape | Pass a valid `--origin my-org/my-skills` (or `--origin my-org/my-skills@main`) |
| `no origin given … non-interactive session (no TTY)` | `init` run without `--origin` and stdin is not a terminal | Pass `--origin OWNER/REPO` or set `SKILLRIG_ORIGIN` |
| `no origin given … non-interactive mode requested (--non-interactive)` | `--non-interactive` set but no `--origin` | Pass `--origin OWNER/REPO` or set `SKILLRIG_ORIGIN` |
| "no origin configured" from a later command | No source supplied an origin | Run `skillrig init --origin OWNER/REPO`, or set `SKILLRIG_ORIGIN`, or add a `--global` default |
Expand Down
12 changes: 12 additions & 0 deletions .agents/skills/skillrig-init/evals/evals.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,17 @@
{ "id": "3.2", "text": "Offers concrete fixes: run `skillrig init --origin OWNER/REPO`, set SKILLRIG_ORIGIN, or set a --global default" },
{ "id": "3.3", "text": "Notes the project config is found by walking up from the current directory (works from subdirectories)" }
]
},
{
"id": 4,
"name": "track-a-branch",
"description": "User wants the repo to follow a specific branch of the skills library — should append @REF to the origin (OWNER/REPO@branch), not invent a separate flag.",
"prompt": "Our skills repo acme/agent-skills has a 'staging' branch we want to try before it merges. How do I point this repo at that branch with skillrig?",
"trap": "Model invents a non-existent flag (e.g. --branch/--ref), claims skillrig verifies the branch exists over the network, or conflates this with pinning an individual skill to a tag/SHA.",
"assertions": [
{ "id": "4.1", "text": "Recommends `skillrig init --origin acme/agent-skills@staging` (the @REF suffix on the single --origin string)" },
{ "id": "4.2", "text": "Does NOT invent a separate --branch/--ref flag; the ref rides inside the origin reference" },
{ "id": "4.3", "text": "Notes the @REF is validated for shape only / offline — existence on the remote is not checked" }
]
}
]
2 changes: 2 additions & 0 deletions .agents/skills/skillrig-init/evals/trigger-eval-set.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
{ "query": "skillrig says 'no origin configured' — how do I fix that?", "should_trigger": true },
{ "query": "What's the precedence between SKILLRIG_ORIGIN and the project config file?", "should_trigger": true },
{ "query": "How do I set a personal default skills origin used across all my repos?", "should_trigger": true },
{ "query": "I want this repo to track the staging branch of our skills repo acme/agent-skills with skillrig — how?", "should_trigger": true },
{ "query": "Can skillrig point at a specific branch of the skills library instead of the default branch?", "should_trigger": true },
{ "query": "Write a table-driven unit test for a Go parsing function.", "should_trigger": false },
{ "query": "How do I rebase my feature branch onto main and resolve conflicts?", "should_trigger": false },
{ "query": "Configure golangci-lint to enable the gosec linter.", "should_trigger": false }
Expand Down
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

> PRE-RELEASE MARKER: As long as this marker is present we NEVER PLAN BACKWARD COMPATBILITY. We are in rapid iteration and may make breaking changes to the CLI and/or skill contract at any time. ANY PLAN IGNORES BACKWARD COMPATIBILITY.

## What this is

`skillrig` is a single, generic, **consume-only** Go CLI for pointing a repo (or a per-user default) at an **origin** — the `OWNER/REPO` that hosts an org's agent skills — and managing vendored skills from it. The same binary serves humans, agents, and CI. There is no `publish`/`login` and no write credential in the binary: GitHub is the authority plane ("publishing" = a PR to the origin).
`skillrig` is a single, generic, **consume-only** Go CLI for pointing a repo (or a per-user default) at an **origin** — the `OWNER/REPO[@REF]` that hosts an org's agent skills — and managing vendored skills from it. The same binary serves humans, agents, and CI. There is no `publish`/`login` and no write credential in the binary: GitHub is the authority plane ("publishing" = a PR to the origin).

Two design documents are binding and override general instincts:
- `.specledger/memory/constitution.md` — development principles (spec-first, quickstart-as-contract, YAGNI, skill–CLI co-evolution).
Expand Down
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

`skillrig` is a CLI for pointing a repository (or your per-user default) at an
**origin** — the `OWNER/REPO` that hosts your team's agent skills — and resolving
which origin is active for any working directory.
which origin is active for any working directory. An origin reference is
`OWNER/REPO[@REF]`; the optional `@REF` tracks a specific branch.

> NOTE: a skillrig **origin** is a GitHub repository with a determined structure, use the template repository provided to create your own origin.

Expand All @@ -28,6 +29,14 @@ directory if you are not inside a git repo). `init` is **idempotent** and
**consume-only**: it records an existing origin, never creates or scaffolds one,
and binding the same origin twice is a no-op.

```sh
# Track a specific branch of the origin instead of its default branch.
skillrig init --origin my-org/my-skills@staging
```

The optional `@REF` is validated for shape only (offline) — it is not checked
against the remote.

### Set a personal default

```sh
Expand Down Expand Up @@ -84,6 +93,12 @@ The v0 `config.toml` holds a single key:
origin = 'my-org/my-skills'
```

To track a branch, the optional `@REF` is stored combined in the same key:

```toml
origin = 'my-org/my-skills@staging'
```

Unknown keys are ignored on read, so config added by later versions will not break this
one. The full, extended `config.toml` structure is documented on the project docs
website; see also [docs/design/cli.md](docs/design/cli.md) for the CLI design contract.
4 changes: 3 additions & 1 deletion docs/ARCHITECTURE-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ skillrig is a *framework* any org can adopt, not a single-org tool. Three pieces

Lower-priority sources fill in only what higher ones omit (like git local > global > system) — so a contractor can target client-A's origin in one repo and client-B's in another, while keeping a personal global default.

**Origin reference shape — `OWNER/REPO[@REF]`.** The origin reference accepts an optional `@REF` suffix that tracks a **branch** of the library (e.g. `my-org/my-skills@staging`); omitted, it tracks the default branch. It is stored combined in the single `origin` key and validated shape-only/offline. This realizes the `@ref` half of the R26 identity grammar (§9b) for origins specifically — note the *origin's* `@ref` is a moving branch pointer, whereas a *skill's* pin (`add --pin`) is an immutable tag/SHA. The `[/path]` portion of the grammar remains future work.

**Config vs. lock — separate files, co-located dir.** Input and tool-output have different natures and must not share a file (you'd get merge conflicts on hand-edited bits whenever the tool rewrites generated bits — the reason npm splits `package.json` from `package-lock.json`). So:
```
.skillrig/
Expand Down Expand Up @@ -310,7 +312,7 @@ Verified against mise's GitHub backend docs (current as of early 2026). Three fi

## 9b. External sources, allowlist & audit (R26–R29) — v1+ governance, designed-for in v0

**Identity grammar (R26) — v0 foundation.** Adopt the ecosystem-standard reference grammar `OWNER/REPO[/path]@ref` + skill name. This is the format both Vercel `npx skills` and GitHub `gh skill` use (`gh skill install github/awesome-copilot documentation-writer@v1.2.0`, with nested-path discovery via the `skills/*/SKILL.md` convention). Use it as the **single key** for: lockfile entries (§4.2), `index.json` rows, and allowlist entries. One grammar, three consumers — an allowlist entry is literally "a source-ref pattern that lock entries are permitted to match."
**Identity grammar (R26) — v0 foundation.** Adopt the ecosystem-standard reference grammar `OWNER/REPO[/path]@ref` + skill name. This is the format both Vercel `npx skills` and GitHub `gh skill` use (`gh skill install github/awesome-copilot documentation-writer@v1.2.0`, with nested-path discovery via the `skills/*/SKILL.md` convention). Use it as the **single key** for: lockfile entries (§4.2), `index.json` rows, and allowlist entries. One grammar, three consumers — an allowlist entry is literally "a source-ref pattern that lock entries are permitted to match." *(Implemented so far: the origin reference realizes `OWNER/REPO[@REF]` with `@REF` as a branch pointer — see §2d; `[/path]` and lock/allowlist consumers are still future work.)*

**Allowlist (R27) — policy data in the monorepo.** Author an `allowlist` section consumed by the `index.json` build (or a sibling `policy.toml`), listing permitted external sources at `OWNER/REPO[/path]` granularity, optionally pinned with `@ref`. Because it ships with the org-controlled source of truth, `doctor` evaluates "is this source permitted?" as a **deterministic offline lookup** (N6) — never inference.

Expand Down
3 changes: 2 additions & 1 deletion docs/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ resolver — AP-04 / AP-06) and layers thin commands on top.
|---|----------------|---------|------------|--------|
| 001 | **`init` + origin resolution** — `env SKILLRIG_ORIGIN > .skillrig/config.toml > ~/.config/skillrig/config.toml`; `skillrig init [--origin] [--global]` binds an existing origin (never bootstraps) | Environment | — (project skeleton) | 🚧 |
| 002 | **`skillcore` + `verify`** — git tree-SHA + `skill.toml` manifest parse; offline label-honesty + orphan check; exit codes 0/2/3 | Verification Gate | 001 | ⬜ |
| 003 | **`search`** — read committed `index.json`, deterministic tag filter, Two-Level Output | Query | 001 | ⬜ |
| 003 | **`search`** — read origin (branch aware) committed `index.json`, deterministic tag filter, Two-Level Output | Query | 001 | ⬜ |
| 004 | **`add`** — vendor a skill subtree + write lock entry; `--dry-run`, refuse-clobber-without-`--force` | Vendor Mutation | 002 | ⬜ |
| 005 | **backing-CLI prereqs** — `[[requires]]` declare + verify (`--eligible`-style readiness, auth-as-distinct-failure R18); mise consumption via per-CLI tagged releases + template-generated `mise.toml` | (extends verify/doctor) | 002 | ⬜ |
| 006 | **`doctor`** — superset health check (integrity + prereqs + auth) | Environment | 002, 005 | ⬜ |
| 007 | **`bump --pr`** — detect upstream advance, drift-aware three-way-merge, open reviewable PR (conflict markers + non-zero exit on conflict) | Vendor Mutation | 002, 004 | ⬜ |
| 008 | **`global add` / `global verify`** — fetch/restore user-scope skills against the global lock | Global Management | 002 | ⬜ |
| 009 | **multi-client materialization** — canonical `.agents/skills` + symlink views, copy-fallback (Windows/CI) | (supports add/global) | 004 | ⬜ |
| 010 | **`lint`** — author-side conformance gate, required PR check on the origin | Verification Gate | 002 | ⬜ |
| 011 | **`aws`** — support AWS AgentRegistry hosted skills | Evolution | 002 | ⬜ |

**Cross-cutting v0 commitments** (architecture §13):
- Two scopes only — project (vendored, verify-only) + global (fetch/restore). **No "shared" middle tier.**
Expand Down
23 changes: 22 additions & 1 deletion docs/design/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Quick reference for contributors. Every `skillrig` subcommand must satisfy these
4. **JSON output is complete** — full data, pipeable to `jq`, no truncation
5. **Errors to stderr, data to stdout** — enables clean piping
6. **Positional args for simple cases** — reserve flags for optional/complex params
7. **Origin is resolved, never baked in** — env > project config > global default (§2d of architecture.md); `--origin` overrides
7. **Origin is resolved, never baked in** — env > project config > global default (§2d of architecture.md); `--origin` overrides. The origin reference is `OWNER/REPO[@REF]`; `@REF` is optional and tracks a branch (see [Origin Reference Grammar](#origin-reference-grammar))
8. **Classify against a pattern before merging** — see [Pattern Classification](#pattern-classification) and the [pattern-gate checklist](checklist-template.md)
9. **The CLI is consume-only** — no `publish`, no `login`, no write credential in the binary (architecture §2b). GitHub is the authority plane.
10. **Standard flags everywhere** — see [Standard Flags](#standard-flags): `--json` + `--verbose` on every command; mutating commands also take `--dry-run` and refuse to clobber divergent content without `--force`
Expand Down Expand Up @@ -230,6 +230,27 @@ A small set of flags carry the same meaning across every command, so an agent ca

---

## Origin Reference Grammar

The origin reference — the value of `--origin`, `SKILLRIG_ORIGIN`, and the `origin` key in `.skillrig/config.toml` — is `OWNER/REPO[@REF]`. The `@REF` suffix is **optional**: omitted, the origin tracks the library's default branch; supplied, it tracks a specific **branch** (e.g. a staging line of the skills library). Validation is **shape-only and offline** — like the rest of `init`, it never checks that the repo or ref actually exists (that is a future `doctor`/`verify`/`add` concern).

```
skillrig init --origin my-org/my-skills # default branch
skillrig init --origin my-org/my-skills@staging # track the 'staging' branch
```

This realizes the `@ref` half of the ecosystem-standard identity grammar `OWNER/REPO[/path]@ref` (architecture R26) that `gh skill` (`gh skill install github/awesome-copilot documentation-writer@v1.2.0`) and Vercel `npx skills` use. The `[/path]` portion remains future work.

**Two meanings of `@ref`, kept distinct.** For an **origin**, `@REF` is a *moving pointer* — a branch you track and re-resolve. For a **skill** vendored via `add` (`skillrig add <skill> --pin <ref>`), the ref is an *immutable* pin — a tag or commit SHA, recorded in the lock so the vendored content is reproducible. Same grammar, opposite intent: the origin says "where to look (and which line of development)"; the pin says "exactly which reviewed bytes." Docs and help text must not conflate them.

### Why a single `@ref` string, not a separate flag

The branch rides *inside* the one origin string rather than in a separate `--branch`/`--ref` flag, and is stored combined in the single `origin` config key (`origin = 'my-org/my-skills@staging'`). Rationale:

- **One key, three consumers (R26).** The same reference is the key for config, `index.json` rows, and (later) allowlist/lock entries. A single canonical string keeps those aligned; splitting owner/repo from ref into parallel fields invites drift and a "what wins if both are set?" ambiguity.
- **Ecosystem familiarity.** `@ref` matches `gh skill`, `npx skills`, npm (`pkg@version`), and Go modules (`mod@version`) — an agent transfers the form without re-reading `--help`.
- **No new flag surface.** `--origin` stays the single way to name an origin; the grammar carries the optional precision. (A `#`-separator — git/npm git-dep style — was considered and rejected for weaker ecosystem alignment with the R26 grammar already adopted.)

## Pattern Classification

Every `skillrig` subcommand MUST identify which pattern(s) it follows. This classification drives design constraints and review expectations. See the [pattern-gate checklist](checklist-template.md) for the per-command gate used at PR review time.
Expand Down
Loading