Convert the standalone `tea` skill into a skills-dir plugin so commands are
namespaced and an enforcement hook can ship with it:
- /tea:login — pin the project Gitea login into .claude/settings.local.json
- /tea:use — tea CLI reference (was the old root SKILL.md), with the
login rule slimmed since the hook now enforces it
- hooks/tea-guard.sh — PreToolUse(Bash) guard: blocks any `tea` command that
touches Gitea unless it carries --login and $GITEA_LOGIN is set. Exempts
`tea logins list` and `tea --version/--help` so /tea:login can bootstrap.
References moved under skills/use/references/. `claude plugin validate` passes;
guard unit-tested across allow/block cases.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.7 KiB
name, description
| name | description |
|---|---|
| use | Reference docs for the `tea` CLI — Gitea's command-line client. Load when the user asks about Gitea repos, issues, pulls, releases, actions, or other Gitea entities, to look up the right `tea` command and flags. Every tea call must carry --login "$GITEA_LOGIN" (enforced by the tea-guard hook; set it with /tea:login). |
/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.
Login is mandatory (enforced)
Every tea invocation that touches Gitea MUST include --login "$GITEA_LOGIN"
(or -l "$GITEA_LOGIN"). This is enforced by the tea-guard PreToolUse
hook — a tea command without --login is blocked before it runs. If
$GITEA_LOGIN is unset, run /tea:login to pin one.
Why: without --login, tea silently falls back to the machine's default
login (possibly the user's personal account) and writes under the wrong
identity. The login value is pinned per-project in .claude/settings.local.json
under env.GITEA_LOGIN. Only tea logins list and tea --version/--help are
exempt from the guard.
How to use
- Identify the entity in the request: issues, pulls, labels, milestones, releases, times, repos, branches, actions, webhooks, comments, notifications, etc.
- Find the matching command in the index below.
- Run it via Bash with the login, e.g.
tea issues list --login "$GITEA_LOGIN" --repo owner/repo --state open.
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 (see /tea:login). Config lives in $XDG_CONFIG_HOME/tea.
Index
- tea CLI overview — global flags, common options, output formats
- ENTITIES — issues, pulls, labels, milestones, releases, times, repos, branches, actions, webhooks, comment
- HELPERS — open, notifications, clone, api
- MISC — whoami, admin
- SETUP — logins, logout, ssh-keys
Rich payloads — write to $PWD/tmp/ first, then tea api
Entity subcommands (tea comment, tea issues create, tea pulls 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.
Procedure
- Ensure the target dir exists:
mkdir -p tmp/{kind}where{kind}iscomment,issue,pull,release, etc. - 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:Newlines inside the body must be encoded asmkdir -p tmp/comment cat > tmp/comment/issue-60.json <<'EOF' {"body": "## Heading\n\nMulti-line markdown with `code`, | tables |, and ```fences```."} EOF\nin the JSON string. If composing programmatically, pipe throughjq -Rs '{body: .}' < body.md > tmp/comment/issue-60.json. - POST with
tea api, passing the file with-d @<path>:tea api --login "$GITEA_LOGIN" \ -X POST -d @tmp/comment/issue-60.json \ repos/{owner}/{repo}/issues/60/comments - 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 |
|---|---|
| Comment on issue/PR | POST repos/{owner}/{repo}/issues/{n}/comments |
| Edit comment | PATCH repos/{owner}/{repo}/issues/comments/{id} |
| Create issue | POST repos/{owner}/{repo}/issues |
| Edit issue/PR body or title | PATCH repos/{owner}/{repo}/issues/{n} |
| Create PR | POST repos/{owner}/{repo}/pulls |
| Create release | POST repos/{owner}/{repo}/releases |
Short single-line bodies (e.g. tea comment 42 "lgtm" --login "$GITEA_LOGIN")
are still fine via entity commands.
Tips
- Pass
-o jsonfor structured output when parsing programmatically. - Use
--fields, -fto narrow columns. - Pagination:
--page, -p <n>and--limit, --lm <n>(defaults 1 / 30). - If a
teacommand is blocked bytea-guard, you forgot--loginor$GITEA_LOGINis unset — add the flag or run/tea:login.