335b0bbd54
Replace fetch_issue.py with four scripts around a flat, greppable cache in tmp/issues/. Planning stays offline and issues reach Gitea in one push: - issue_get.py: fetch by key or by filter (--milestone/--label/-q). The list endpoint carries issue bodies, so a whole milestone costs one request per 50 issues. Gitea silently ignores an unresolvable milestones= filter and returns the entire backlog, so the milestone is resolved up front and every returned issue is re-checked locally. --deps walks the dependency graph downwards via the structured sections plus native dependencies and writes tree-<slug>.md. - issue_push.py: validate a local draft against the canonical format, create missing labels with the right colors and exclusivity, POST, delete the draft. - issue_list.py: discovery to stdout, writes nothing. - issue_index.py: rebuild INDEX.md from what is on disk. Files use one metadata field per line with inline lists so plain grep works without a parser. This is a cache and a drafting area, not a mirror: no drift tracking, no sync back. Projects are not fetchable — the projects API is 404 on Gitea 1.26; documented alongside the milestone caveat. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
102 lines
4.5 KiB
Markdown
102 lines
4.5 KiB
Markdown
# tea — Claude Code plugin for the Gitea CLI
|
|
|
|
A Claude Code plugin that gives Claude a reference for the `tea` CLI and enforces a hard rule: every `tea` command runs under the login **the operator chose**, never one Claude picked.
|
|
|
|
## What it ships
|
|
|
|
| Piece | What it does |
|
|
|---|---|
|
|
| `/tea:auth` skill | Prompts you to pick a Gitea login and pins it to the project |
|
|
| `/tea:use` skill | Tea CLI reference — loads command docs on demand |
|
|
| `/tea:issue` skill | Drafts issues locally in a canonical format (typed labels, fixed sections), then pushes them |
|
|
| Issue scripts | Fetch issues into a flat, greppable local cache (`tmp/issues/`), walk dependency trees, push drafts |
|
|
| `tea-guard` hook | PreToolUse hook that blocks or rewrites every `tea` invocation |
|
|
|
|
## Prerequisites
|
|
|
|
- **Claude Code** — CLI, desktop app, or IDE extension
|
|
- **Python 3** — required by the `tea-guard` hook (`python3` must be on `$PATH`)
|
|
- **`tea`** — Gitea's official CLI. Install with `brew install tea` (macOS) or from [gitea.com/gitea/tea/releases](https://gitea.com/gitea/tea/releases)
|
|
- At least one login configured: `tea logins add` (interactive — run it in a terminal, not via Claude)
|
|
|
|
## Installation
|
|
|
|
This is a Claude Code plugin — install it through the plugin marketplace, not by hand-editing `settings.json`.
|
|
|
|
1. Register this repo as a marketplace:
|
|
|
|
```
|
|
/plugin marketplace add https://git.noodles.cam/claude-skills/tea.git
|
|
```
|
|
|
|
Already have a local clone? Point at the directory instead:
|
|
|
|
```
|
|
/plugin marketplace add /path/to/tea
|
|
```
|
|
|
|
2. Install the plugin:
|
|
|
|
```
|
|
/plugin install tea@tea
|
|
```
|
|
|
|
The skills (`/tea:auth`, `/tea:use`, `/tea:issue`) and the `tea-guard` hook load immediately. Use `/plugin` to enable, disable, or update it later.
|
|
|
|
> The marketplace registration is written to `extraKnownMarketplaces` and the plugin to `enabledPlugins` in your settings automatically — you don't edit those by hand. There is **no** top-level `"plugins"` settings key; if you've added one from older instructions, remove it.
|
|
|
|
## First use
|
|
|
|
Run `/tea:auth` once per project. Claude will list your available Gitea logins and ask you to pick one. The choice is written to `.claude/settings.local.json` and takes effect immediately — no restart needed.
|
|
|
|
```
|
|
/tea:auth
|
|
```
|
|
|
|
After that, use `/tea:use` to look up commands, or just ask Claude to do something with Gitea and it will load the reference automatically.
|
|
|
|
## How the login guard works
|
|
|
|
Every `tea` invocation Claude writes must carry the literal placeholder `--login "$GITEA_LOGIN"`. The `tea-guard` hook intercepts the Bash call before it runs, looks up the pinned login from `.claude/settings.local.json`, and rewrites the command to use it.
|
|
|
|
Claude is **blocked** from:
|
|
- running `tea` without `--login` at all
|
|
- naming a login itself (e.g. `--login myaccount`)
|
|
- using any variable other than `$GITEA_LOGIN`
|
|
|
|
This prevents silent fallback to the machine's default login (often a personal account) when working in a project that belongs to a different identity.
|
|
|
|
`tea logins list` and `tea --version / --help` are exempt — they don't touch Gitea data.
|
|
|
|
## Project layout
|
|
|
|
```
|
|
.claude-plugin/
|
|
plugin.json plugin manifest
|
|
marketplace.json marketplace catalog (makes `/plugin install` work)
|
|
hooks/
|
|
hooks.json registers the PreToolUse hook
|
|
tea-guard.sh the guard (Python 3, no deps)
|
|
skills/
|
|
auth/SKILL.md /tea:auth skill
|
|
use/SKILL.md /tea:use skill
|
|
use/references/tea/ tea CLI reference docs
|
|
use/references/issue-format.md canonical issue format (types, templates)
|
|
use/scripts/ issue scripts (Python 3, no deps):
|
|
issue_get.py fetch issues into tmp/issues/, --deps walks the graph
|
|
issue_push.py validate a local draft, create labels, POST, drop the draft
|
|
issue_list.py discovery listing to stdout
|
|
issue_index.py rebuild tmp/issues/INDEX.md (no network)
|
|
_tea.py shared login / api / on-disk-format helpers
|
|
issue/SKILL.md /tea:issue skill
|
|
```
|
|
|
|
## Local issue cache
|
|
|
|
The scripts keep issues in `tmp/issues/` (gitignore it) as flat markdown with
|
|
one metadata field per line — so `grep -l 'labels:.*type/bug' tmp/issues/*.md`
|
|
works without a parser. It is a **cache and a drafting area, not a mirror**:
|
|
nothing tracks drift and nothing syncs back. Drafts written during planning
|
|
live in `tmp/issues/drafts/` and are deleted once `issue_push.py` creates them
|
|
in Gitea.
|