summaryrefslogtreecommitdiffstats
path: root/nix.go
diff options
context:
space:
mode:
authorSimen A. W. Olsen <hello@simenandre.no>2026-10-25 12:41:28 +0100
committerSimen A. W. Olsen <hello@simenandre.no>2026-10-25 12:41:28 +0100
commitc596038adc7cdbd64988e61fee856d533b58c25d (patch)
treea02fde25835416d143ff56b807e640f6a7e9cf82 /nix.go
downloadskills-c596038adc7cdbd64988e61fee856d533b58c25d.tar.gz
skills-c596038adc7cdbd64988e61fee856d533b58c25d.zip
feat: skills, a package manager for agent skillsHEADv0.1.0main
Diffstat (limited to 'nix.go')
-rw-r--r--nix.go41
1 files changed, 41 insertions, 0 deletions
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
+}