Files
naudachu bac45028bf tea-guard: resolve and rewrite --login instead of env-checking
The previous guard required $GITEA_LOGIN to be set in the Bash environment,
which (a) only happens after a session restart and (b) let Claude name any
login it liked as long as one was set. Two failures: pinning needed a restart
to take effect, and Claude could pick the wrong identity from memory.

Rewrite the guard (now python3 for JSON in/out) to RESOLVE the login itself:

- Claude must write the literal placeholder --login "$GITEA_LOGIN".
- The hook reads the operator's pin from .claude/settings.local.json
  (env.GITEA_LOGIN) at call time — from the FILE via CLAUDE_PROJECT_DIR/cwd
  walk-up — and rewrites the command to that literal via updatedInput.
- A literal login, another variable, an empty value, or a missing --login are
  all blocked: Claude may not choose the identity, only the operator may.
- No pin -> block with a pointer to /tea:login.

Effect: pinning works in the same session (no restart), and Claude can no
longer act under a login it picked. /tea:login now mandates an explicit
operator choice (AskUserQuestion), never inferring from memory. /tea:use
documents the placeholder-only contract.

Guard unit-tested across 13 rewrite/block/passthrough cases incl. -l,
--login=, ${...}, compound+walkup+pipe. claude plugin validate passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 16:26:54 +05:00

5.4 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. Always write the login as the literal placeholder --login "$GITEA_LOGIN" — the tea-guard hook substitutes the operator-pinned login; 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: 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:login).
  • no login pinned → blocked with a pointer to run /tea:login.

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: issues, pulls, labels, milestones, releases, times, repos, branches, actions, webhooks, comments, notifications, etc.
  2. Find the matching command in the index below.
  3. Run it via Bash with the placeholder login, e.g. tea issues 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:login) and injected by the guard. 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

  1. Ensure the target dir exists: mkdir -p tmp/{kind} where {kind} is comment, issue, 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:
    mkdir -p tmp/comment
    cat > tmp/comment/issue-60.json <<'EOF'
    {"body": "## Heading\n\nMulti-line markdown with `code`, | tables |, and ```fences```."}
    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/comment/issue-60.json.
  3. 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
    
  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
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. Always the placeholder, never a login name.

Tips

  • Pass -o json for structured output when parsing programmatically.
  • 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:login).