diff --git a/docs/nix.md b/docs/nix.md new file mode 100644 index 00000000..bf1685e1 --- /dev/null +++ b/docs/nix.md @@ -0,0 +1,74 @@ +# Nix package + +INSOMNIA provides a flake package for installing the user-facing Pod CLI and TUI binaries without relying on a source checkout at runtime. + +## Build + +From the repository root: + +```sh +nix build .# +``` + +The default package is implemented by `package.nix` and builds the Cargo workspace binaries `pod` and `tui`. The derivation uses the checked-in `Cargo.lock`, so Cargo dependencies are fetched by the normal Nix Rust packaging path instead of by network access during the build. + +The package output contains: + +- `bin/pod` — Pod CLI / runtime process. +- `bin/tui` — terminal UI. +- `share/insomnia/resources/` — bundled runtime resources, including `resources/prompts/`. +- `share/doc/insomnia/nix.md` — this document. + +## Run + +After `nix build`: + +```sh +./result/bin/pod --help +./result/bin/tui +``` + +With flakes: + +```sh +nix run .#tui +nix run .#pod -- --help +``` + +`nix run .#` defaults to the TUI. + +## Configuration discovery + +The Nix package does not put user configuration, sessions, sockets, or other mutable state in the Nix store. The installed binaries keep the same path semantics as non-Nix builds: + +| Purpose | Override | `INSOMNIA_HOME` fallback | XDG / default fallback | +| --- | --- | --- | --- | +| User config (`manifest.toml`, prompt overrides, model/provider overrides) | `INSOMNIA_CONFIG_DIR` | `$INSOMNIA_HOME/config` | `$XDG_CONFIG_HOME/insomnia`, then `$HOME/.config/insomnia` | +| Persistent data (`sessions/`, Pod metadata) | `INSOMNIA_DATA_DIR` | `$INSOMNIA_HOME` | `$HOME/.insomnia` | +| Runtime state (sockets, lock files, live registry) | `INSOMNIA_RUNTIME_DIR` | `$INSOMNIA_HOME/run` | `$XDG_RUNTIME_DIR/insomnia`, then `$HOME/.insomnia/run` | + +`INSOMNIA_USER_MANIFEST=` can still be used to select an explicit user manifest for the Pod CLI cascade path. Project manifests are still discovered from `.insomnia/manifest.toml` under the current workspace unless a CLI mode documents otherwise. + +## Validation + +The package derivation has a credential-free install check that verifies: + +- `pod --help` starts successfully. +- `tui` is installed and reaches argument parsing. +- bundled prompt resources and this Nix usage document are present in the output. + +For full validation before handing changes to review, run: + +```sh +nix build .# +nix flake check +cargo fmt --check +``` + +This packaging change does not require provider credentials. A Rust `cargo check` is only needed if Rust source or runtime path semantics are changed. + +## Known limitations + +- The package currently installs the TUI and Pod CLI only; development-only wrappers from `devshell.nix` are not part of the installable package. +- The TUI does not currently expose a conventional `--help` / `--version` CLI path, so the package smoke check uses an argument-parse failure path for the TUI rather than launching an interactive session. +- Bundled resources are installed under `share/insomnia/resources/` for packaging completeness and inspection. Built-in prompt/resource loading remains governed by the existing application code and user/project override rules. diff --git a/flake.nix b/flake.nix index 0f493fb7..38b62d8c 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "A very basic flake"; + description = "INSOMNIA agent runtime"; inputs = { nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; @@ -16,9 +16,22 @@ system: let pkgs = nixpkgs.legacyPackages.${system}; + insomnia = pkgs.callPackage ./package.nix { }; + mkApp = name: description: { + type = "app"; + program = "${insomnia}/bin/${name}"; + meta.description = description; + }; in { - packages.default = pkgs.callPackage ./package.nix { }; + packages.default = insomnia; + packages.insomnia = insomnia; + + apps.default = mkApp "tui" "Run the INSOMNIA terminal UI"; + apps.tui = mkApp "tui" "Run the INSOMNIA terminal UI"; + apps.pod = mkApp "pod" "Run the INSOMNIA Pod CLI"; + + checks.default = insomnia; devShells.default = import ./devshell.nix { inherit pkgs; }; } diff --git a/package.nix b/package.nix index e69de29b..1e050bd0 100644 --- a/package.nix +++ b/package.nix @@ -0,0 +1,97 @@ +{ + lib, + stdenv, + rustPlatform, + pkg-config, + openssl, + darwin, +}: + +let + srcRoot = ./.; + srcRootString = toString srcRoot; + sourceFilter = + path: type: + let + pathString = toString path; + relPath = lib.removePrefix "${srcRootString}/" pathString; + baseName = baseNameOf pathString; + in + !( + baseName == ".git" + || baseName == "target" + || baseName == "result" + || lib.hasPrefix ".insomnia" relPath + || lib.hasPrefix "work-items" relPath + ); +in +rustPlatform.buildRustPackage rec { + pname = "insomnia"; + version = "0.1.0"; + + src = lib.cleanSourceWith { + src = srcRoot; + filter = sourceFilter; + }; + + cargoLock.lockFile = ./Cargo.lock; + + strictDeps = true; + + nativeBuildInputs = [ pkg-config ]; + + buildInputs = [ + openssl + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin ( + with darwin.apple_sdk.frameworks; + [ + CoreFoundation + Security + SystemConfiguration + ] + ); + + cargoBuildFlags = [ + "-p" + "pod" + "-p" + "tui" + ]; + + # The package check is a credential-free install smoke check below. Running the + # workspace test suite is intentionally left to cargo-based CI because this + # derivation is scoped to packaging the user-facing binaries. + doCheck = false; + + postInstall = '' + install -Dm644 docs/nix.md "$out/share/doc/insomnia/nix.md" + mkdir -p "$out/share/insomnia" + cp -R resources "$out/share/insomnia/resources" + ''; + + doInstallCheck = true; + installCheckPhase = '' + runHook preInstallCheck + + "$out/bin/pod" --help >/dev/null + test -x "$out/bin/tui" + if "$out/bin/tui" --session not-a-uuid 2>tui.err; then + echo "tui unexpectedly accepted an invalid --session value" >&2 + exit 1 + fi + grep -q "invalid --session UUID" tui.err + + test -d "$out/share/insomnia/resources/prompts" + test -f "$out/share/doc/insomnia/nix.md" + + runHook postInstallCheck + ''; + + meta = { + description = "Agentic coding Pod runtime and terminal UI"; + license = lib.licenses.mit; + mainProgram = "tui"; + platforms = lib.platforms.unix; + }; +}