common: add agents configuration for Claude/Gemini

This commit is contained in:
Adriano Caloiaro 2026-01-06 07:40:49 -08:00
parent b96b20b51d
commit 883b91d822
No known key found for this signature in database
5 changed files with 232 additions and 7 deletions

56
AGENTS.md Normal file
View file

@ -0,0 +1,56 @@
# Agent Guide for NixOS System Configuration
This repository contains NixOS and macOS (nix-darwin) configurations managed with Nix Flakes.
## Project Structure
- **`flake.nix`**: Entry point for all system configurations.
- **`systems/`**: Configuration for specific hosts.
- `zw`, `jellybee`, `homebee`: NixOS systems.
- `greenhouse` (hostname `JJTH7GH17J`): macOS system.
- `pi`, `homepi`: Likely Raspberry Pi or similar ARM systems (some may be inactive in `flake.nix`).
- **`common/`**: Shared configurations, overlays, and Home Manager modules.
- **`images/`**: Configuration for generating system images.
## Key Commands
### Deployment
- **Install NixOS**: `nixos-install --flake .#<hostname>`
- **Rebuild NixOS**: `nixos-rebuild switch --flake .#<hostname>`
- **Rebuild macOS**: `darwin-rebuild switch --flake .#<hostname>`
- **Update Flakes**: `nix flake update`
### Provisioning
- **ZFS Setup**: Use `systems/<hostname>/nixos-zfs-setup.sh` (e.g., for `zw`) to partition disks and create ZFS pools before installation.
- **Warning**: This script wipes disks. Read carefully before running.
## Configuration Patterns
### Modules & Options
- Custom Home Manager modules are defined in `common/home-manager` (e.g., `code`, `jira`).
- Modules often use `mkOption` to define enabling flags (e.g., `code.jujutsu.enable`).
- Shared system configuration is often imported via `imports` in host-specific `configuration.nix`.
### Secret Management
- **Tool**: `agenix` is used for encryption.
- **Files**: Secrets are stored as `.age` files in `systems/<hostname>/secrets/`.
- **Key**: Secrets are typically decrypted using SSH keys or dedicated key files.
- **Integration**: `homeage` is used for user-level secret management in Home Manager.
### Version Control
- **Jujutsu (jj)**: The user heavily utilizes `jj` alongside `git`.
- **Aliases**: `jj` aliases are configured in `common/home-manager/code/default.nix`.
## Gotchas
- **Empty Directories**: Some directories might seem empty but serve as mount points or future placeholders.
- **Hardware Specifics**:
- `zw`: ThinkPad (x86_64)
- `greenhouse`: MacBook Pro (M-series, aarch64)
- **Private Modules**: The flake inputs reference a private `greenhouse-nix-modules` repo. If you cannot access it, some evaluations might fail.
- **Impermanence**: Some systems use "impermanence" setup (root rollback on boot), configured in `nixos-zfs-setup.sh` and Nix modules.
## Development
- **Formatting**: No global formatter is enforced in `flake.nix` (only `nixpkgs-fmt` or `alejandra` are common in Nix, but check if installed).
- **Linter**: `statix` or `deadnix` are common but not explicitly seen in the root.

View file

@ -0,0 +1,91 @@
{
config,
lib,
pkgs,
...
}: let
cfg = config.ai-agents.crush;
in {
options.ai-agents.crush.enable = lib.mkEnableOption "Charmbracelet's Crush";
config = lib.mkIf cfg.enable {
home.packages = [
(pkgs.buildGo125Module rec {
name = "crush";
version = "0.32.0";
vendorHash = "sha256-HauqqSrdpJFKV60BA2/2ZFaMz/wFwRf0+Te4zX34NsU=";
src = pkgs.fetchFromGitHub {
owner = "charmbracelet";
repo = name;
tag = "v${version}";
hash = "sha256-EXHyYpIUGew2AwRqN7CU/A3YXF3HLGkkCgK2jYhSNnA=";
};
checkFlags = let
# these tests fail in the sandbox
skippedTests = [
"TestCoderAgent"
"TestOpenAIClientStreamChoices"
"TestGrepWithIgnoreFiles"
"TestSearchImplementations"
];
in ["-skip=^${builtins.concatStringsSep "$|^" skippedTests}$"];
})
];
programs = {
git.ignores = [".crush"];
fish.loginShellInit =
#fish
''
eval "$(crush completion fish)"
'';
};
xdg.configFile."crush/crush.json".source = (pkgs.formats.json {}).generate "crush-config" {
"$schema" = "https://charm.land/crush.json";
lsp = {
go.command = lib.getExe pkgs.gopls;
nix.command = lib.getExe pkgs.nil;
ruby = {
command = lib.getExe pkgs.solargraph;
args = ["stdio"];
env = {
RUBYOPT = "-W0";
};
};
typescript = {
args = ["--stdio"];
command = lib.getExe pkgs.typescript-language-server;
};
};
mcp = let
transformMcpServer = name: server: {
name = name;
value =
{
disabled = false;
timeout = 120;
}
// (
server
// (
if server ? url
then
if ((builtins.match ".*sse.*" server.url) == null)
then {type = "http";}
else {type = "sse";}
else if server ? command
then {type = "stdio";}
else {}
)
);
};
in
lib.listToAttrs (lib.mapAttrsToList transformMcpServer config.ai-agents.mcpServers);
};
};
}

