diff --git a/AGENTS.md b/AGENTS.md index 7427612..f696e1b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,7 +58,7 @@ Git workflow: OpenClaw packaging: - The gateway package must include Control UI assets (run `pnpm ui:build` in the Nix build). - Product intent: ship a working Nix package for OpenClaw users, not just a pin mirror. `openclaw-gateway` is the source-built runnable gateway for Linux and macOS; `openclaw-app` is the Darwin-only desktop app from upstream's signed/notarized app artifact; `openclaw` is the batteries-included bundle. -- User-facing docs should lead with one package: `openclaw`. Treat `openclaw-gateway`, `openclaw-tools`, and `openclaw-app` as advanced/component outputs for checks, modules, and debugging, not separate product tracks. +- User-facing docs should lead with one package: `openclaw`. Treat `openclaw-gateway` and `openclaw-app` as advanced/component outputs for checks, modules, and debugging, not separate product tracks. Runtime tools are internal implementation detail, not a public package surface. - README should be agent-first: the main setup path is "tell your coding agent you want OpenClaw using Nix, then let it inspect/interview/configure/verify." Manual commands are reference material, not the primary onboarding path. - Do not split the repo into separate desktop/server tracks. Segment package outputs, keep one simple user-facing flake. - DJTBOT deployment freshness is downstream and out of scope unless explicitly requested; fix public packaging first. diff --git a/README.md b/README.md index 79ca9ed..71c2a7c 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Bot: *runs whisper, sends you text* You talk to Telegram, your machine does things. -**One flake, everything works.** Gateway + tools everywhere; macOS app on macOS. +**One flake, everything works.** Gateway everywhere; runtime dependencies bundled; macOS app on macOS. **Plugins are self-contained.** Each plugin declares its CLI tools in Nix. You enable it, the build and wiring happens automatically. @@ -132,7 +132,7 @@ Repository: github:openclaw/nix-openclaw What nix-openclaw is: - Batteries-included Nix package for OpenClaw (AI assistant gateway) -- Installs gateway + tools everywhere; macOS app only on macOS +- Installs the gateway everywhere; macOS app only on macOS - Runs as a launchd service on macOS, systemd user service on Linux What I need you to do: @@ -616,26 +616,6 @@ programs.openclaw = { Plugins are keyed by their declared `name`. If two plugins declare the same name, the **last entry wins** (use this to override a prod plugin with a local dev one). -### Tool overrides (avoid collisions) - -Home Manager auto-excludes `git` when `programs.git.enable = true`. - -Drop built-in tools that you already install elsewhere: - -```nix -programs.openclaw.excludeTools = [ "git" "jq" "ripgrep" ]; -``` - -Or provide a custom list: - -```nix -programs.openclaw.toolNames = [ "nodejs_22" "pnpm_10" "summarize" ]; -``` - -If you override `programs.openclaw.package`, use `pkgs.openclawPackages.withTools { ... }.openclaw` to apply these lists. - ---- - ## Packaging & Updates **Goal:** `nix-openclaw` is a great Nix package. Automation, promotion, and fleet rollout live elsewhere. @@ -655,11 +635,10 @@ Outputs: ``` .#openclaw .#openclaw-gateway -.#openclaw-tools .#openclaw-app # Darwin only ``` -`.#openclaw-gateway`, `.#openclaw-tools`, and `.#openclaw-app` are component outputs for modules, CI, debugging, and advanced use. Start with `.#openclaw`. +`.#openclaw-gateway` and `.#openclaw-app` are component outputs for modules, CI, debugging, and advanced use. Start with `.#openclaw`. Pins live in: - `nix/sources/openclaw-source.nix` @@ -714,9 +693,8 @@ home-manager switch --rollback # revert | Package | Contents | | --- | --- | -| `openclaw` (default) | Canonical package. macOS: gateway + app + tools. Linux: gateway + tools. | +| `openclaw` (default) | Canonical package. Exposes `openclaw`; keeps runtime tools internal. macOS also links the app. | | `openclaw-gateway` | Component output: gateway CLI/service only | -| `openclaw-tools` | Component output: toolchain bundle | | `openclaw-app` | Component output: macOS app only | ### What we manage vs what you manage @@ -731,10 +709,12 @@ home-manager switch --rollback # revert | Anthropic API key | | ✓ | | Chat IDs | | ✓ | -### Included tools +### Runtime tools > **Platform note:** the toolchain is filtered per platform. macOS-only tools are skipped on Linux. +The default `openclaw` package uses these tools internally and does not expose them as separate user commands. + **Core**: nodejs, pnpm, git, curl, jq, python3, ffmpeg, sox, ripgrep **Default first-party tools** come from `nix-openclaw-tools`: gogcli (`gog`), goplaces, summarize, camsnap, sonoscli. diff --git a/flake.nix b/flake.nix index f05042a..3c5ff61 100644 --- a/flake.nix +++ b/flake.nix @@ -75,6 +75,9 @@ let baseChecks = { gateway = packageSetStable.openclaw-gateway; + bin-surface = pkgs.callPackage ./nix/checks/openclaw-bin-surface.nix { + openclawPackage = packageSetStable.openclaw; + }; package-contents = pkgs.callPackage ./nix/checks/openclaw-package-contents.nix { openclawGateway = packageSetStable.openclaw-gateway; }; @@ -114,7 +117,6 @@ paths = [ packageSetStable.openclaw packageSetStable.openclaw-gateway - packageSetStable.openclaw-tools ] ++ (builtins.attrValues baseChecks); }; diff --git a/nix/checks/openclaw-bin-surface.nix b/nix/checks/openclaw-bin-surface.nix new file mode 100644 index 0000000..647ad41 --- /dev/null +++ b/nix/checks/openclaw-bin-surface.nix @@ -0,0 +1,22 @@ +{ + lib, + stdenvNoCC, + openclawPackage, +}: + +stdenvNoCC.mkDerivation { + pname = "openclaw-bin-surface"; + version = lib.getVersion openclawPackage; + + dontUnpack = true; + dontConfigure = true; + dontBuild = true; + + env = { + OPENCLAW_PACKAGE = openclawPackage; + }; + + doCheck = true; + checkPhase = "${../scripts/check-openclaw-bin-surface.sh}"; + installPhase = "${../scripts/empty-install.sh}"; +} diff --git a/nix/packages/default.nix b/nix/packages/default.nix index c5eb613..dce025c 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -17,11 +17,6 @@ let pnpmDepsHash = sourceInfo.pnpmDepsHash or null; }; openclawApp = if isDarwin then pkgs.callPackage ./openclaw-app.nix { } else null; - openclawTools = pkgs.buildEnv { - name = "openclaw-tools"; - paths = toolSets.tools; - pathsToLink = [ "/bin" ]; - }; openclawBundle = pkgs.callPackage ./openclaw-batteries.nix { openclaw-gateway = openclawGateway; openclaw-app = openclawApp; @@ -32,6 +27,5 @@ in { openclaw-gateway = openclawGateway; openclaw = openclawBundle; - openclaw-tools = openclawTools; } // (if isDarwin then { openclaw-app = openclawApp; } else { }) diff --git a/nix/packages/openclaw-batteries.nix b/nix/packages/openclaw-batteries.nix index 0168cd7..8d4d01b 100644 --- a/nix/packages/openclaw-batteries.nix +++ b/nix/packages/openclaw-batteries.nix @@ -1,6 +1,7 @@ { lib, - buildEnv, + stdenvNoCC, + makeWrapper, openclaw-gateway, openclaw-app ? null, extendedTools ? [ ], @@ -8,20 +9,34 @@ }: let - appPaths = lib.optional (openclaw-app != null) openclaw-app; - appLinks = lib.optional (openclaw-app != null) "/Applications"; bundleVersion = if version != null && version != "" then version else lib.getVersion openclaw-gateway; + toolsPath = lib.makeBinPath extendedTools; in -buildEnv { - name = "openclaw-${bundleVersion}"; - paths = [ openclaw-gateway ] ++ appPaths ++ extendedTools; - pathsToLink = [ "/bin" ] ++ appLinks; +stdenvNoCC.mkDerivation { + pname = "openclaw"; + version = bundleVersion; + + dontUnpack = true; + dontConfigure = true; + dontBuild = true; + + nativeBuildInputs = [ makeWrapper ]; + + env = { + OPENCLAW_APP_PACKAGE = lib.optionalString (openclaw-app != null) "${openclaw-app}"; + OPENCLAW_GATEWAY_BIN = "${openclaw-gateway}/bin/openclaw"; + OPENCLAW_TOOLS_PATH = toolsPath; + STDENV_SETUP = "${stdenvNoCC}/setup"; + }; + + installPhase = "${../scripts/openclaw-batteries-install.sh}"; meta = with lib; { description = "OpenClaw batteries-included bundle (gateway + app + tools)"; homepage = "https://github.com/openclaw/openclaw"; license = licenses.mit; platforms = platforms.darwin ++ platforms.linux; + mainProgram = "openclaw"; }; } diff --git a/nix/scripts/check-openclaw-bin-surface.sh b/nix/scripts/check-openclaw-bin-surface.sh new file mode 100755 index 0000000..415bb61 --- /dev/null +++ b/nix/scripts/check-openclaw-bin-surface.sh @@ -0,0 +1,35 @@ +#!/bin/sh +set -eu + +if [ -z "${OPENCLAW_PACKAGE:-}" ]; then + echo "OPENCLAW_PACKAGE is not set" >&2 + exit 1 +fi + +bin_dir="${OPENCLAW_PACKAGE}/bin" +openclaw_bin="${bin_dir}/openclaw" + +if [ ! -x "$openclaw_bin" ]; then + echo "Missing executable: $openclaw_bin" >&2 + exit 1 +fi + +extra_bins="$(find "$bin_dir" -mindepth 1 -maxdepth 1 -print | while IFS= read -r entry; do + name="$(basename "$entry")" + if [ "$name" != "openclaw" ]; then + printf '%s\n' "$name" + fi +done)" + +if [ -n "$extra_bins" ]; then + echo "openclaw package exposes internal runtime tools in bin:" >&2 + printf '%s\n' "$extra_bins" >&2 + exit 1 +fi + +if ! grep -q 'PATH' "$openclaw_bin"; then + echo "openclaw wrapper does not set the internal runtime tool PATH" >&2 + exit 1 +fi + +echo "openclaw bin surface: ok" diff --git a/nix/scripts/openclaw-batteries-install.sh b/nix/scripts/openclaw-batteries-install.sh new file mode 100755 index 0000000..e9c9ffe --- /dev/null +++ b/nix/scripts/openclaw-batteries-install.sh @@ -0,0 +1,48 @@ +#!/bin/sh +set -eu + +if [ -z "${OPENCLAW_GATEWAY_BIN:-}" ]; then + echo "OPENCLAW_GATEWAY_BIN is not set" >&2 + exit 1 +fi +if [ ! -x "$OPENCLAW_GATEWAY_BIN" ]; then + echo "OPENCLAW_GATEWAY_BIN is not executable: $OPENCLAW_GATEWAY_BIN" >&2 + exit 1 +fi +if [ -z "${STDENV_SETUP:-}" ]; then + echo "STDENV_SETUP is not set" >&2 + exit 1 +fi +if [ ! -f "$STDENV_SETUP" ]; then + echo "STDENV_SETUP not found: $STDENV_SETUP" >&2 + exit 1 +fi + +mkdir -p "$out/bin" + +if [ -n "${OPENCLAW_TOOLS_PATH:-}" ]; then + bash -e -c '. "$STDENV_SETUP"; makeWrapper "$OPENCLAW_GATEWAY_BIN" "$out/bin/openclaw" --prefix PATH : "$OPENCLAW_TOOLS_PATH"' +else + bash -e -c '. "$STDENV_SETUP"; makeWrapper "$OPENCLAW_GATEWAY_BIN" "$out/bin/openclaw"' +fi + +if [ -n "${OPENCLAW_APP_PACKAGE:-}" ]; then + app_dir="${OPENCLAW_APP_PACKAGE}/Applications" + if [ ! -d "$app_dir" ]; then + echo "OpenClaw app package has no Applications directory: $OPENCLAW_APP_PACKAGE" >&2 + exit 1 + fi + + mkdir -p "$out/Applications" + found_app=0 + for app in "$app_dir"/*.app; do + [ -e "$app" ] || continue + ln -s "$app" "$out/Applications/$(basename "$app")" + found_app=1 + done + + if [ "$found_app" -ne 1 ]; then + echo "OpenClaw app package has no .app under: $app_dir" >&2 + exit 1 + fi +fi