From 310ff13c776d99c5c82021a619354b6d39c31453 Mon Sep 17 00:00:00 2001 From: alexion Date: Mon, 20 Jul 2026 21:37:33 -0400 Subject: [PATCH] feat(gitea-axi): install the CLI and wire its agent context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add gitea-axi as a flake input and a new modules.gitea-axi module that installs the CLI through its home-manager module. That module also declares the Claude Code context — the Agent Skill and the SessionStart dashboard hook — when claude-code is enabled on the host, so neogaia gets both while a host without the harness would get the CLI alone. Drop the hand-written SessionStart hook from the claude-code module, which named a gitea-axi binary nothing installed; the gitea-axi module owns it now. Remove the vendored skill fork, which had drifted from upstream and would collide with the copy the module writes. --- CLAUDE.md | 9 ++-- flake.lock | 45 ++++++++++++++++- flake.nix | 7 +++ hosts/neogaia/default.nix | 1 + modules/claude-code/claude-code.nix | 12 ----- modules/claude-code/skills/gitea-axi/SKILL.md | 48 ------------------- modules/gitea-axi.nix | 22 +++++++++ 7 files changed, 79 insertions(+), 65 deletions(-) delete mode 100644 modules/claude-code/skills/gitea-axi/SKILL.md create mode 100644 modules/gitea-axi.nix diff --git a/CLAUDE.md b/CLAUDE.md index a7468a1..bcfa577 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -52,10 +52,11 @@ The domain model (Host, Module, Skeleton, Auto-loader, Enable convention, overla Staging is enough; the file need not be committed. - chaotic-nyx must **not** follow our `nixpkgs`, and its packages are built against chaotic's own pinned nixpkgs (its overlay defaults to `onTopOf = "flake-nixpkgs"`, the cache-friendly path). That is what lets the `nyx-cache.chaotic.cx` binary cache hit instead of compiling the CachyOS kernel from source; the tradeoff is that chaotic packages do not see our `unstable`/`stable` overlays. -- The remote is self-hosted Gitea (`git.alexion.dev`), and the intended CLI is `gitea-axi` rather than `tea`. - `gitea-axi` resolves the repository from the `origin` remote and takes credentials from the `axi` tea login, so both are implicit inside a checkout. - **No forge CLI is installed on the NixOS build.** No `gitea-axi`, no `tea`, no `gh` on `PATH` — the flake names `gitea-axi` only as the claude-code module's `SessionStart` hook command and never packages it, so that hook invokes a binary that is not there. - Credentials, however, do exist: `~/.config/tea/config.yml` holds a token-bearing login named `alexion` (not `axi`), so pull requests **can** be opened with `nix run nixpkgs#tea -- pr create --login alexion --repo alexion/dotfiles --base main --head ...`. +- The remote is self-hosted Gitea (`git.alexion.dev`), and the forge CLI is `gitea-axi` rather than `tea`. + `gitea-axi` resolves the repository from the `origin` remote and discovers credentials from a `tea` login whose host matches the remote, so both are implicit inside a checkout. + It is installed on `neogaia` by `modules.gitea-axi`, and verified: `gitea-axi` run from this checkout renders the `alexion/dotfiles` dashboard authenticated, so the claude-code `SessionStart` hook that runs it now resolves to a real binary rather than a missing one. + The package wraps the binary so `git` and `tea` are reachable without being on `PATH`, while still preferring the operator's own where present. + Credentials: `~/.config/tea/config.yml` holds a token-bearing login named `alexion`, which `gitea-axi` uses and which also opens pull requests directly with `nix run nixpkgs#tea -- pr create --login alexion --repo alexion/dotfiles --base main --head ...`. The `--repo` flag is required on that path, since `tea` resolves `origin` only for a login whose SSH host matches. The same token reads PR discussion, which `tea` itself does poorly: `tea pr --comments` prints only the body, and `-f comments` returns no comments field at all. Use the API instead, taking the token from `.logins[] | select(.name=="alexion") | .token`. diff --git a/flake.lock b/flake.lock index 4f1fa33..898aa4b 100644 --- a/flake.lock +++ b/flake.lock @@ -76,6 +76,27 @@ "url": "https://flakehub.com/f/DeterminateSystems/flake-schemas/%3D0.5.0.tar.gz" } }, + "gitea-axi": { + "inputs": { + "home-manager": "home-manager_2", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1784592615, + "narHash": "sha256-AH96vm0yYyS9sk35GnagZoWww8s8NHWYuyZJpSStlMM=", + "ref": "refs/heads/main", + "rev": "1468003f5b63f49fcd3cd456c25a8ad4f25716cc", + "revCount": 82, + "type": "git", + "url": "https://git.alexion.dev/alexion/gitea-axi" + }, + "original": { + "type": "git", + "url": "https://git.alexion.dev/alexion/gitea-axi" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -98,6 +119,27 @@ } }, "home-manager_2": { + "inputs": { + "nixpkgs": [ + "gitea-axi", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1784588016, + "narHash": "sha256-ouZe80aWEhMLVMkqICFDN+JUw+0FJtCr/bh+hHtRtMg=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "deeb6b7eb7e0c44ae1819c051ce175bd92a85100", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_3": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -227,7 +269,8 @@ "inputs": { "chaotic": "chaotic", "disko": "disko", - "home-manager": "home-manager_2", + "gitea-axi": "gitea-axi", + "home-manager": "home-manager_3", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs_2", "nixpkgs-stable": "nixpkgs-stable", diff --git a/flake.nix b/flake.nix index b1babdf..17f5390 100644 --- a/flake.nix +++ b/flake.nix @@ -40,6 +40,13 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + # Agent-ergonomic CLI for Gitea, with its home-manager module wiring in the + # Claude Code context where that harness is present. + gitea-axi = { + url = "git+https://git.alexion.dev/alexion/gitea-axi"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + # CachyOS kernel and binary cache. Pins its own nixpkgs so its cache stays # usable and the kernel is fetched from it. chaotic.url = "github:chaotic-cx/nyx/nyxpkgs-unstable"; diff --git a/hosts/neogaia/default.nix b/hosts/neogaia/default.nix index 3e3d037..43264c7 100644 --- a/hosts/neogaia/default.nix +++ b/hosts/neogaia/default.nix @@ -49,6 +49,7 @@ modules.tmux.enable = true; modules.nvim.enable = true; modules.claude-code.enable = true; + modules.gitea-axi.enable = true; time.timeZone = "America/New_York"; i18n.defaultLocale = "en_GB.UTF-8"; diff --git a/modules/claude-code/claude-code.nix b/modules/claude-code/claude-code.nix index d0ae9b8..9a69ddb 100644 --- a/modules/claude-code/claude-code.nix +++ b/modules/claude-code/claude-code.nix @@ -77,18 +77,6 @@ in ]; } ]; - SessionStart = [ - { - matcher = ""; - hooks = [ - { - type = "command"; - command = "gitea-axi"; - timeout = 10; - } - ]; - } - ]; }; }; }; diff --git a/modules/claude-code/skills/gitea-axi/SKILL.md b/modules/claude-code/skills/gitea-axi/SKILL.md deleted file mode 100644 index 5e30a48..0000000 --- a/modules/claude-code/skills/gitea-axi/SKILL.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -name: gitea-axi -description: Use when working with a Gitea repository's issues, pull requests, labels, reviews, comments, or milestones — listing, viewing, creating, editing, commenting, reviewing, or merging on a Gitea host such as git.alexion.dev. Prefer this over the `tea` CLI, raw Gitea API calls, or improvised `git` commands for issue/PR/label work. ---- - -# gitea-axi - -`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. - -## 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 - -Every command resolves two things: which repository to act on, and which credentials to authenticate with. -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. - 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). -- **Credentials.** When the environment is pre-configured — `GITEA_AXI_TOKEN` together with `GITEA_AXI_API_URL` — authentication is automatic and you need nothing more. - Otherwise credentials come from a `tea` login: pass `--login ` (or set `GITEA_AXI_LOGIN=`) unless the checkout's remote already selects one. - -So outside a checkout with the token in the environment, `gitea-axi -R OWNER/NAME …` is all you need; do not go hunting for a config file or a login profile. - -## Command groups - -- `issue` — list, view, create, comment on, edit, close/reopen, pin, and link issues. -- `pr` — create, view, comment on, edit, review, merge, check out, diff, and inspect the checks of pull requests. -- `label` — list, create, edit, and delete labels. -- `search` — full-text search; it takes a subcommand, so search issues with `search issues ""` and pull requests with `search prs ""` (a bare `search ""` 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 `: it shows labels and state by default, and takes `--fields assignees,milestone,…` for the rest. -You rarely need `issue list` to answer a question about a single issue. - -## Discovery - -This skill is a pointer, not a command reference — the CLI is the single source of truth for its own interface. - -- Run `gitea-axi` with no arguments for the repository dashboard (open issues and pull requests). - Add `--full` for the open-PR table and issue counts by label. -- Run `gitea-axi --help` (or `gitea-axi --help`) for the exact flags of any command. diff --git a/modules/gitea-axi.nix b/modules/gitea-axi.nix new file mode 100644 index 0000000..36bf996 --- /dev/null +++ b/modules/gitea-axi.nix @@ -0,0 +1,22 @@ +{ + config, + lib, + inputs, + ... +}: +# gitea-axi for the primary user, installed through its own home-manager module. +# That module also declares the Claude Code context when that harness is +# enabled on the host; enabling this alone installs the CLI and nothing else. +let + cfg = config.modules.gitea-axi; + user = config.user.name; +in +{ + options.modules.gitea-axi.enable = + lib.mkEnableOption "gitea-axi, an agent-ergonomic CLI for Gitea issues and pull requests"; + + config = lib.mkIf cfg.enable { + home-manager.sharedModules = [ inputs.gitea-axi.homeModules.default ]; + home-manager.users.${user}.programs.gitea-axi.enable = true; + }; +}