View file

@ -0,0 +1,67 @@
{
config,
lib,
pkgs,
...
}: let
cfg = config.ai-agents;
json = pkgs.formats.json {};
in {
imports = [
./crush.nix
];
options.ai-agents = with lib;
with types; {
enable = mkEnableOption "AI Agents";
mcpServers = mkOption {
description = "MCP Configurations";
type = attrs;
default = {
git = {
args = ["mcp-server-git" "--repository" "${config.home.homeDirectory}/proj/nixos-system"];
command = "uvx";
};
};
};
};
config = lib.mkIf cfg.enable {
ai-agents.crush.enable = true;
home = {
file.".cursor/mcp.json".source = json.generate "cursor-mcp-config" {inherit (cfg) mcpServers;};
packages = with pkgs; [
nodejs_24 # for npx
uv # for uvx
];
};
programs = {
aider-chat.enable = true;
codex.enable = true;
opencode = {
enable = true;
enableMcpIntegration = true;
};
mcp = {
enable = true;
servers = cfg.mcpServers;
};
claude-code = {
inherit (cfg) mcpServers;
enable = true;
};
fabric-ai = {
enable = true;
enableZshIntegration = true;
};
};
};
}

View file

@ -511,14 +511,11 @@
},
"nixpkgs_5": {
"locked": {
"lastModified": 1767892417,
"narHash": "sha256-dhhvQY67aboBk8b0/u0XB6vwHdgbROZT3fJAjyNh5Ww=",
"lastModified": 1766309749,
"narHash": "sha256-3xY8CZ4rSnQ0NqGhMKAy5vgC+2IVK0NoVEzDoOh4DA4=",
"lastModified": 1768127708,
"narHash": "sha256-1Sm77VfZh3mU0F5OqKABNLWxOuDeHIlcFjsXeeiPazs=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "3497aa5c9457a9d88d71fa93a4a8368816fbeeba",
"rev": "a6531044f6d0bef691ea18d4d4ce44d0daa6e816",
"rev": "ffbc9f8cbaacfb331b6017d5a5abb21a492c9a38",
"type": "github"
},
"original": {

View file

@ -11,9 +11,14 @@
../../../common/home-manager/helix
../../../common/home-manager/jira
../../../common/home-manager/qutebrowser
../../../common/home-manager/ai-agents
homeage.homeManagerModules.homeage
];
ai-agents = {
enable = true;
crush.enable = true;
};
modules.aerospace.enable = true;
programs = {
aerc = {
@ -96,7 +101,7 @@
}
];
loginShellInit = ''
. $HOME/.nix-profile/share/asdf-vm/asdf.fish
# . $HOME/.nix-profile/share/asdf-vm/asdf.fish
'';
};
fzf = {
@ -124,6 +129,15 @@
active_border_color none
font_size 14.0
'';
environment = {
# for gemini
"GOOGLE_CLOUD_PROJECT" = "elegant-pipe-468016-d8";
"GOOGLE_CLOUD_LOCATION" = "global";
# for gemini via crush
"VERTEXAI_LOCATION" = "$GOOGLE_CLOUD_LOCATION";
"VERTEXAI_PROJECT" = "$GOOGLE_CLOUD_PROJECT";
};
shellIntegration.enableFishIntegration = true;
};
starship = {