From c596038adc7cdbd64988e61fee856d533b58c25d Mon Sep 17 00:00:00 2001 From: "Simen A. W. Olsen" Date: Sun, 25 Oct 2026 12:41:28 +0100 Subject: feat: skills, a package manager for agent skills --- nix.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 nix.go (limited to 'nix.go') diff --git a/nix.go b/nix.go new file mode 100644 index 0000000..ddfccf7 --- /dev/null +++ b/nix.go @@ -0,0 +1,41 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "os" + "os/exec" + "strings" +) + +// managedBy names the tool that installs skills instead of this one, such as +// home-manager. skills then only maintains the lock and the Nix store. +func managedBy() string { return os.Getenv("SKILLS_MANAGED_BY") } + +// nixFetch copies a locked source into the Nix store as the current user and +// returns its narHash. A later evaluation, even by root without this user's +// SSH keys, then finds it there instead of fetching it. +func nixFetch(ctx context.Context, url, rev string) (string, error) { + ref := "git+" + url + "?rev=" + rev + "&allRefs=1" + cmd := exec.CommandContext(ctx, "nix", "--extra-experimental-features", "nix-command flakes", + "flake", "prefetch", "--json", ref) + var stderr bytes.Buffer + cmd.Stderr = &stderr + out, err := cmd.Output() + if errors.Is(err, exec.ErrNotFound) { + return "", fmt.Errorf("SKILLS_MANAGED_BY=%s needs nix, which is not installed", managedBy()) + } + if err != nil { + return "", fmt.Errorf("nix could not fetch %s: %s", url, strings.TrimSpace(stderr.String())) + } + var p struct { + Hash string `json:"hash"` + } + if err := json.Unmarshal(out, &p); err != nil || p.Hash == "" { + return "", fmt.Errorf("unexpected output from nix flake prefetch: %s", out) + } + return p.Hash, nil +} -- cgit v1.3.1