Files
naudachu 83f73c5cea 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>
2026-08-11 00:25:28 +05:00

7.8 KiB


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:

# 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 — 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

The canonical issue format moved to ../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:
    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>:
    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).