diff --git a/NOTICE b/NOTICE index 2ba7c60..63ccbf7 100644 --- a/NOTICE +++ b/NOTICE @@ -32,3 +32,10 @@ skills/kagi/scripts/{search,extract}.mjs https://github.com/badlogic/pi-skills/blob/main/brave-search/search.js Modified: rewritten against the Kagi Universal Search API (v1); key read from the OS keyring instead of an environment variable. + +skills/commit/SKILL.md + Inspired by mitsuhiko/agent-stuff (Apache-2.0): + https://github.com/mitsuhiko/agent-stuff/blob/main/skills/commit/SKILL.md + Modified: defers to project instructions and observed history instead of a + prescribed Conventional Commits format; detects jj as well as git; leaves + signing and trailers to repository configuration. diff --git a/README.md b/README.md index 65d2664..531f563 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Personal [Pi](https://pi.dev) package — extensions, skills, prompts, and theme ## Skills +- [commit](./skills/commit/README.md) - commit changes with a message matching the repository's own conventions, in git or jj. - [github](./skills/github/README.md) - use the `gh` CLI when interacting with GitHub. - [kagi](./skills/kagi/README.md) - web search and extraction via the Kagi API. diff --git a/skills/commit/README.md b/skills/commit/README.md new file mode 100644 index 0000000..588770a --- /dev/null +++ b/skills/commit/README.md @@ -0,0 +1,45 @@ +# commit — setup + +`SKILL.md` in this directory is the whole skill: instructions, no scripts. It replaces the always-loaded "match the repository's commit style" rule in `AGENTS.md` with text Pi reads only when it is about to commit something, and it handles `jj` as well as `git`. + +## Requirements + +Only the version-control CLI the checkout already uses has to be on `PATH`: + +```bash +command -v git jj # whichever your repositories use +``` + +Nothing to install, authenticate, or configure for the skill itself — it runs read-only inspection commands and one commit command. A machine with neither CLI simply never triggers it. + +## Use + +Ask for a commit in ordinary words — "let's commit this work" — and Pi loads the skill from its description. `/skill:commit` forces the load when it doesn't. Anything you say alongside the request outranks everything the skill contains, including which files belong in the commit. + +## Setting a repo's style + +The skill has no message format of its own. It reads, in order: the request, project guidance (`AGENTS.md`, `CLAUDE.md`, `CONTRIBUTING*`, `git config --get commit.template`, or a `commit-msg` hook under `core.hooksPath`), the last 50 subjects in history. With nothing to read — a fresh repository, or history whose changes carry no descriptions — it asks rather than guessing. + +To pin the style, add this section to the `AGENTS.md` at the root of that repository — the same file Pi already loads as project instructions, so the skill reads it with no further setup: + +```markdown +## Commit format + +Use `[type/name] Message`, the artifact path as the scope: +`[extensions/goal] Add a token budget to goal continuation`. +``` + +A colocated repository (`.jj` beside `.git`) is committed with `jj describe`, not `git commit`, because jj owns that history. To use git there anyway, say so in the request or put the stanza above in the project's `AGENTS.md` — both outrank detection. + +## Troubleshooting + +- **`name "commit" collision` under `[Skill conflicts]` in Pi's startup diagnostics** — two skills claim the name and the first discovered wins; rename or remove one source. +- **`skill path does not exist`** — a `pi.skills` entry points somewhere that isn't there. Relative paths resolve from the settings file that declares them. +- **`/skill:commit` is absent from the command list** — skill commands need `enableSkillCommands` in settings; typing it still works. Run `/reload` after editing a skill. +- **`(no email set)` in `jj log`** — jj does not read git's `user.name`/`user.email`; set it once with `jj config set --user user.name "Spencer Gilbert"` and the matching `user.email`, or jj warns `Name and email not configured` on every describe. +- **Commit came out unsigned where its history is signed** — the skill never passes `-S`/`--gpg-sign` or runs `jj sign`, so signing is whatever the configuration says: `git config --get commit.gpgSign`, `jj config get signing.backend`. Fix it there, or ask for the signature in the request. The same goes for a missing `Signed-off-by` (git's `format.signOff`, a DCO line rather than a signature) and for `Change-Id` and other trailers, which the skill adds only to repositories whose history already carries them. +- **Subject style ignored in a jj repository** — `jj log` hides abandoned and orphaned changes from its default revset, so the sample read may be thinner than the history. Check what is reachable with `jj log -r 'all()' --no-pager -T 'description.first_line() ++ "\n"'`. + +## Credits + +Inspired by [mitsuhiko/agent-stuff `skills/commit/SKILL.md`](https://github.com/mitsuhiko/agent-stuff/blob/main/skills/commit/SKILL.md) (Apache-2.0) — keeps the read-the-repo-then-commit shape; drops the prescribed Conventional Commits format in favour of project instructions and observed history, handles `jj` as well as `git`, and leaves signing and trailers to repository configuration. diff --git a/skills/commit/SKILL.md b/skills/commit/SKILL.md new file mode 100644 index 0000000..8d3463f --- /dev/null +++ b/skills/commit/SKILL.md @@ -0,0 +1,39 @@ +--- +name: commit +description: Commit the current changes with a message that matches the repository's own conventions. Use when asked to commit, describe, or land changes, or when writing a commit message. Detects jj (Jujutsu) and git instead of assuming either. +compatibility: Needs the checkout's own VCS CLI on PATH, `git` or `jj`. +--- + +# Commit + +Commit the current changes. Take the message format from the repository, not from a convention you already know. + +## Find the tool + +`jj root` succeeds → use `jj`, including in a colocated repository where `.jj` sits beside `.git` and jj owns the history; `git commit` there writes behind its back. Otherwise use `git`. If neither succeeds this is not a checkout: say so rather than running `git init` or `jj git init`. + +## Find the style + +Use the first source below that answers the question, and do not fall back on Conventional Commits or any other well-known convention when none of them does. + +1. **The request** — anything stated, however it was phrased or invoked. +2. **Project guidance** — `AGENTS.md`, `CLAUDE.md`, `CONTRIBUTING*`, `git config --get commit.template`, or a `commit-msg` hook (`core.hooksPath`, else `.git/hooks/`). +3. **Observed history** — `git log --format=%s -n 50`, or `jj log -n 50 --no-pager -T 'description.first_line() ++ "\n"'`. Copy subject structure, capitalization, tense, scope or `[type/name]`-style prefixes, whether bodies appear and how they wrap, and which trailers appear. +4. **Nothing above answered it** — a fresh repository, or history with no descriptions: ask for guidance. Do not invent a convention. + +## Make the commit + +Read the change set first: `git status --short` with `git diff` (and `--cached`), or `jj status` with `jj diff`. + +- **git** — stage by path (`git add `, not `-A`, which sweeps in files the change never meant), then `git commit -m ""`, one more `-m` per body paragraph. +- **jj** — the working copy already holds the change: `jj describe -m ""`, then `jj new` to leave it and start clean. There is no staging area; split with `jj split` or move part into another change with `jj squash`. +- **Always pass `-m`** — bare `git commit` and bare `jj describe` open `$EDITOR` / `ui.editor` and wait for you. +- **Then read back what you wrote** — `git log -1 --format=%B`, or `jj log --no-pager -r @ -T 'description'`. + +## Defaults + +The request overrides every one of these. + +- Commit only: no push, publish, rebase, or pull request. +- Commit only the files this change is about. If a file's place in it is unclear, ask before including it. +- **Trailers and signatures follow the repository.** Copy `Signed-off-by`, `Change-Id`, or a breaking-change footer when its history or instructions have them, and add none it does not. Do not pass `-S`/`--gpg-sign` or run `jj sign` on your own initiative — `commit.gpgSign` and `format.signOff` in git, `signing.backend` in jj, decide whether a change is signed.