feat(nix): expose declarative outputs and a home-manager module (task 0045)
All checks were successful
CI / test (22) (pull_request) Successful in 49s
CI / test (true, 24) (pull_request) Successful in 1m5s
CI / flake (pull_request) Successful in 3s
CI / test (22) (push) Successful in 49s
CI / test (true, 24) (push) Successful in 1m5s
CI / flake (push) Successful in 3s
All checks were successful
CI / test (22) (pull_request) Successful in 49s
CI / test (true, 24) (pull_request) Successful in 1m5s
CI / flake (pull_request) Successful in 3s
CI / test (22) (push) Successful in 49s
CI / test (true, 24) (push) Successful in 1m5s
CI / flake (push) Successful in 3s
Let a Nix configuration declare gitea-axi's ambient context instead of running a command that writes it. `setup` and `setup hooks` are write-only against files the operator is assumed to own, so an operator whose agent configuration is generated cannot use them at all. The package installs the bundled Agent Skill to share/gitea-axi/skills and publishes it as `passthru.skill`, alongside `passthru.sessionStartHook` read from `session-start-hook.json` — a committed declaration the fast tier reads too, so a test drives `setup hooks` and asserts the two agree. On top of that, `homeModules.gitea-axi` declares both from those attributes through home-manager's own Claude Code options, so an operator's existing skills and SessionStart hooks compose rather than collide. Importing it without enabling it yields a byte-identical generation. The spec's Out of Scope entry deferring a home-manager module is deleted; ADR 0020 records the reversal, and INSTALL.md describes both paths.
This commit was merged in pull request #54.
This commit is contained in:
111
home-manager-module.nix
Normal file
111
home-manager-module.nix
Normal file
@@ -0,0 +1,111 @@
|
||||
# A home-manager module declaring gitea-axi's ambient context — the bundled
|
||||
# Agent Skill and the SessionStart hook — for an operator whose agent
|
||||
# configuration is generated rather than owned (ADR 0020).
|
||||
#
|
||||
# It is a wiring layer and nothing more. Both pieces come from the package's
|
||||
# published attributes, so what a declarative configuration installs and what
|
||||
# `gitea-axi setup` writes imperatively are the same two artefacts, and neither
|
||||
# is restated here.
|
||||
#
|
||||
# Importing this module changes nothing until `programs.gitea-axi.enable` is set.
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.programs.gitea-axi;
|
||||
|
||||
# The package the declarations are read out of. `package = null` opts out of
|
||||
# putting the binary on PATH, not out of the configuration — an operator who
|
||||
# installs gitea-axi system-wide still wants the Skill — so the declarations
|
||||
# fall back to the default build, which in that arrangement is already in the
|
||||
# closure anyway.
|
||||
sourcePackage = if cfg.package != null then cfg.package else defaultPackage;
|
||||
|
||||
defaultPackage = pkgs.callPackage ./package.nix { };
|
||||
|
||||
# Both integrations write into files a sibling module owns, so nothing lands
|
||||
# unless that module is the one writing them.
|
||||
claudeCode = config.programs.claude-code;
|
||||
in
|
||||
{
|
||||
options.programs.gitea-axi = {
|
||||
enable = lib.mkEnableOption "gitea-axi, an agent-ergonomic CLI for Gitea issues and pull requests";
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.package;
|
||||
default = defaultPackage;
|
||||
defaultText = lib.literalExpression "pkgs.callPackage ./package.nix { }";
|
||||
description = ''
|
||||
The gitea-axi package to install, or `null` to declare the
|
||||
configuration without installing the binary — for an operator who
|
||||
supplies it another way, such as `environment.systemPackages`.
|
||||
|
||||
The SessionStart hook records a name resolved on `PATH`, so a binary
|
||||
installed elsewhere satisfies it. With `null` the Agent Skill is still
|
||||
taken from the default build.
|
||||
'';
|
||||
};
|
||||
|
||||
skill.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to install gitea-axi's bundled Agent Skill, which teaches the
|
||||
agent to reach for gitea-axi over `tea` or raw API calls.
|
||||
|
||||
Turn this off to keep writing the Skill with `gitea-axi setup` while
|
||||
managing the rest declaratively.
|
||||
'';
|
||||
};
|
||||
|
||||
sessionStartHook.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to register the SessionStart hook that renders the gitea-axi
|
||||
dashboard at the start of an agent session.
|
||||
|
||||
Turn this off to keep writing the hook with `gitea-axi setup hooks`
|
||||
while managing the rest declaratively.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
(lib.mkIf (cfg.package != null) { home.packages = [ cfg.package ]; })
|
||||
|
||||
# Declared through the Claude Code module's own options rather than by
|
||||
# writing its files, so an operator who already declares Skills and
|
||||
# SessionStart hooks gets ours merged into theirs instead of a collision.
|
||||
(lib.mkIf cfg.skill.enable {
|
||||
programs.claude-code.skills.gitea-axi = sourcePackage.skill;
|
||||
})
|
||||
|
||||
(lib.mkIf cfg.sessionStartHook.enable {
|
||||
programs.claude-code.settings.hooks.SessionStart = [ sourcePackage.sessionStartHook ];
|
||||
})
|
||||
|
||||
{
|
||||
# Without this the options above are set and silently dropped, leaving
|
||||
# an operator with a configuration that says the Skill is installed and
|
||||
# a session that never sees it.
|
||||
assertions = [
|
||||
{
|
||||
assertion = (cfg.skill.enable || cfg.sessionStartHook.enable) -> claudeCode.enable;
|
||||
message = ''
|
||||
programs.gitea-axi declares a Claude Code Agent Skill and session
|
||||
hook, which programs.claude-code writes. Set
|
||||
programs.claude-code.enable = true, or turn off
|
||||
programs.gitea-axi.skill.enable and
|
||||
programs.gitea-axi.sessionStartHook.enable.
|
||||
'';
|
||||
}
|
||||
];
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user