Harden the benchmark and cut gitea-axi's agent cost #44

Merged
alexion merged 7 commits from bench-skill-and-cli-cost-fixes into main 2026-07-19 12:40:57 -04:00
2 changed files with 32 additions and 37 deletions
Showing only changes of commit d56b1d0707 - Show all commits

View File

@@ -6,43 +6,34 @@ description: Use when working with a Gitea repository's issues, pull requests, l
# gitea-axi # gitea-axi
`gitea-axi` is an agent-ergonomic CLI for a Gitea repository's issues and pull requests. `gitea-axi` is an agent-ergonomic CLI for a Gitea repository's issues and pull requests.
Its output is compact TOON built for another program to read, and its errors are structured with actionable suggestions. Its output is compact TOON meant to be read directly, and a failed command's error names the fix — follow that suggestion rather than guessing at another command.
## When to use it
Reach for `gitea-axi` whenever a task touches a Gitea repository's issues, pull requests, labels, or reviews.
- **Over `tea`:** `gitea-axi` returns structured output and typed errors instead of human-formatted tables, and it defaults the repository and login from the local checkout.
- **Over raw Gitea API calls:** it handles auth, pagination, name-to-ID resolution, and review-decision aggregation for you, so you do not hand-roll HTTP.
- **Over improvised `git`:** for anything about issues or pull requests as entities (state, reviews, labels, comments) rather than local commits and branches.
## Targeting and authentication ## Targeting and authentication
Every command resolves two things: which repository to act on, and which credentials to authenticate with. Every command resolves a repository and credentials; getting both right on the first call is the difference between one command and a retry.
Get both right on the first call — they are the usual reason a command fails and has to be retried.
- **Repository.** Inside a Gitea checkout it is taken from the `origin` remote automatically. - **Repository.** Inside a Gitea checkout it comes from the `origin` remote.
Outside a checkout you must name it: pass `-R OWNER/NAME` on every command (or set `GITEA_AXI_REPO=OWNER/NAME` once for the session). Outside one, pass `-R OWNER/NAME` on every command, or set `GITEA_AXI_REPO=OWNER/NAME` once for the session.
- **Credentials.** When the environment is pre-configured — `GITEA_AXI_TOKEN` together with `GITEA_AXI_API_URL` authentication is automatic and you need nothing more. - **Credentials.** With `GITEA_AXI_TOKEN` and `GITEA_AXI_API_URL` set, authentication is automatic.
Otherwise credentials come from a `tea` login: pass `--login <name>` (or set `GITEA_AXI_LOGIN=<name>`) unless the checkout's remote already selects one. Otherwise pass `--login <name>`, or set `GITEA_AXI_LOGIN`.
So outside a checkout with the token in the environment, `gitea-axi <command> -R OWNER/NAME …` is all you need; do not go hunting for a config file or a login profile. Outside a checkout with the token in the environment, `gitea-axi <command> -R OWNER/NAME …` is the whole invocation — don't look for a config file or a login profile.
## Command groups ## Commands
- `issue` — list, view, create, comment on, edit, close/reopen, pin, and link issues. - `issue` — list, view, create, comment, edit, close, reopen, pin, and link (blocks / blocked-by).
- `pr`create, view, comment on, edit, review, merge, check out, diff, and inspect the checks of pull requests. - `pr`list, view, create, comment, edit, review, merge, close, reopen, diff, checks, and checkout.
- `label` — list, create, edit, and delete labels. - `label` — list, create, edit, delete.
- `search` — full-text search; it takes a subcommand, so search issues with `search issues "<query>"` and pull requests with `search prs "<query>"` (a bare `search "<query>"` is not valid). - `search issues "<query>"` and `search prs "<query>"` — full-text search (a bare `search "<query>"` is not valid).
- `setup` — install this skill (`setup`) and, opt-in, the SessionStart dashboard hook (`setup hooks`).
To read one issue's fields, reach straight for `issue view <number>`: it shows labels and state by default, and takes `--fields assignees,milestone,…` for the rest. ## Finding and acting
You rarely need `issue list` to answer a question about a single issue.
## Discovery Find the target, then act on it — two commands, not a survey of the repository.
This skill is a pointer, not a command reference — the CLI is the single source of truth for its own interface. - **Find it.** If you already know the number, act on it directly.
Otherwise reach for one command — `search issues "<query>"` for a title or keyword, or `issue list --state all --label <name>` to narrow by a property — not both.
- Run `gitea-axi` with no arguments for the repository dashboard (open issues and pull requests). - **Read one issue or PR.** `issue view <number>` (or `pr view <number>`) shows labels and state by default, and takes `--fields assignees,milestone,…` for the rest.
Add `--full` for the open-PR table and issue counts by label. You do not need `issue list` to answer a question about a single known issue.
- Run `gitea-axi <command> --help` (or `gitea-axi <group> <command> --help`) for the exact flags of any command. - **Act on it.** `issue edit <number>` and `pr edit <number>` change fields with repeatable `--add-label` / `--remove-label` and `--add-assignee` / `--remove-assignee`, plus `--title`, `--body`, and `--milestone`.
Reviewing is `pr review <number>` with exactly one of `--approve`, `--request-changes`, or `--comment`, and an optional `--body`.
A comment is `issue comment <number> --body <text>`; a new label is `label create --name <text> --color <hex-without-#>`.

View File

@@ -36,19 +36,23 @@ describe("bundled Agent Skill markdown", () => {
it("references each command group as a one-liner", () => { it("references each command group as a one-liner", () => {
const body = skill.toLowerCase(); const body = skill.toLowerCase();
for (const group of ["issue", "pr", "label", "search", "setup"]) { for (const group of ["issue", "pr", "label", "search"]) {
expect(body, `expected the skill to mention the ${group} command group`).toContain( expect(body, `expected the skill to mention the ${group} command group`).toContain(
group, group,
); );
} }
}); });
it("points at the bare dashboard and per-command help for discovery", () => { it("steers find-then-act and does not push exploratory discovery", () => {
const body = skill.toLowerCase(); const body = skill.toLowerCase();
// Bare dashboard: running the binary with no arguments. // The intended steering: find the target, then act on it.
expect(body).toContain("no argument"); expect(body).toContain("find the target");
expect(body).toContain("dashboard"); expect(body).toContain("act on it");
// Per-command help. // The find/act discipline: not a full survey, and not both find commands at once.
expect(body).toContain("--help"); expect(body).toContain("not a survey");
expect(body).toContain("not both");
// The removed exploratory anti-pattern must be gone.
expect(body).not.toContain("dashboard");
expect(body).not.toContain("no argument");
}); });
}); });