skills/flake.nix
dan 5759ccc8fe feat: add web search and browser automation skills
- brave-search: Web search via Brave Search API
- browser-tools: Interactive browser automation via Chrome DevTools Protocol
- flake.nix: Add brave and kagi API key support
2026-01-24 09:40:15 -08:00

135 lines
4.6 KiB
Nix

{
description = "AI agent skills for Claude Code and OpenCode";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
let
# Home Manager module for deploying skills
skillsModule = import ./modules/ai-skills.nix;
# List of available skills
availableSkills = builtins.attrNames (import ./skills.nix);
in
flake-utils.lib.eachDefaultSystem
(system:
let
pkgs = import nixpkgs { inherit system; };
in
{
# Development shell for working on skills
devShells.default = pkgs.mkShell {
name = "ai-skills";
packages = with pkgs; [
bash
shellcheck
jq
];
shellHook = ''
echo "🤖 AI Skills development environment"
echo "Available skills: ${builtins.concatStringsSep ", " availableSkills}"
echo ""
echo "Commands:"
echo " ./bin/deploy-skill.sh <name> - Copy skill to dotfiles"
echo " bash -n skills/*/scripts/*.sh - Validate all scripts"
'';
};
# Package individual skills for deployment
packages =
let
# Filter to only skills that exist
existingSkills = builtins.filter
(name: builtins.pathExists (./skills + "/${name}"))
availableSkills;
individualSkills = builtins.listToAttrs (
map (skillName: {
name = skillName;
value = pkgs.stdenv.mkDerivation {
name = "ai-skill-${skillName}";
src = ./skills + "/${skillName}";
installPhase = ''
mkdir -p $out
cp -r . $out/
# Make scripts executable
if [ -d $out/scripts ]; then
chmod +x $out/scripts/*.sh 2>/dev/null || true
fi
'';
};
}) existingSkills
);
in
individualSkills // {
# All skills as a combined package
all-skills = pkgs.symlinkJoin {
name = "all-ai-skills";
paths = builtins.attrValues individualSkills;
};
};
})
// {
# Export the Home Manager module
homeManagerModules.ai-skills = skillsModule;
# Also export as nixosModules for compatibility
nixosModules.ai-skills = skillsModule;
# Export skills paths for direct use
lib = {
inherit availableSkills;
# Helper to get skill path
getSkillPath = skillName: ./skills/${skillName};
# Helper to get all skill paths
getAllSkillPaths = map (name: ./skills/${name}) availableSkills;
# API Keys - Single Source of Truth
# Used by both direnv stdlib and sops-nix configuration
apiKeys = [ "openai" "google" "anthropic" "openrouter" "brave" "kagi" ];
# Generate direnv stdlib use_api_keys function
mkDirenvStdlib = keys:
let
toEnvVar = key: {
"openai" = "OPENAI_API_KEY";
"google" = "GEMINI_API_KEY";
"anthropic" = "ANTHROPIC_API_KEY";
"openrouter" = "OPENROUTER_API_KEY";
"brave" = "BRAVE_API_KEY";
"kagi" = "KAGI_API_KEY";
}.${key} or (builtins.throw "Unknown API key: ${key}");
# Google key exports both GEMINI_API_KEY and GOOGLE_API_KEY
mkExport = key:
if key == "google" then ''
[ -f /run/secrets/api_keys/${key} ] && export ${toEnvVar key}="$(cat /run/secrets/api_keys/${key})" && export GOOGLE_API_KEY="$GEMINI_API_KEY"''
else ''
[ -f /run/secrets/api_keys/${key} ] && export ${toEnvVar key}="$(cat /run/secrets/api_keys/${key})"'';
in ''
use_api_keys() {
${builtins.concatStringsSep "\n " (map mkExport keys)}
}
'';
# Generate sops-nix secrets attribute set
mkSopsSecrets = { keys, owner, group ? "users" }:
builtins.listToAttrs (map (key: {
name = "api_keys/${key}";
value = {
mode = "0600";
inherit owner group;
};
}) keys);
};
};
}