npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tea-axi

v0.0.1

Published

Agent-shaped CLI sidecar for Gitea tea — dense TOON output, never prompts

Downloads

21

Readme

tea-axi

An agent-shaped CLI for Gitea. A sidecar to upstream tea: it reads tea's own config and credentials, keeps none of its own, and never replaces the tea binary.

Built to the AXI (Agent eXperience Interface) principles, as a Gitea sibling of gh-axi.

firstmate dependency path: GitHub keeps using gh-axi; Gitea uses tea-axi. Both stay supported.

  • Dense TOON output (~40% fewer tokens than JSON).
  • Never prompts. Missing login or ambiguous targets fail immediately with the exact fix command (e.g. fix: tea logins default gitea.example.com).
  • Contextual help[N]: next steps (axi principle 9).
  • --json when you want machine JSON instead of TOON.
  • -q / --jq <path> for a single bare field value (firstmate poll shape).
  • Content-first home view; per-command --help for every group.

Spec sources

| Source | Role | |--------|------| | axi.md / kunchenguid/axi | 10 AXI principles (output, empty states, errors, content-first, …) | | gh-axi | Closest sibling: forge CLI wrap of an official CLI. Command nouns (issue view, not invent-your-own), count lines, truncation footers, auth error shape, empty-list help | | Local ~/.npm-global install of gh-axi | Runtime reference while building |

Where Gitea genuinely differs from GitHub, divergences are listed below — not silent invention.

Install

Requires Node 20+ and a working tea on PATH (v0.15.1+ recommended).

pnpm install && pnpm build
node dist/bin/tea-axi.js --help
# optional: npm link / install -g from this package

The binary is tea-axi. It does not shadow, replace, or modify /opt/homebrew/bin/tea (or any other tea install).

How auth works

tea-axi has no config of its own. It never writes to tea's config either.

| Platform | tea config directory (read-only) | |----------|----------------------------------| | macOS | ~/Library/Application Support/tea/ | | Linux/XDG | $XDG_CONFIG_HOME/tea or ~/.config/tea |

Contents (owned by tea): config.yml, credentials.json.enc, lock file.

Credentials are encrypted via tea's credstore / OS keyring (since tea v0.13.0). tea-axi does not decrypt them. It shells out to tea (and tea api) so upstream owns token material. Stale GITEA_AUTH_TOKEN / GITEA_TOKEN env vars are stripped from the child environment so a bad export cannot 401 over tea's own login.

Never-prompt gate

Before any command that needs auth, tea-axi reads config.yml and requires:

  1. At least one login, and
  2. Either a default: true login or an explicit --login <name>.

If neither is true, it exits non-zero immediately:

error: no default login for gitea.example.com
code: AUTH_REQUIRED
help[2]:
  fix: tea logins default gitea.example.com
  Or pass --login gitea.example.com

Child processes are spawned with execFile (shell: false, stdio: ['ignore','pipe','pipe']). Stdin is not a TTY, so tea's interactive canPrompt path cannot block an agent.

Auth / health check

For firstmate bootstrap (the gh auth status role):

tea-axi auth status    # compact health record; non-zero + fix line if unusable
tea-axi whoami         # same live API check, user-oriented schema

Either works as a health probe. Both call tea api user and fail closed.

Command surface

Mirrored from gh-axi where the domain maps; Gitea-only names stay tea-shaped. Every group has tea-axi <cmd> --help.

tea-axi                     # dashboard: login + current repo summary
tea-axi whoami              # authenticated user (health probe)
tea-axi auth status         # health probe (gh auth status equivalent)
tea-axi login list|show     # read-only view of tea logins
tea-axi repo list|show
tea-axi issue list|view|create|comment|close
tea-axi pr list|view|create|merge|review-comment
tea-axi label list|create|delete
tea-axi release list|view|create
tea-axi run list|view              # Gitea Actions runs
tea-axi workflow list|view         # Gitea Actions workflows
tea-axi secret list|set|delete     # Actions secrets (values write-only)
tea-axi variable list|get|set|delete
tea-axi search repos|issues <query>
tea-axi api <endpoint>             # escape hatch (wraps tea api)

Explicitly not supported on Gitea

These gh-axi verbs have no Gitea equivalent. They are listed in top-level --help and return NOT_SUPPORTED with a fix line (not silent omission):

| Verb | Why | |------|-----| | gist | Gitea has no GitHub Gist equivalent | | project | Gitea has no GitHub Projects v2 equivalent | | setup | SessionStart hooks not shipped yet (axi principle 7 secondary path) |

Global flags: -r/--repo owner/name, -l/--login name, --json, -q/--jq <path> (single bare field), --help, -v/--version.

Bodies: --body / --description / --body-file (gh-axi-compatible).

firstmate call-site coverage

| firstmate need | tea-axi | |----------------|---------| | PR merge poll state from URL | tea-axi pr view <gitea-pr-url> --json -q .merged → bare true/false | | PR merge by number + repo | tea-axi pr merge <n> -r owner/name (v1) | | Auth bootstrap | tea-axi auth status or tea-axi whoami | | Discover surface without source | tea-axi --help / tea-axi pr --help / … |

