refactor: turn the repo into a two-plugin marketplace

tea and tdl were two repositories, each carrying its own
.claude-plugin/marketplace.json — two marketplaces to register for what
is one collection. Fold them into one.

The repo root is now the marketplace and nothing else: a single
.claude-plugin/marketplace.json whose entries point at ./plugins/tea and
./plugins/tdl. A plugin's root is its own directory under plugins/, so
${CLAUDE_PLUGIN_ROOT} still resolves inside it and every path a plugin
uses stays relative to itself — the hooks and the test roots needed no
adjustment beyond the move.

tea's files move with git mv, so its history and blame follow. tdl
arrives as a plain copy; its history stays in claude-skills/threedotslab.

test_payload_root asserted `tmp/` was ignored by REPO/.gitignore. The
rule is that tmp/ is ignored, not which file says so, and git reads every
.gitignore on the way up — so the test now walks up to the repo root the
same way git does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
naudachu
2026-08-11 00:25:28 +05:00
parent 23f78beafb
commit 83f73c5cea
69 changed files with 4187 additions and 168 deletions
+169
View File
@@ -0,0 +1,169 @@
---
name: use
description: Reference docs for the `tea` CLI — Gitea's command-line client. Load when the user asks about Gitea repos, pulls, releases, milestones, labels, actions, webhooks, or other Gitea entities, to look up the right `tea` command and flags. Always write the login as the literal placeholder --login "$GITEA_LOGIN" — the tea-guard hook substitutes the operator-pinned login; set it with /tea:auth. Issues are NOT handled here: use /tea:issue to work on them and /tea:sync to move them to and from Gitea.
---
# /tea:use — tea CLI reference
Reference material for the `tea` CLI (Gitea's official command-line client).
Use these docs to look up commands, flags, filters, and output fields before
running `tea` via Bash.
## Issues are somewhere else
Do **not** reach for `tea issues` or `tea api .../issues/...` to read or create
an issue. Two skills own that, and they keep the payload out of your context:
| Skill | Scope |
|---|---|
| `/tea:issue` | issues as units of work — create, read, grep, validate, dependency graph. Offline. |
| `/tea:sync` | moving issues between the local store and Gitea — pull, push, comment. |
This skill covers everything else Gitea has: pulls, releases, milestones,
labels, repos, branches, actions, webhooks, notifications, times.
## Login: always write the placeholder, never a name (enforced)
Every `tea` invocation that touches Gitea MUST carry the login as the **literal
placeholder** `--login "$GITEA_LOGIN"` (or `-l "$GITEA_LOGIN"`). Do **not**
substitute an actual login name yourself.
The **`tea-guard`** PreToolUse hook enforces this and resolves it:
- no `--login` → blocked.
- `--login "$GITEA_LOGIN"` → the hook reads the operator's pinned login from
`.claude/settings.local.json` (`env.GITEA_LOGIN`) **at call time** and
rewrites the command to use that literal before it runs.
- `--login <some-name>` or any other variable → blocked. You may not choose the
login; only the operator does (via `/tea:auth`).
- no login pinned → blocked with a pointer to run `/tea:auth`.
Why: without an explicit login `tea` silently falls back to the machine's
default (possibly the user's personal account), and a login *you* pick may be
the wrong identity. Pinning is the operator's decision; the hook guarantees it.
The pin takes effect immediately — no restart. Only `tea logins list` and
`tea --version/--help` are exempt from the guard.
## How to use
1. Identify the entity in the request: pulls, labels, milestones, releases,
times, repos, branches, actions, webhooks, notifications, etc.
2. Find the matching command in the index below.
3. Run it via Bash with the placeholder login, e.g.
`tea pulls list --login "$GITEA_LOGIN" --repo owner/repo --state open`.
(The hook rewrites `"$GITEA_LOGIN"` to the operator-pinned login.)
`tea` auto-detects owner/repo from `$PWD` inside a git repo; otherwise pass
`--repo owner/repo` (or `-r`). Login is **not** auto-detected — it is pinned
per-project by the operator (see `/tea:auth`) and injected by the guard.
Config lives in `$XDG_CONFIG_HOME/tea`.
### `--repo` takes a slug — except where a checkout is required
A few commands touch local git, not just the API, and for those `--repo`
**must be a path to a checkout**; a slug is rejected:
```
Error: local repository required: execute from a repo dir, or specify a path with --repo
```
The message reads like the flag is missing even when it was passed. Confirmed
for `pulls create`, `pulls checkout` and `pulls clean` (tea 0.14.x). Everything
that is only an API call — `pulls list`, `milestones`, `releases`, `times`,
`labels`, `issues` — takes the slug from any directory.
Three working forms for `pulls create`:
```bash
# 1. cwd inside the checkout, no --repo at all
tea pulls create --login "$GITEA_LOGIN" --head feat/x --base main \
--title "…" --description "…"
# 2. from anywhere, --repo as a PATH (this is also the git-worktree answer:
# point it at the main checkout)
tea pulls create --login "$GITEA_LOGIN" --repo /path/to/checkout \
--head feat/x --base main --title "…" --description "…"
# 3. no checkout in reach — POST it, where owner/repo is a slug again
tea api --login "$GITEA_LOGIN" -X POST -d @tmp/pull/x.json \
repos/{owner}/{repo}/pulls
```
## Index
- [tea CLI overview](references/tea/index.md) — global flags, common options, output formats
- [ENTITIES](references/tea/entities.md) — issues, pulls, labels, milestones, releases, times, repos, branches, actions, webhooks, comment
- [HELPERS](references/tea/helpers.md) — open, notifications, clone, api
- [MISC](references/tea/misc.md) — whoami, admin
- [SETUP](references/tea/setup.md) — logins, logout, ssh-keys
The canonical issue format moved to
[`../issue/references/format.md`](../issue/references/format.md) — it describes
local files, not `tea` commands.
## Rich payloads — write to `$PWD/tmp/` first, then `tea api`
Entity subcommands (`tea comment`, `tea pulls create`, `tea releases create`, …)
are built for humans at a TTY. With a large or formatted body they can hang
silently — an empty-looking positional arg triggers `$EDITOR` fallback, or a
scope/confirm prompt waits on a TTY that doesn't exist. The harness eventually
kills the process (e.g. exit 144 = 128 + SIGURG on macOS).
**Rule:** for any non-trivial body (multi-line, or containing markdown / code
fences / backticks / pipes / tables), bypass entity commands. Save the full
request payload to `$PWD/tmp/` first, then POST via `tea api`.
Issues and issue comments are already wrapped — use `/tea:sync` rather than
hand-rolling their JSON. The procedure below covers everything else.
### Procedure
1. Ensure the target dir exists: `mkdir -p tmp/{kind}` where `{kind}` is
`pull`, `release`, etc.
2. Write the **complete request body as JSON** to `$PWD/tmp/{kind}/<slug>.json`.
One file = one request. Use a quoted heredoc to avoid shell expansion:
```bash
mkdir -p tmp/release
cat > tmp/release/v0-2-0.json <<'EOF'
{"tag_name": "v0.2.0", "name": "v0.2.0", "body": "## Changes\n\nMulti-line markdown with `code`."}
EOF
```
Newlines inside the body must be encoded as `\n` in the JSON string. If
composing programmatically, pipe through
`jq -Rs '{body: .}' < body.md > tmp/release/v0-2-0.json`.
3. POST with `tea api`, passing the file with `-d @<path>`:
```bash
tea api --login "$GITEA_LOGIN" \
-X POST -d @tmp/release/v0-2-0.json \
repos/{owner}/{repo}/releases
```
4. Keep the file. `tmp/` should be gitignored; the saved payload is useful for
retries, edits (`PATCH`), and debugging failed posts.
### Common endpoints
| Action | Method + endpoint |
|---|---|
| Create PR | `POST repos/{owner}/{repo}/pulls` |
| Edit PR body or title | `PATCH repos/{owner}/{repo}/issues/{n}` |
| Comment on a PR | `POST repos/{owner}/{repo}/issues/{n}/comments` |
| Edit comment | `PATCH repos/{owner}/{repo}/issues/comments/{id}` |
| Create release | `POST repos/{owner}/{repo}/releases` |
| Create milestone | `POST repos/{owner}/{repo}/milestones` |
Short single-line bodies (e.g. `tea comment 42 "lgtm" --login "$GITEA_LOGIN"`)
are still fine via entity commands. Always the placeholder, never a login name.
## Tips
- Pass `-o json` for structured output when parsing programmatically — on
**entity commands only**. On `tea api`, `-o` is a *file name*: `-o json`
writes the response body to a file called `json` and leaves stdout empty.
The response is already JSON, so there is nothing to format; use `-` for
stdout, or leave the flag off.
- Use `--fields, -f` to narrow columns.
- Pagination: `--page, -p <n>` and `--limit, --lm <n>` (defaults 1 / 30).
- If a `tea` command is blocked by `tea-guard`: either you forgot
`--login "$GITEA_LOGIN"`, you wrote a literal login name instead of the
placeholder (not allowed — let the guard substitute), or no login is pinned
(run `/tea:auth`).
@@ -0,0 +1,137 @@
# tea CLI — ENTITIES
See [`./index.md`](./index.md) for global options and common flags shared by all commands.
## `tea issues` (aliases: `issue`, `i`)
Without args lists issues; with `<index>` shows issue detail.
Shared filters: `--state {all|open|closed}` (default: open), `--kind {issues|pulls|all}`, `--keyword/-k`, `--labels/-L`, `--milestones/-m`, `--author/-A`, `--assignee/-a`, `--mentions/-M`, `--owner/--org`, `--from/-F`, `--until/-u`, `--comments`. Available fields: `index,state,kind,author,author-id,url,title,body,created,updated,deadline,assignees,milestone,labels,comments,owner,repo`.
Subcommands:
- `list, ls` — list (same filters as above).
- `create, c` — create an issue. Options: `--title/-t`, `--description/-d`, `--assignees/-a`, `--labels/-L`, `--milestone/-m`, `--deadline/-D`, `--referenced-version/-v` (commit hash or tag).
- `edit, e <idx>...` — edit. `--title`, `--description`, `--add-assignees/-a`, `--add-labels/-L`, `--remove-labels`, `--milestone`, `--deadline`, `--referenced-version`. To unset a value pass an empty string (`--milestone ""`).
- `reopen, open <idx>...`
- `close <idx>...`
## `tea pulls` (aliases: `pull`, `pr`)
Without args lists PRs; with `<index>` shows PR detail. Fields: `index,state,author,author-id,url,title,body,mergeable,base,base-commit,head,diff,patch,created,updated,deadline,assignees,milestone,labels,comments,ci`.
Subcommands:
- `list, ls` (`--state`)
- `checkout, co <idx>` — check out PR locally. `--branch/-b` creates a local branch if missing. Needs a checkout, same as `create`: `--repo` is a path here, not a slug.
- `clean <idx>` — delete local and remote feature branches for a closed PR. `--ignore-sha` matches branch by name instead of commit hash. Needs a checkout, same as `create`.
- `create, c` — create a PR. `--head <user:branch>`, `--base/-b`, `--allow-maintainer-edits/--edits`, `--agit`, `--topic`, plus all issue-style fields (`--title`, `--description`, `--assignees`, `--labels`, `--milestone`, `--deadline`, `--referenced-version`).
**Needs a local checkout.** `--repo owner/repo` is *not* accepted here — the
slug fails with `local repository required: execute from a repo dir, or
specify a path with --repo`, whose advice reads like the flag was missing.
Run it with cwd inside the checkout and no `--repo`, or pass `--repo
/path/to/checkout`. From a git worktree, point `--repo` at the main
checkout. With no checkout in reach, `POST repos/{owner}/{repo}/pulls`
through `tea api`, which takes the slug.
- `close <idx>...`, `reopen, open <idx>...`
- `edit, e <idx>...` — like `issues edit` plus `--add-reviewers/-r`, `--remove-reviewers`.
- `review <idx>` — interactive review.
- `approve, lgtm, a <idx> [comment]`
- `reject <idx> <reason>`
- `merge, m <idx>``--style/-s {merge|rebase|squash|rebase-merge}` (default merge), `--title/-t`, `--message/-m`.
- `review-comments, rc <idx>` — list review comments. Fields: `id,body,reviewer,path,line,resolver,created,updated,url`.
- `resolve <comment-id>` / `unresolve <comment-id>`
## `tea labels` (alias: `label`)
- `list, ls``--save/-s` dumps labels to a file.
- `create, c``--name`, `--color`, `--description`, `--file` (bulk import from file).
- `update``--id`, `--name`, `--color`, `--description`.
- `delete, rm``--id`.
## `tea milestones` (aliases: `milestone`, `ms`)
Fields: `title,state,items_open,items_closed,items,duedate,description,created,updated,closed,id`.
- `list, ls` (`--state`)
- `create, c``--title/-t`, `--description/-d`, `--deadline/--expires/-x`, `--state`.
- `close <name>...``--force/-f` deletes instead of closing.
- `reopen, open <name>...`
- `delete, rm <name>`
- `issues, i <name>` — manage milestone contents:
- `add, a <name> <issue-idx>`
- `remove, r <name> <issue-idx>`
## `tea releases` (aliases: `release`, `r`)
- `list, ls`
- `create, c [<tag>]``--tag`, `--target` (branch/commit), `--title/-t`, `--note/-n`, `--note-file/-f`, `--draft/-d`, `--prerelease/-p`, `--asset/-a <path>` (repeatable).
- `edit, e <tag>...``--tag`, `--target`, `--title/-t`, `--note/-n`, `--draft/-d <bool>`, `--prerelease/-p <bool>`.
- `delete, rm <tag>...``--confirm/-y` required; `--delete-tag` also removes the git tag.
- `assets, asset, a` — manage release attachments:
- `list, ls <tag>`
- `create, c <tag> <asset>...`
- `delete, rm <tag> <attachment-name>...``--confirm/-y`.
## `tea times` (aliases: `time`, `t`)
Time tracking on issues/PRs. Fields: `id,created,repo,issue,user,duration`. Command-level: `--from/-f`, `--until/-u`, `--total/-t`, `--mine/-m`.
- `add, a <issue> <duration>` — e.g. `tea times add 1 1h25m`.
- `delete, rm <issue> <time-id>`
- `reset <issue>`
- `list, ls [username | #issue]` — username filters by user on the repo; `#N` filters by issue; `--mine` aggregates across all repos.
## `tea organizations` (aliases: `organization`, `org`)
- `list, ls`
- `create, c <name>``--full-name/-n`, `--description/-d`, `--website/-w`, `--location/-L`, `--visibility/-v`, `--repo-admins-can-change-team-access`.
- `delete, rm <name>`
## `tea repos` (alias: `repo`)
Fields: `description,forks,id,name,owner,stars,ssh,updated,url,permission,type`.
- `list, ls``--watched/-w`, `--starred/-s`, `--owner/-O`, `--type/-T {fork|mirror|source}`.
- `search, s [term]``--topic/-t`, `--type/-T`, `--owner/-O`, `--private {true|false}`, `--archived {true|false}`.
- `create, c``--name`, `--owner/-O`, `--private`, `--description/--desc`, `--init`, `--labels`, `--gitignores/--git`, `--license`, `--readme`, `--branch`, `--template`, `--trustmodel {committer|collaborator|collaborator+committer}`, `--object-format {sha1|sha256}`.
- `create-from-template, ct``--template/-t`, `--name/-n`, `--owner/-O`, `--private`, `--description/--desc`, copy toggles: `--content`, `--githooks`, `--avatar`, `--labels`, `--topics`, `--webhooks`.
- `fork, f``--owner/-O` (default: current user).
- `migrate, m``--name`, `--owner`, `--clone-url`, `--service {git|gitea|gitlab|gogs}`, `--mirror`, `--mirror-interval`, `--private`, `--template`, copy toggles: `--wiki`, `--issues`, `--labels`, `--pull-requests`, `--releases`, `--milestones`, `--lfs`, `--lfs-endpoint`, auth: `--auth-user`, `--auth-password`, `--auth-token`.
- `delete, rm``--name`, `--owner/-O`, `--force/-f`.
- `edit, e``--name`, `--description/--desc`, `--website`, `--private <bool>`, `--template <bool>`, `--archived <bool>`, `--default-branch`.
## `tea branches` (aliases: `branch`, `b`)
Fields: `name,protected,user-can-merge,user-can-push,protection`.
- `list, ls`
- `protect, P <branch>` — enable branch protection.
- `unprotect, U <branch>` — remove protection.
- `rename, rn <old> <new>`
## `tea actions` (alias: `action`)
CI management: secrets, variables, workflow definitions, workflow runs.
### `tea actions secrets` (alias: `secret`)
- `list, ls`
- `create, add, set <name> [value]``--file` or `--stdin` to read the value.
- `delete, remove, rm <name>``--confirm/-y`.
### `tea actions variables` (aliases: `variable`, `vars`, `var`)
- `list, ls``--name` to fetch a single variable.
- `set, create, update <name> [value]``--file`, `--stdin`.
- `delete, remove, rm <name>``--confirm/-y`.
### `tea actions runs` (alias: `run`)
- `list, ls``--status {success|failure|pending|queued|in_progress|skipped|canceled}`, `--branch`, `--event`, `--actor`, `--since`, `--until`.
- `view, show, get <run-id>``--jobs` prints the jobs table.
- `delete, remove, rm, cancel <run-id>``--confirm/-y`.
- `logs, log <run-id>``--job <id>`, `--follow/-f` (requires the job to be in progress).
### `tea actions workflows` (alias: `workflow`)
- `list, ls`
- `view, show, get <workflow-id>`
- `dispatch, trigger, run <workflow-id>``--ref/-r`, `--input/-i key=value` (repeatable), `--follow/-f`.
- `enable <workflow-id>`
- `disable <workflow-id>``--confirm/-y`.
## `tea webhooks` (aliases: `webhook`, `hooks`, `hook`)
Scope is selected by flag: `--repo`, `--org`, `--global`.
- `list, ls`
- `create, c <webhook-url>``--type {gitea|gogs|slack|discord|dingtalk|telegram|msteams|feishu|wechatwork|packagist}` (default: gitea), `--secret`, `--events` (default: push), `--active`, `--branch-filter`, `--authorization-header`.
- `update, edit, u <id>``--url`, `--secret`, `--events`, `--active` / `--inactive`, `--branch-filter`, `--authorization-header`.
- `delete, rm <id>``--confirm/-y`.
## `tea comment, c <issue/pr index> [body]`
Add a comment to an issue or PR. Body may be passed as an argument or supplied interactively.
@@ -0,0 +1,30 @@
# tea CLI — HELPERS
See [`./index.md`](./index.md) for global options and common flags shared by all commands.
## `tea open, o`
Open the current repository/context in a web browser.
## `tea notifications` (aliases: `notification`, `n`)
Defaults to the current repo; `--mine/-m` aggregates across all your repos. Fields: `id,status,updated,index,type,state,title,repository`. Filters: `--types/-t {issue|pull|repository|commit}`, `--states/-s {pinned|unread|read}` (default: `unread,pinned`).
- `ls, list`
- `read, r [all | <id>]`
- `unread, u [all | <id>]`
- `pin, p [all | <id>]`
- `unpin [all | <id>]`
## `tea clone, C <repo-slug> [target-dir]`
Clone without requiring a local git install. Accepts slug forms: `gitea/tea`, `tea`, `gitea.com/gitea/tea`, `git@gitea.com:gitea/tea`, `https://gitea.com/gitea/tea`, `ssh://gitea.com:22/gitea/tea`. A host in the slug overrides `--login`. Options: `--depth/-d`, `--login/-l`.
## `tea api <endpoint>`
Authenticated HTTP request to the Gitea API. Endpoints are auto-prefixed with `/api/v1/` unless they start with `/api/` or `http(s)://`. Placeholders `{owner}` and `{repo}` are filled from the repo context.
- `--method/-X {GET|POST|PUT|PATCH|DELETE}` (default GET; switches to POST automatically when a body is provided)
- `--field/-f key=value` — string field on body (repeatable).
- `--Field/-F key=value` — typed field (numbers, booleans, null, JSON arrays/objects); `@file` or `@-` (stdin); `"null"` forces literal string.
- `--data/-d` — raw JSON body (`@file` / `@-`). Incompatible with `-f`/`-F`.
- `--header/-H key:value` (repeatable)
- `--include/-i` — write status + response headers to stderr.
- `--output/-o <file>` — write response body to file (`-` = stdout). **Not the entity commands' format flag**: `-o json` here creates a file named `json` and prints nothing. The body is already JSON.
- Quote the endpoint if it contains `?` or `&` to prevent shell expansion.
@@ -0,0 +1,36 @@
# tea CLI — Index
Version: `tea 0.14.1` (go-sdk v0.25.1). Source: recursive `--help` traversal. Upstream: https://gitea.com/gitea/tea
`tea` is a productivity helper for Gitea. It uses the current git repository context (`$PWD`) — owner/repo/login are auto-detected when inside a repo. Config is persisted in `$XDG_CONFIG_HOME/tea`.
## Global options
- `--debug, --vvv` — enable debug mode
- `--help, -h`, `--version, -v`
## Common flags (present on nearly every command)
| Flag | Purpose |
|---|---|
| `--login, -l <name>` | use a specific login from the config |
| `--repo, -r <owner/repo>` | override repository context (local path or slug). **A slug only works where the command is pure API.** `pulls create`, `pulls checkout` and `pulls clean` need a real checkout and read this flag as a path — see [SKILL.md](../../SKILL.md) |
| `--remote, -R <name>` | discover login from this git remote |
| `--output, -o <fmt>` | output format: `simple, table, csv, tsv, yaml, json`. **Entity commands only** — on `tea api` the same flag is a FILE NAME, see [HELPERS](./helpers.md) |
| `--page, -p <n>` / `--limit, --lm <n>` | pagination (defaults 1 / 30) |
| `--fields, -f <list>` | which columns to print |
## Command categories
```
ENTITIES: issues, pulls, labels, milestones, releases, times,
organizations, repos, branches, actions, webhooks, comment
HELPERS: open, notifications, clone, api
MISC: whoami, admin
SETUP: logins, logout, ssh-keys
```
- [ENTITIES](./entities.md)
- [HELPERS](./helpers.md)
- [MISC](./misc.md)
- [SETUP](./setup.md)
@@ -0,0 +1,17 @@
# tea CLI — MISCELLANEOUS
See [`./index.md`](./index.md) for global options and common flags shared by all commands.
## `tea whoami`
Show the currently logged in user.
## `tea admin, a`
Operations requiring admin access on the Gitea instance.
### `tea admin users` (alias: `u`)
Fields: `id,login,full_name,email,avatar_url,language,is_admin,restricted,prohibit_login,location,website,description,visibility,activated,lastlogin_at,created_at`.
- `list, ls`
- `create, add, new``--username/-u`, `--password/-p` / `--password-file` / `--password-stdin`, `--email/-e`, `--full-name`, `--admin`, `--restricted`, `--prohibit-login`, `--no-must-change-password`, `--visibility {public|limited|private}`.
- `edit, update, e, u <username>` — paired flags: `--password` (or `--password-file`/`--password-stdin`), `--email/-e`, `--full-name`, `--description`, `--website`, `--location`, `--admin`/`--no-admin`, `--restricted`/`--no-restricted`, `--prohibit-login`/`--allow-login`, `--active`/`--inactive`, `--no-must-change-password`, `--visibility`, `--max-repo-creation` (-1 = unlimited), `--allow-git-hook`/`--no-allow-git-hook`, `--allow-import-local`/`--no-allow-import-local`, `--allow-create-organization`/`--no-allow-create-organization`.
- `delete, rm, remove <username>``--confirm/-y`.
@@ -0,0 +1,19 @@
# tea CLI — SETUP
See [`./index.md`](./index.md) for global options and common flags shared by all commands.
## `tea logins` (alias: `login`)
- `list, ls`
- `add` — interactive when called without args. `--name/-n`, `--url/-u` (`$GITEA_SERVER_URL`), `--token/-t` (`$GITEA_SERVER_TOKEN`), `--user` (`$GITEA_SERVER_USER`), `--password/--pwd` (`$GITEA_SERVER_PASSWORD`), `--otp` (`$GITEA_SERVER_OTP`), `--scopes` (`$GITEA_SCOPES`), `--ssh-key/-s`, `--ssh-agent-principal/-c`, `--ssh-agent-key/-a`, `--insecure/-i`, `--no-version-check/--nv`, `--helper/-j`, `--oauth/-o` (plus `--client-id`, `--redirect-url`).
- `edit, e` — interactive.
- `delete, rm <name>`
- `default [<login>]` — get or set the default login.
- `oauth-refresh [<login>]` — refresh an OAuth token (opens browser if the refresh token is also expired).
## `tea logout <name>`
Remove a stored login.
## `tea ssh-keys` (alias: `ssh-key`)
- `list, ls`
- `add <key-file>``--title/-t` (defaults to filename without extension).
- `delete, rm <key-id>``--confirm/-y`.