Implement the complete homelab-deploy system with three operational modes: - Listener mode: Runs on NixOS hosts as a systemd service, subscribes to NATS subjects with configurable templates, executes nixos-rebuild on deployment requests with concurrency control - MCP mode: MCP server exposing deploy, deploy_admin, and list_hosts tools for AI assistants with tiered access control - CLI mode: Manual deployment commands with subject alias support via environment variables Key components: - internal/messages: Request/response types with validation - internal/nats: Client wrapper with NKey authentication - internal/deploy: Executor with timeout and lock for concurrency - internal/listener: Subject template expansion and request handling - internal/cli: Deploy logic with alias resolution - internal/mcp: MCP server with mcp-go integration - nixos/module.nix: NixOS module with hardened systemd service Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
4.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
homelab-deploy is a message-based deployment system for NixOS configurations using NATS for messaging. The binary operates in three modes:
- Listener mode - Runs on NixOS hosts as a systemd service, subscribes to NATS subjects, executes
nixos-rebuildon deployment requests - MCP mode - MCP server exposing deployment tools for AI assistants
- CLI mode - Manual deployment commands for administrators
Architecture
NATS Subject Structure
Default subjects follow deploy.<tier>.<target>, but are configurable via template variables:
deploy.<tier>.<hostname>- Deploy to specific hostdeploy.<tier>.all- Deploy to all hosts in tierdeploy.<tier>.role.<role>- Deploy to hosts with role in tierdeploy.responses.<uuid>- Response subject for request/replydeploy.discover- Host discovery subject
Template variables: <hostname>, <tier>, <role> - expanded at listener startup.
Package Structure
cmd/homelab-deploy/main.go # CLI entrypoint with urfave/cli/v3 subcommands
internal/messages/ # Shared message types (request, response, enums)
internal/nats/ # NATS client wrapper with NKey auth
internal/deploy/ # Deployment execution logic (nixos-rebuild, lock)
internal/listener/ # Listener mode (NATS subscription, request handling)
internal/cli/ # CLI deploy command logic and subject aliases
internal/mcp/ # MCP server mode
nixos/module.nix # NixOS module for listener service
Key Design Patterns
- Request/Reply over NATS: Deployer sends request with unique
reply_tosubject, listener responds with status updates - NKey authentication: All NATS connections use ed25519 NKey authentication
- Concurrency control: Only one deployment per host at a time (in-memory lock)
- Tiered access: MCP has separate credentials for test-tier vs admin (all tiers) access
Message Formats
Request: {"action": "switch|boot|test|dry-activate", "revision": "<branch-or-commit>", "reply_to": "<subject>"}
Response: {"hostname": "<name>", "status": "accepted|rejected|started|completed|failed", "error": "<code>|null", "message": "<details>"}
Dependencies
Key Go libraries:
github.com/urfave/cli/v3- CLI frameworkgithub.com/nats-io/nats.go- NATS clientgithub.com/nats-io/nkeys- NKey authenticationgithub.com/mark3labs/mcp-go- MCP server implementation
Build Commands
Run commands through the Nix development shell using nix develop -c:
# Build
nix develop -c go build ./...
# Run tests
nix develop -c go test ./...
# Run single test
nix develop -c go test -run TestName ./path/to/package
# Lint
nix develop -c golangci-lint run
# Vulnerability check
nix develop -c govulncheck ./...
# Test Nix build
nix build
# Run the binary (prefer this over go build + running binary)
# To pass arguments, use -- before them: nix run .#default -- --help
nix run .#default
Testing Procedures
Before committing, run the following checks:
nix develop -c go test ./...- Unit testsnix develop -c golangci-lint run- Lintingnix develop -c govulncheck ./...- Vulnerability scanningnix build- Verify nix build works
Commit Message Format
Use conventional commit format:
feat: add new feature
fix: fix a bug
docs: update documentation
refactor: refactor code without changing behavior
test: add or update tests
chore: maintenance tasks
Version Bumping
Follow semantic versioning:
- Patch (0.0.x): Bugfixes
- Minor (0.x.0): Non-breaking changes adding features
- Major (x.0.0): Breaking changes
Update the const version in main.go. The Nix build extracts the version from there automatically.
When to bump: If any Go code has changed, bump the version before committing. Do this automatically when asked to commit. On feature branches, only bump once per branch (check if version has already been bumped compared to master).