PR URLs

Accept a full Gitea PR URL anywhere a PR number is accepted:

https://<host>/<owner>/<repo>/pulls/<n>

Note pulls (Gitea), not GitHub's pull. Host is validated against configured tea logins — never assumed. Wrong host / GitHub-shaped /pull/ fail with an explicit fix line.

Merge state (load-bearing — both captain repos squash-merge)

Read merge state only through tea-axi (or raw tea api). Never trust tea pull <n> -o json / tea -o json for whether a PR is merged.

Established facts on this Gitea instance:

| Source | Squash-merged PR | |--------|------------------| | Gitea API /repos/.../pulls/<n> | merged: true | | Upstream tea pull <n> -o json | merged: null, merge_commit_sha: null |

If an agent or poll uses tea's JSON renderer, firstmate never sees the merge land and work sits "unmerged" forever with nothing visibly broken.

tea-axi pr view always goes through tea api. Prefer the poll shape:

tea-axi pr view <url-or-number> --json -q .merged   # bare true | false

Single-value selector

tea-axi pr view https://gitea.example.com/ryan/tea-axi/pulls/2 --json -q .merged
# true

Prints the bare value only (no TOON, no JSON braces). Missing field → non-zero exit + NOT_FOUND.

Divergences from gh-axi (deliberate)

| Topic | gh-axi | tea-axi | Why | |-------|--------|---------|-----| | Repo flag | -R/--repo | -r/--repo | Match upstream tea (-r) so muscle memory transfers from tea, not gh | | Auth | gh auth login / gh auth status | tea logins add / tea-axi auth status | Different CLI; fix lines must name tea | | Config path | gh's hosts.yml | macOS Application Support tea/ | tea's real path (not ~/.config/tea on macOS) | | Detail verb | view primary | view primary; show alias | Aligned with gh-axi; keep show for tea users | | PR path | /pull/<n> | /pulls/<n> | Gitea URL shape | | Field select | gh -q via upstream | -q / --jq on tea-axi JSON objects | No full jq engine; path select only | | Merge styles | GitHub merge/squash/rebase | + rebase-merge | Gitea API supports it | | Host flag | --hostname / GH_HOST | tea login name (-l) | Multi-instance is tea logins, not GH_HOST | | gist / project / setup | full surface | explicit NOT_SUPPORTED | No Gitea equivalent (or not shipped) |

Fork vs wrap

v1 wraps tea; it does not fork it. Evidence:

  1. JSON surface is enough. tea issues|pulls|repos … -o json + tea api cover list, detail, and mutations.
  2. tea api is a complete escape hatch. Missing commands never block.
  3. Credentials are encrypted. Forking would vendor credstore/keyring code; wrapping reuses it.
  4. Upstream is 0.x ~monthly and has broken flags before (v0.14.1). Fork pays permanent merge tax.

Cost of wrap: one process spawn per call. Acceptable vs network I/O.

Same architectural choice as gh-axi wrapping gh.

AXI principle checklist

| # | Principle | tea-axi | |---|-----------|---------| | 1 | Token-efficient TOON | default stdout via @toon-format/toon | | 2 | Minimal default schemas | list: number,title,state,author | | 3 | Content truncation + --full | truncateBody size hint | | 4 | Pre-computed aggregates | count: lines; truncation note when page full | | 5 | Definitive empty states | count: 0 + create-oriented help | | 6 | Structured errors, no prompts, idempotent close | AUTH_REQUIRED fix lines; close no-op | | 7 | Ambient context / setup | not shipped (setup → NOT_SUPPORTED) | | 8 | Content first | bare tea-axi → live dashboard | | 9 | Contextual disclosure | help[N]: after list/view/mutations | | 10 | Consistent --help | top-level + every command group |

Development / testing

Follows the captain's /ry-testing discipline: red-first for load-bearing invariants, boundary fakes (FakeTeaRunner) instead of network, offline default gate, discriminating asserts (never-prompt tests check fix line + AUTH_REQUIRED + no tea invocation + elapsed < 2s — not a vacuous non-zero exit).

pnpm install   # needs committed pnpm-workspace.yaml allowBuilds.esbuild=true
pnpm build
pnpm test      # offline, ~seconds — must work from a clean clone
node dist/bin/tea-axi.js whoami  # live smoke (needs tea login)
node dist/bin/tea-axi.js pr view https://gitea.example.com/ryan/tea-axi/pulls/2 --json -q .merged

pnpm-workspace.yaml explicitly allows esbuild's postinstall (required by vitest/vite). A clean clone must not need pnpm approve-builds.

There is no tea-axi update self-update path (package is not on npm). That command is not advertised in --help.

Test-only env

| Variable | Purpose | |----------|---------| | TEA_AXI_TEA_CONFIG_DIR | Point at a fake tea config directory |

License

MIT