detached d205ffd

docs(skills): add an agent skill for using ermite and its CLI

commit
d205ffdd70fc00ccd96c6b10b585749b3f82fbfa
author
brice · · 2026-10-11 05:21 UTC
parent
9fdf386
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
3 files · +158 -0
M README.md +2 -0
@@ -49,6 +49,8 @@ ermite version # client and server, warns about missing server
4949 ermite watch [repo] [--json] # follows events, reconnects and resumes
5050 ```
5151
52+An agent skill describing the CLI and the forge lives in [`skills/ermite`](skills/ermite/SKILL.md); link or copy that folder into your agent's skills directory.
53+
5254 `--json` on `repo list|show|create|edit`, `token create|list` and `version` prints stable field names, listed in each command's `--help`; `watch --json` prints one object per line. Errors are one line on standard error (`ermite: …`) and exit status 1. `ermite completion bash|zsh|fish` prints a shell completion script that completes repository names from the server.
5355
5456 ## Git over HTTP
@@ -49,6 +49,8 @@ ermite version # client and server, warns about missing server
49 ermite watch [repo] [--json] # follows events, reconnects and resumes49 ermite watch [repo] [--json] # follows events, reconnects and resumes
50 ```50 ```
51 51
52+An agent skill describing the CLI and the forge lives in [`skills/ermite`](skills/ermite/SKILL.md); link or copy that folder into your agent's skills directory.
53+
52 `--json` on `repo list|show|create|edit`, `token create|list` and `version` prints stable field names, listed in each command's `--help`; `watch --json` prints one object per line. Errors are one line on standard error (`ermite: …`) and exit status 1. `ermite completion bash|zsh|fish` prints a shell completion script that completes repository names from the server.54 `--json` on `repo list|show|create|edit`, `token create|list` and `version` prints stable field names, listed in each command's `--help`; `watch --json` prints one object per line. Errors are one line on standard error (`ermite: …`) and exit status 1. `ermite completion bash|zsh|fish` prints a shell completion script that completes repository names from the server.
53 55
54 ## Git over HTTP56 ## Git over HTTP
A skills/ermite/CLI.md +83 -0
@@ -0,0 +1,83 @@
1+# ermite CLI reference
2+
3+Remote commands read `ERMITE_URL` (`http://` or `https://`) and `ERMITE_TOKEN` (optional for public reads). Run `ermite <command> --help` for the authoritative text of a command and its JSON fields.
4+
5+Errors are one line on standard error (`ermite: ...`) with exit status 1. `--json` prints stable field names. `ermite completion bash|zsh|fish` completes repository names from the server.
6+
7+## Repositories
8+
9+| Command | Scope | Notes |
10+|---|---|---|
11+| `repo list [--json]` | none | repositories you can see |
12+| `repo show <name> [--json]` | none | |
13+| `repo create <name> [--description TEXT] [--visibility public]` | `repo:write` | private by default |
14+| `repo edit <name> [--description TEXT] [--visibility V] [--default-branch B] [--merge-modes fast-forward,squash] [--failing-checks-block=false]` | `repo:admin` | only the given flags change; `--description ""` clears it; the branch must exist |
15+| `repo delete <name> [--yes]` | `repo:admin` | |
16+
17+Repository JSON: `name`, `description`, `visibility`, `default_branch`, `created_at`, `pushed_at` (null before the first push), `merge_modes`, `failing_checks_block`.
18+
19+## Tokens
20+
21+| Command | Scope | Notes |
22+|---|---|---|
23+| `token create <label> [--preset cli\|agent\|ci] [--scope S] [--repo R] [--expires 30d\|2w\|12h\|2027-01-31] [--json]` | `token:admin` | secret printed once on standard output; there is no default scope |
24+| `token list [--json]` | `token:admin` | secrets are never shown; the admin token is not listed |
25+| `token revoke <id>` | `token:admin` | |
26+
27+Presets add up with `--scope` (repeatable or comma-separated):
28+
29+| Preset | Scopes |
30+|---|---|
31+| `cli` | every scope, for the owner's daily use |
32+| `agent` | `repo:write`, `mr:write` |
33+| `ci` | `repo:read` |
34+
35+Scopes:
36+
37+| Scope | Allows |
38+|---|---|
39+| `repo:read` | read private repositories |
40+| `repo:write` | push, create a repository |
41+| `repo:admin` | delete a repository, change visibility, description, default branch, merge settings |
42+| `mr:write` | open, comment on, resolve, close, mark read |
43+| `mr:merge` | merge |
44+| `token:admin` | create, list and revoke tokens |
45+| `ci:write`, `secrets:write`, `runner:register` | reserved for CI |
46+
47+A token can never grant more than the token that creates it. `--repo` (repeatable) limits it to those repositories; the default is all. Labels are free text up to 100 bytes; `owner` and `root` are reserved. Token JSON: `id`, `label`, `scopes`, `repos`, `expires_at`, `created_at`, `last_used_at`.
48+
49+## Merge requests
50+
51+| Command | Scope | Notes |
52+|---|---|---|
53+| `mr create <repo> --source B --title T [--target B] [--description TEXT\|-]` | `mr:write` | target defaults to the default branch; title of 120 characters max; `-` reads standard input |
54+| `mr list <repo> [--state open\|merged\|closed\|all] [--json]` | none | default `open` |
55+| `mr show <repo> <n> [--diff] [--since-last-read] [--mark-read] [--json]` | `mr:write` for `--mark-read` | commits, changed files and comments; `--diff` adds hunks with line numbers |
56+| `mr comment <repo> <n> -m TEXT\|- [--path P --line N --side old\|new]` | `mr:write` | the line must be in the current diff; a deleted file uses its old path |
57+| `mr resolve <repo> <n> <comment-id> [--undo]` | `mr:write` | doing it twice is not an error |
58+| `mr merge <repo> <n> --head <full-id> [--squash]` | `mr:merge` | refused if the branch moved or the target is not an ancestor of the head |
59+| `mr close <repo> <n>` | `mr:write` | a closed merge request cannot be reopened |
60+
61+Merge request JSON: `repo`, `number`, `title`, `description`, `source_branch`, `target_branch`, `state`, `author` (token label), `created_at`, `updated_at`, `head_id`, `merged_commit_id`, `merge_mode`. `mr show --json` adds `commits`, `diff_base_id`, `stats`, `files` (with `hunks` under `--diff`: `kind`, `old_number`, `new_number`, `text`), `comments`, `last_read_id`, `last_read_lost`.
62+
63+## Events
64+
65+`ermite watch [repo] [--json]` runs until interrupted, reconnects and resumes after the last event. With `--json` it prints one object per line with `id`, `time`, `type` and type-specific fields.
66+
67+| Type | Extra fields |
68+|---|---|
69+| `repo_created`, `repo_updated`, `repo_deleted` | `repo`, `repository` |
70+| `pushed` | `repo`, `ref_updates` (`ref`, `old_id`, `new_id`; an empty id means created or deleted) |
71+| `merge_request_opened`, `merge_request_merged`, `merge_request_closed` | `repo`, `merge_request` |
72+| `comment_added` | `repo`, `number`, `comment` |
73+| `gap` | none: events were lost, reload the state |
74+
75+## Server and web
76+
77+| Command | Notes |
78+|---|---|
79+| `serve` | configured by `ERMITE_*` environment variables only (see the project README) |
80+| `version [--json]` | client version; with `ERMITE_URL`, the server version and features |
81+| `signing-key show` | public key and `allowed_signers` line to check squash commits with `git verify-commit` |
82+| `web login [--json]` | one-time sign-in link (about 60 s); needs the admin token or a token with every scope and no repository list; the link is a secret |
83+| `web logout --all` | signs every browser out |
@@ -0,0 +1,83 @@
1+# ermite CLI reference
2+
3+Remote commands read `ERMITE_URL` (`http://` or `https://`) and `ERMITE_TOKEN` (optional for public reads). Run `ermite <command> --help` for the authoritative text of a command and its JSON fields.
4+
5+Errors are one line on standard error (`ermite: ...`) with exit status 1. `--json` prints stable field names. `ermite completion bash|zsh|fish` completes repository names from the server.
6+
7+## Repositories
8+
9+| Command | Scope | Notes |
10+|---|---|---|
11+| `repo list [--json]` | none | repositories you can see |
12+| `repo show <name> [--json]` | none | |
13+| `repo create <name> [--description TEXT] [--visibility public]` | `repo:write` | private by default |
14+| `repo edit <name> [--description TEXT] [--visibility V] [--default-branch B] [--merge-modes fast-forward,squash] [--failing-checks-block=false]` | `repo:admin` | only the given flags change; `--description ""` clears it; the branch must exist |
15+| `repo delete <name> [--yes]` | `repo:admin` | |
16+
17+Repository JSON: `name`, `description`, `visibility`, `default_branch`, `created_at`, `pushed_at` (null before the first push), `merge_modes`, `failing_checks_block`.
18+
19+## Tokens
20+
21+| Command | Scope | Notes |
22+|---|---|---|
23+| `token create <label> [--preset cli\|agent\|ci] [--scope S] [--repo R] [--expires 30d\|2w\|12h\|2027-01-31] [--json]` | `token:admin` | secret printed once on standard output; there is no default scope |
24+| `token list [--json]` | `token:admin` | secrets are never shown; the admin token is not listed |
25+| `token revoke <id>` | `token:admin` | |
26+
27+Presets add up with `--scope` (repeatable or comma-separated):
28+
29+| Preset | Scopes |
30+|---|---|
31+| `cli` | every scope, for the owner's daily use |
32+| `agent` | `repo:write`, `mr:write` |
33+| `ci` | `repo:read` |
34+
35+Scopes:
36+
37+| Scope | Allows |
38+|---|---|
39+| `repo:read` | read private repositories |
40+| `repo:write` | push, create a repository |
41+| `repo:admin` | delete a repository, change visibility, description, default branch, merge settings |
42+| `mr:write` | open, comment on, resolve, close, mark read |
43+| `mr:merge` | merge |
44+| `token:admin` | create, list and revoke tokens |
45+| `ci:write`, `secrets:write`, `runner:register` | reserved for CI |
46+
47+A token can never grant more than the token that creates it. `--repo` (repeatable) limits it to those repositories; the default is all. Labels are free text up to 100 bytes; `owner` and `root` are reserved. Token JSON: `id`, `label`, `scopes`, `repos`, `expires_at`, `created_at`, `last_used_at`.
48+
49+## Merge requests
50+
51+| Command | Scope | Notes |
52+|---|---|---|
53+| `mr create <repo> --source B --title T [--target B] [--description TEXT\|-]` | `mr:write` | target defaults to the default branch; title of 120 characters max; `-` reads standard input |
54+| `mr list <repo> [--state open\|merged\|closed\|all] [--json]` | none | default `open` |
55+| `mr show <repo> <n> [--diff] [--since-last-read] [--mark-read] [--json]` | `mr:write` for `--mark-read` | commits, changed files and comments; `--diff` adds hunks with line numbers |
56+| `mr comment <repo> <n> -m TEXT\|- [--path P --line N --side old\|new]` | `mr:write` | the line must be in the current diff; a deleted file uses its old path |
57+| `mr resolve <repo> <n> <comment-id> [--undo]` | `mr:write` | doing it twice is not an error |
58+| `mr merge <repo> <n> --head <full-id> [--squash]` | `mr:merge` | refused if the branch moved or the target is not an ancestor of the head |
59+| `mr close <repo> <n>` | `mr:write` | a closed merge request cannot be reopened |
60+
61+Merge request JSON: `repo`, `number`, `title`, `description`, `source_branch`, `target_branch`, `state`, `author` (token label), `created_at`, `updated_at`, `head_id`, `merged_commit_id`, `merge_mode`. `mr show --json` adds `commits`, `diff_base_id`, `stats`, `files` (with `hunks` under `--diff`: `kind`, `old_number`, `new_number`, `text`), `comments`, `last_read_id`, `last_read_lost`.
62+
63+## Events
64+
65+`ermite watch [repo] [--json]` runs until interrupted, reconnects and resumes after the last event. With `--json` it prints one object per line with `id`, `time`, `type` and type-specific fields.
66+
67+| Type | Extra fields |
68+|---|---|
69+| `repo_created`, `repo_updated`, `repo_deleted` | `repo`, `repository` |
70+| `pushed` | `repo`, `ref_updates` (`ref`, `old_id`, `new_id`; an empty id means created or deleted) |
71+| `merge_request_opened`, `merge_request_merged`, `merge_request_closed` | `repo`, `merge_request` |
72+| `comment_added` | `repo`, `number`, `comment` |
73+| `gap` | none: events were lost, reload the state |
74+
75+## Server and web
76+
77+| Command | Notes |
78+|---|---|
79+| `serve` | configured by `ERMITE_*` environment variables only (see the project README) |
80+| `version [--json]` | client version; with `ERMITE_URL`, the server version and features |
81+| `signing-key show` | public key and `allowed_signers` line to check squash commits with `git verify-commit` |
82+| `web login [--json]` | one-time sign-in link (about 60 s); needs the admin token or a token with every scope and no repository list; the link is a secret |
83+| `web logout --all` | signs every browser out |
A skills/ermite/SKILL.md +73 -0
@@ -0,0 +1,73 @@
1+---
2+name: ermite
3+description: Explains how to use an ermite Git forge and its CLI - clone and push over HTTPS, repositories, tokens and scopes, merge requests (review, comment, merge), live events, and running the server. Use when the user mentions ermite, runs `ermite` commands, pushes to or reviews on an ermite server, or self-hosts one.
4+---
5+
6+# ermite
7+
8+ermite is a single-user Git forge in one binary. `ermite serve` runs the server; every other `ermite` command is a client that talks to a running server over its API. The owner holds the admin token and creates scoped tokens for themselves, agents and CI.
9+
10+## Connect
11+
12+```sh
13+export ERMITE_URL=https://git.example.com
14+export ERMITE_TOKEN=ermite_... # optional for public reads
15+ermite version # client and server versions, warns about missing features
16+ermite repo list
17+```
18+
19+Never print a token, commit it, log it or paste it into a chat. Prefer a Git credential helper to a token in a URL. Use `https://`: a token sent over plain `http://` to a remote host triggers a warning.
20+
21+## Git
22+
23+```sh
24+git clone https://git.example.com/<repo>.git # public: no credentials
25+git push https://git.example.com/<repo>.git main # password = token, username ignored
26+```
27+
28+- Pushing to a name that does not exist creates a private repository (needs `repo:write`).
29+- Names are lowercase `[a-z0-9._-]`, 1 to 100 characters.
30+- Private repositories need `repo:read` to clone or browse.
31+
32+## Review a merge request
33+
34+1. List: `ermite mr list <repo> --json`.
35+2. Read: `ermite mr show <repo> <n> --diff --json`. Keep `head_id`; take line numbers from the hunks.
36+3. Comment on a line: `ermite mr comment <repo> <n> -m "text" --path <file> --line <n> --side new`. Without `--path` the comment is general. The line must appear in the diff.
37+4. Merge only when asked: `ermite mr merge <repo> <n> --head <head_id>`, with `--squash` for one commit signed by the server.
38+
39+The merge is refused when the branch moved since `head_id` (review again) or when the target is not an ancestor of the head (rebase and push again). The repository may allow only one merge mode.
40+
41+Open one: `ermite mr create <repo> --source <branch> --title "..."`. After new pushes, `mr show --since-last-read` shows only what changed since `--mark-read`.
42+
43+## Tokens
44+
45+```sh
46+ermite token create my-agent --preset agent --repo <repo> --expires 30d
47+```
48+
49+The secret is printed once. Presets: `agent` (push, open and comment on merge requests), `ci` (read), `cli` (everything). Add `--scope mr:merge` to let an agent merge. A token can never grant more than the token that creates it. Full scope list: [CLI.md](CLI.md).
50+
51+## Follow events
52+
53+`ermite watch [repo] --json` prints one JSON object per event (pushes, repositories, merge requests, comments). It reconnects and resumes on its own; a `gap` event means some events were lost, so reload the state.
54+
55+## Run a server
56+
57+```sh
58+token=$(head -c 32 /dev/urandom | base64) # the root credential: store it safely
59+docker run -d -p 127.0.0.1:7341:7341 -v ermite-data:/data \
60+ -e ERMITE_PUBLIC_URL=https://git.example.com -e ERMITE_ADMIN_TOKEN="$token" <ermite-image>
61+```
62+
63+- Required: `ERMITE_DATA_DIR` (the image uses `/data`), `ERMITE_PUBLIC_URL`, `ERMITE_ADMIN_TOKEN` (32+ characters). It needs git 2.45 or newer.
64+- Put TLS on a reverse proxy and list its network in `ERMITE_TRUSTED_PROXIES`.
65+- Health check: `GET /-/health`.
66+- Owner web access: `ermite web login` prints a one-time link (about 60 s, 12 h session).
67+- If a page or a read looks wrong, set `ERMITE_GIT_READER=cli` and restart: every read then uses the `git` binary.
68+
69+## Output conventions
70+
71+`--json` prints stable field names, listed in each command's `--help`. Errors are one line on standard error (`ermite: ...`) with exit status 1. `ermite completion bash|zsh|fish` completes repository names.
72+
73+Every command, flag, scope and JSON field: [CLI.md](CLI.md).
@@ -0,0 +1,73 @@
1+---
2+name: ermite
3+description: Explains how to use an ermite Git forge and its CLI - clone and push over HTTPS, repositories, tokens and scopes, merge requests (review, comment, merge), live events, and running the server. Use when the user mentions ermite, runs `ermite` commands, pushes to or reviews on an ermite server, or self-hosts one.
4+---
5+
6+# ermite
7+
8+ermite is a single-user Git forge in one binary. `ermite serve` runs the server; every other `ermite` command is a client that talks to a running server over its API. The owner holds the admin token and creates scoped tokens for themselves, agents and CI.
9+
10+## Connect
11+
12+```sh
13+export ERMITE_URL=https://git.example.com
14+export ERMITE_TOKEN=ermite_... # optional for public reads
15+ermite version # client and server versions, warns about missing features
16+ermite repo list
17+```
18+
19+Never print a token, commit it, log it or paste it into a chat. Prefer a Git credential helper to a token in a URL. Use `https://`: a token sent over plain `http://` to a remote host triggers a warning.
20+
21+## Git
22+
23+```sh
24+git clone https://git.example.com/<repo>.git # public: no credentials
25+git push https://git.example.com/<repo>.git main # password = token, username ignored
26+```
27+
28+- Pushing to a name that does not exist creates a private repository (needs `repo:write`).
29+- Names are lowercase `[a-z0-9._-]`, 1 to 100 characters.
30+- Private repositories need `repo:read` to clone or browse.
31+
32+## Review a merge request
33+
34+1. List: `ermite mr list <repo> --json`.
35+2. Read: `ermite mr show <repo> <n> --diff --json`. Keep `head_id`; take line numbers from the hunks.
36+3. Comment on a line: `ermite mr comment <repo> <n> -m "text" --path <file> --line <n> --side new`. Without `--path` the comment is general. The line must appear in the diff.
37+4. Merge only when asked: `ermite mr merge <repo> <n> --head <head_id>`, with `--squash` for one commit signed by the server.
38+
39+The merge is refused when the branch moved since `head_id` (review again) or when the target is not an ancestor of the head (rebase and push again). The repository may allow only one merge mode.
40+
41+Open one: `ermite mr create <repo> --source <branch> --title "..."`. After new pushes, `mr show --since-last-read` shows only what changed since `--mark-read`.
42+
43+## Tokens
44+
45+```sh
46+ermite token create my-agent --preset agent --repo <repo> --expires 30d
47+```
48+
49+The secret is printed once. Presets: `agent` (push, open and comment on merge requests), `ci` (read), `cli` (everything). Add `--scope mr:merge` to let an agent merge. A token can never grant more than the token that creates it. Full scope list: [CLI.md](CLI.md).
50+
51+## Follow events
52+
53+`ermite watch [repo] --json` prints one JSON object per event (pushes, repositories, merge requests, comments). It reconnects and resumes on its own; a `gap` event means some events were lost, so reload the state.
54+
55+## Run a server
56+
57+```sh
58+token=$(head -c 32 /dev/urandom | base64) # the root credential: store it safely
59+docker run -d -p 127.0.0.1:7341:7341 -v ermite-data:/data \
60+ -e ERMITE_PUBLIC_URL=https://git.example.com -e ERMITE_ADMIN_TOKEN="$token" <ermite-image>
61+```
62+
63+- Required: `ERMITE_DATA_DIR` (the image uses `/data`), `ERMITE_PUBLIC_URL`, `ERMITE_ADMIN_TOKEN` (32+ characters). It needs git 2.45 or newer.
64+- Put TLS on a reverse proxy and list its network in `ERMITE_TRUSTED_PROXIES`.
65+- Health check: `GET /-/health`.
66+- Owner web access: `ermite web login` prints a one-time link (about 60 s, 12 h session).
67+- If a page or a read looks wrong, set `ERMITE_GIT_READER=cli` and restart: every read then uses the `git` binary.
68+
69+## Output conventions
70+
71+`--json` prints stable field names, listed in each command's `--help`. Errors are one line on standard error (`ermite: ...`) with exit status 1. `ermite completion bash|zsh|fish` completes repository names.
72+
73+Every command, flag, scope and JSON field: [CLI.md](CLI.md).

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 45

↑↓ moveenter openesc close