From 74e87d485f465778e077c7090d08f6b78902160c Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Mon, 31 Aug 2026 23:12:37 -0700 Subject: [PATCH 01/32] feat(nix): add flake, devbox, and CI for building acryl-tui Add Nix flake support targeting the acryl-tui terminal client. The flake uses nixpkgs' modern PNPM hooks (fetchPnpmDeps, pnpmConfigHook) with pnpm_11 and fetcherVersion 4. Key design decisions: - Targets acryl-tui (not the Electron desktop app) as the default package, exposing the `acryl` binary via `nix run .#acryl` - Uses nixpkgs-26.05-darwin legacy pin for x86_64-darwin (Intel macOS), since nixpkgs-unstable dropped support after 26.05 - Forces nodeLinker: hoisted in pnpm-workspace.yaml during the build to flatten node_modules (pnpm 11 moved this setting from .npmrc) - Builds only the TUI dependency chain (acryl-control -> acryl-harness-runtime -> acryl-tui) instead of the full workspace - Sets dontStrip and dontFixup to avoid slow strip/fixup phases on thousands of JS files in node_modules - ESBUILD_BINARY_PATH points to nixpkgs esbuild to avoid the postinstall binary download (skipped by --ignore-scripts) Also adds: - devbox.json for reproducible development environment - .github/workflows/nix.yml for CI across all 4 supported systems - /result and /result-* to .gitignore --- .github/workflows/nix.yml | 51 ++++++++++ flake.lock | 60 ++++++++++++ flake.nix | 192 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 303 insertions(+) create mode 100644 .github/workflows/nix.yml create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml new file mode 100644 index 00000000..83eecb15 --- /dev/null +++ b/.github/workflows/nix.yml @@ -0,0 +1,51 @@ +name: Nix + +on: + pull_request: + branches: [main] + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: nix-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Build (${{ matrix.system }}) + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - system: x86_64-linux + runner: ubuntu-latest + - system: aarch64-linux + runner: ubuntu-24.04-arm + - system: aarch64-darwin + runner: macos-14 + # x86_64-darwin uses nixpkgs-26.05-darwin legacy pin + - system: x86_64-darwin + runner: macos-13 + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - uses: DeterminateSystems/nix-installer-action@main + + - uses: DeterminateSystems/magic-nix-cache-action@main + + - name: Check flake + run: nix flake check --no-build + + - name: Build acryl TUI + run: nix build .#acryl --system ${{ matrix.system }} + + - name: Test --help + run: nix run .#acryl -- --help diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..35a68c49 --- /dev/null +++ b/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1787964612, + "narHash": "sha256-0N9nghg3nwzX6b6qc77EzjR9cu/Z+UR66FlfsCqiURs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e8be7818e19ada32105a8af937a6a473b38167ca", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-darwin-legacy": { + "locked": { + "lastModified": 1787940818, + "narHash": "sha256-vFzVv78WlyEbTyV5BbrnicnV159wC0YPOcBe3QagyBI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "f6107e546a5012172d93e79f1f7950da02ad798f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-26.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "nixpkgs-darwin-legacy": "nixpkgs-darwin-legacy", + "systems": "systems" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..fad337cf --- /dev/null +++ b/flake.nix @@ -0,0 +1,192 @@ +{ + description = "ACRYL local-first plugin-native agent workspace"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + # x86_64-darwin was dropped from nixpkgs-unstable after 26.05. + # Pin the 26.05-darwin stable branch for Intel macOS. + nixpkgs-darwin-legacy.url = "github:NixOS/nixpkgs/nixpkgs-26.05-darwin"; + systems.url = "github:nix-systems/default"; + }; + + outputs = { self, nixpkgs, nixpkgs-darwin-legacy, systems, ... }: + let + allSystems = import systems; + + # Use the legacy pin for x86_64-darwin, unstable for everything else. + nixpkgsFor = system: + if system == "x86_64-darwin" + then nixpkgs-darwin-legacy + else nixpkgs; + + forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f { + inherit system; + pkgs = (nixpkgsFor system).legacyPackages.${system}; + }); + + # Filter out the deepseek-harness git submodule and other directories + # that are not needed for building the TUI. The patches/ directory MUST + # be included because pnpm-workspace.yaml references patch files there. + filterSrc = root: + let + base = toString root; + in + pkgs': path: type: + let + rel = pkgs'.lib.removePrefix base path; + in + ( + # Exclude the deepseek-harness submodule (large, not in workspace) + !pkgs'.lib.hasPrefix "/deepseek-harness" rel && + # Exclude VCS and tooling directories + !pkgs'.lib.hasPrefix "/.git" rel && + !pkgs'.lib.hasPrefix "/.agents" rel && + !pkgs'.lib.hasPrefix "/.claude" rel && + !pkgs'.lib.hasPrefix "/.specify" rel && + !pkgs'.lib.hasPrefix "/.github" rel && + # Exclude documentation and spec directories + !pkgs'.lib.hasPrefix "/specs" rel && + !pkgs'.lib.hasPrefix "/docs" rel && + # Exclude media assets + !pkgs'.lib.hasPrefix "/assets" rel && + rel != "/acryl-logo.png" && + rel != "/acryl-logo-white.png" && + # Exclude Nix build outputs + !pkgs'.lib.hasPrefix "/result" rel + ); + in + { + packages = forAllSystems ({ pkgs, system }: + let + pnpm = pkgs.pnpm_11; + version = (pkgs.lib.importJSON ./package.json).version; + + src = pkgs.lib.cleanSourceWith { + src = ./.; + filter = filterSrc ./. pkgs; + name = "acryl-source"; + }; + + pnpmDeps = pkgs.fetchPnpmDeps { + pname = "acryl"; + inherit version src pnpm; + fetcherVersion = 4; + hash = "sha256-eSJETc4rpA3jrGHOqVcatiLxlhOeg5cpX9wOL2r+3eA="; + }; + in + { + default = self.packages.${system}.acryl; + + acryl = pkgs.stdenv.mkDerivation (finalAttrs: { + pname = "acryl"; + inherit version src pnpmDeps pnpm; + + nativeBuildInputs = [ + pkgs.nodejs_22 + pkgs.pnpmConfigHook + pnpm + pkgs.makeWrapper + ]; + + # esbuild's postinstall (which downloads a platform binary) is + # skipped by --ignore-scripts in pnpmConfigHook. Point + # tsdown/esbuild at the nixpkgs-provided binary instead. + env.ESBUILD_BINARY_PATH = "${pkgs.esbuild}/bin/esbuild"; + + # Force hoisted node-linker so all dependencies are flattened + # into a single node_modules/ directory (like npm's layout). + # In pnpm 11, this setting moved from .npmrc to pnpm-workspace.yaml + # as "nodeLinker". The project's .npmrc still has the old key. + preConfigure = '' + if ! grep -q "nodeLinker" pnpm-workspace.yaml; then + sed -i.bak '1i nodeLinker: hoisted' pnpm-workspace.yaml + rm -f pnpm-workspace.yaml.bak + fi + ''; + + # Don't let pnpmBuildHook run the root "build" script (which + # builds ALL workspace packages including the Electron desktop + # app). We build only the TUI dependency chain manually. + dontPnpmBuild = true; + + # Don't strip debug symbols from JS files in node_modules — + # Nix's strip phase runs `strip -S` on every file, which is + # extremely slow for thousands of .js files and unnecessary + # for interpreted JavaScript. + dontStrip = true; + + # Skip the entire fixup phase (strip, patchShebangs on output, + # broken symlink check). The build phase already runs + # patchShebangs via pnpmConfigHook, and the fixup phase's + # `find -type l` scan over 800+ MB of node_modules is very slow. + dontFixup = true; + + buildPhase = '' + runHook preBuild + + # Build the TUI dependency chain. + # acryl-harness-runtime imports types from acryl-control, so + # acryl-control must be built first. Then acryl-harness-runtime, + # then acryl-tui (which depends on both). + pnpm --filter acryl-control run build + pnpm --filter acryl-harness-runtime run build + pnpm --filter acryl-tui run build + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/lib/acryl $out/bin + + # Copy the built TUI + cp -r acryl-tui/lib $out/lib/acryl/lib + cp acryl-tui/package.json $out/lib/acryl/ + + # With node-linker=hoisted, node_modules/ is a flat directory + # (like npm's layout) with no .pnpm/ virtual store symlinks. + # Just copy it as-is. + cp -a node_modules $out/lib/acryl/node_modules + + # Replace workspace package symlinks/dirs with actual built + # packages (the hoisted linker may have created symlinks for + # workspace packages that point to source directories). + rm -rf $out/lib/acryl/node_modules/acryl-control + mkdir -p $out/lib/acryl/node_modules/acryl-control + cp -r acryl-control/lib $out/lib/acryl/node_modules/acryl-control/lib + cp acryl-control/package.json $out/lib/acryl/node_modules/acryl-control/ + + rm -rf $out/lib/acryl/node_modules/acryl-harness-runtime + mkdir -p $out/lib/acryl/node_modules/acryl-harness-runtime + cp -r acryl-harness-runtime/lib $out/lib/acryl/node_modules/acryl-harness-runtime/lib + cp acryl-harness-runtime/package.json $out/lib/acryl/node_modules/acryl-harness-runtime/ + + # Wrap the TUI entry point + makeWrapper ${pkgs.nodejs_22}/bin/node $out/bin/acryl \ + --add-flags "$out/lib/acryl/lib/bin.js" + + runHook postInstall + ''; + + meta = with pkgs.lib; { + description = "ACRYL local-first plugin-native agent workspace (TUI)"; + homepage = "https://github.com/levonk/acryl"; + license = licenses.mit; + mainProgram = "acryl"; + platforms = platforms.unix; + }; + }); + }); + + devShells = forAllSystems ({ pkgs, system }: { + default = pkgs.mkShell { + packages = with pkgs; [ + nodejs_22 + pnpm_11 + esbuild + ]; + }; + }); + }; +} From 41b15c4eb9557b16e8e4eed8791ab91530df8c9d Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Mon, 31 Aug 2026 23:13:07 -0700 Subject: [PATCH 02/32] docs: record Nix flake support in DEVELOPMENT-LOG.md Document the implementation commit d6d2e464db46fbe61c36e84136880d8c55ac5a0d which added Nix flake support for building acryl-tui. --- docs/DEVELOPMENT-LOG.md | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/docs/DEVELOPMENT-LOG.md b/docs/DEVELOPMENT-LOG.md index ccdf5a02..b600be8e 100644 --- a/docs/DEVELOPMENT-LOG.md +++ b/docs/DEVELOPMENT-LOG.md @@ -657,6 +657,58 @@ the plugin path with one real model-facing Tool as the hard gate. Follow-on diff (authorization pipeline, room identity, relay/handoff, capability package, agent-agnostic canvas) are intentionally recorded as subsequent ledgers. +## 2026-08-31 - Nix flake support for acryl-tui + +**Commit:** [`d6d2e464db46fbe61c36e84136880d8c55ac5a0d`](https://github.com/levonk/acryl/commit/d6d2e464db46fbe61c36e84136880d8c55ac5a0d) + +Added Nix flake support targeting the `acryl-tui` terminal client. The flake +builds the TUI and its workspace dependencies (`acryl-control`, +`acryl-harness-runtime`) using nixpkgs' modern PNPM hooks, producing a +runnable `acryl` binary. + +### What was added + +- `flake.nix` — Nix flake with `packages.${system}.acryl` (default) and + `devShells.${system}.default` +- `flake.lock` — Locked inputs (nixpkgs-unstable, nixpkgs-26.05-darwin, + nix-systems/default) +- `devbox.json` — Reproducible development environment +- `.github/workflows/nix.yml` — CI for all 4 supported systems +- `.gitignore` — `/result` and `/result-*` entries + +### Key design decisions + +- **TUI target, not Electron:** The flake builds `acryl-tui` (the terminal + client) as the default package. Packaging the Electron desktop app via Nix + is a separate, harder problem deferred to future work. + +- **Intel macOS support:** nixpkgs-unstable (26.11) dropped `x86_64-darwin`. + The flake pins `nixpkgs-26.05-darwin` for Intel macOS and uses unstable for + all other systems. + +- **Modern PNPM API:** Uses `fetchPnpmDeps` with `fetcherVersion = 4`, + `pnpmConfigHook`, and `pnpm_11` (not the deprecated `pnpm.fetchDeps`). + +- **Hoisted node-linker:** Forces `nodeLinker: hoisted` in + `pnpm-workspace.yaml` during the build (pnpm 11 moved this setting from + `.npmrc`). This flattens `node_modules/` so the install phase can copy it + without resolving pnpm's `.pnpm/` virtual store symlinks. + +- **Selective build:** Builds only `acryl-control -> acryl-harness-runtime -> + acryl-tui` instead of the full workspace (which includes Electron). + +- **Performance:** `dontStrip` and `dontFixup` skip Nix's strip and fixup + phases, which are extremely slow on thousands of JS files in node_modules. + +### Usage + +```sh +nix build .#acryl +nix run .#acryl -- --help +nix run .#acryl -- --version +``` + +--- ## 2026-08-31 - shared coding capability composition implementation plan Commit: `8b6a955` From 829594529ad6021c60892c13c999dbfff6fc6e00 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Tue, 1 Sep 2026 08:42:55 -0700 Subject: [PATCH 03/32] feat(nix): add acryl-desktop (Electron) as separate Nix package output Add `packages.${system}.acryl-desktop` to the flake, building the Electron desktop app alongside the existing TUI output. Key decisions: - Uses nixpkgs electron (43.1.0) as the runtime instead of the npm electron package (which downloads a platform binary via postinstall, blocked by --ignore-scripts in the Nix sandbox) - Creates a CJS shim at node_modules/electron/index.js that exports the nixpkgs electron path, replacing the real npm package - Skips the generate-* build scripts (they use sharp for image processing) since build/ assets are already tracked in git - Builds the full dependency chain: acryl-control -> acryl-harness-runtime -> dsh-community-market -> acryl-development-canvas -> acryl-desktop - Refactors shared derivation attrs (pnpmDeps, preConfigure, etc.) into commonDerivationAttrs to avoid duplication between TUI and desktop derivations Both outputs verified: nix run .#acryl -- --help nix run .#acryl-desktop -- --help --- .github/workflows/nix.yml | 8 ++- flake.nix | 127 +++++++++++++++++++++++++++++++++----- 2 files changed, 117 insertions(+), 18 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 83eecb15..8b909061 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -47,5 +47,11 @@ jobs: - name: Build acryl TUI run: nix build .#acryl --system ${{ matrix.system }} - - name: Test --help + - name: Build acryl-desktop + run: nix build .#acryl-desktop --system ${{ matrix.system }} + + - name: Test TUI --help run: nix run .#acryl -- --help + + - name: Test desktop --help + run: nix run .#acryl-desktop -- --help diff --git a/flake.nix b/flake.nix index fad337cf..68f9344f 100644 --- a/flake.nix +++ b/flake.nix @@ -73,12 +73,9 @@ fetcherVersion = 4; hash = "sha256-eSJETc4rpA3jrGHOqVcatiLxlhOeg5cpX9wOL2r+3eA="; }; - in - { - default = self.packages.${system}.acryl; - acryl = pkgs.stdenv.mkDerivation (finalAttrs: { - pname = "acryl"; + # Shared flags for both TUI and desktop derivations. + commonDerivationAttrs = { inherit version src pnpmDeps pnpm; nativeBuildInputs = [ @@ -105,8 +102,8 @@ ''; # Don't let pnpmBuildHook run the root "build" script (which - # builds ALL workspace packages including the Electron desktop - # app). We build only the TUI dependency chain manually. + # builds ALL workspace packages). We build only the needed + # dependency chains manually in each derivation's buildPhase. dontPnpmBuild = true; # Don't strip debug symbols from JS files in node_modules — @@ -118,8 +115,27 @@ # Skip the entire fixup phase (strip, patchShebangs on output, # broken symlink check). The build phase already runs # patchShebangs via pnpmConfigHook, and the fixup phase's - # `find -type l` scan over 800+ MB of node_modules is very slow. + # `find -type l` scan over node_modules is very slow. dontFixup = true; + }; + + # Helper to install a built workspace package into a node_modules + # directory, replacing any symlink/dir that the hoisted linker + # may have created. + installWorkspacePackage = pkgDir: destDir: '' + rm -rf ${destDir}/${pkgDir} + mkdir -p ${destDir}/${pkgDir} + cp -r ${pkgDir}/lib ${destDir}/${pkgDir}/lib + cp ${pkgDir}/package.json ${destDir}/${pkgDir}/ + ''; + in + { + default = self.packages.${system}.acryl; + + acryl = pkgs.stdenv.mkDerivation (finalAttrs: { + pname = "acryl"; + inherit (commonDerivationAttrs) version src pnpmDeps pnpm nativeBuildInputs preConfigure dontPnpmBuild dontStrip dontFixup; + env.ESBUILD_BINARY_PATH = commonDerivationAttrs.env.ESBUILD_BINARY_PATH; buildPhase = '' runHook preBuild @@ -152,15 +168,8 @@ # Replace workspace package symlinks/dirs with actual built # packages (the hoisted linker may have created symlinks for # workspace packages that point to source directories). - rm -rf $out/lib/acryl/node_modules/acryl-control - mkdir -p $out/lib/acryl/node_modules/acryl-control - cp -r acryl-control/lib $out/lib/acryl/node_modules/acryl-control/lib - cp acryl-control/package.json $out/lib/acryl/node_modules/acryl-control/ - - rm -rf $out/lib/acryl/node_modules/acryl-harness-runtime - mkdir -p $out/lib/acryl/node_modules/acryl-harness-runtime - cp -r acryl-harness-runtime/lib $out/lib/acryl/node_modules/acryl-harness-runtime/lib - cp acryl-harness-runtime/package.json $out/lib/acryl/node_modules/acryl-harness-runtime/ + ${installWorkspacePackage "acryl-control" "$out/lib/acryl/node_modules"} + ${installWorkspacePackage "acryl-harness-runtime" "$out/lib/acryl/node_modules"} # Wrap the TUI entry point makeWrapper ${pkgs.nodejs_22}/bin/node $out/bin/acryl \ @@ -177,6 +186,90 @@ platforms = platforms.unix; }; }); + + acryl-desktop = pkgs.stdenv.mkDerivation (finalAttrs: { + pname = "acryl-desktop"; + inherit (commonDerivationAttrs) version src pnpmDeps pnpm nativeBuildInputs preConfigure dontPnpmBuild dontStrip dontFixup; + env.ESBUILD_BINARY_PATH = commonDerivationAttrs.env.ESBUILD_BINARY_PATH; + + # Electron is needed at build time for vite and at runtime. + # nixpkgs electron (43.1.0) is close to the project's 43.4.0. + buildInputs = [ pkgs.electron ]; + + buildPhase = '' + runHook preBuild + + # Build the full dependency chain for the desktop app. + # Order matters: each package imports types from its deps. + pnpm --filter acryl-control run build + pnpm --filter acryl-harness-runtime run build + pnpm --filter dsh-community-market run build + pnpm --filter acryl-development-canvas run build + + # Build the desktop package. Skip the generate-* scripts + # (they use sharp for image processing) since the build/ + # directory with pre-generated assets is already tracked + # in git. Run tsdown, vite, and tsc directly. + pnpm --filter acryl-desktop exec tsdown + pnpm --filter acryl-desktop exec vite build --config vite.native-ui.config.ts + pnpm --filter acryl-desktop exec tsc -p tsconfig.json --emitDeclarationOnly + pnpm --filter acryl-desktop exec tsc -p tsconfig.client.json --emitDeclarationOnly + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/lib/acryl-desktop $out/bin + + # Copy the built desktop package + cp -r acryl-desktop/lib $out/lib/acryl-desktop/lib + cp -r acryl-desktop/build $out/lib/acryl-desktop/build + cp acryl-desktop/package.json $out/lib/acryl-desktop/ + cp acryl-desktop/cordis.patch.yml $out/lib/acryl-desktop/ 2>/dev/null || true + + # Copy node_modules (hoisted, flat layout) + cp -a node_modules $out/lib/acryl-desktop/node_modules + + # Replace workspace packages with built versions + ${installWorkspacePackage "acryl-control" "$out/lib/acryl-desktop/node_modules"} + ${installWorkspacePackage "acryl-harness-runtime" "$out/lib/acryl-desktop/node_modules"} + ${installWorkspacePackage "dsh-community-market" "$out/lib/acryl-desktop/node_modules"} + ${installWorkspacePackage "acryl-development-canvas" "$out/lib/acryl-desktop/node_modules"} + ${installWorkspacePackage "acryl-desktop" "$out/lib/acryl-desktop/node_modules"} + + # Create a shim for the 'electron' npm package that exports + # the nixpkgs electron path. The desktop launcher does + # `import('electron')` to get the binary path; the real npm + # package downloads a platform binary via postinstall (blocked + # by --ignore-scripts), so we replace it with a CJS module + # that returns the nixpkgs electron path. + rm -rf $out/lib/acryl-desktop/node_modules/electron + mkdir -p $out/lib/acryl-desktop/node_modules/electron + cat > $out/lib/acryl-desktop/node_modules/electron/index.js < $out/lib/acryl-desktop/node_modules/electron/package.json <<'ELECTRON_PKG' + { "name": "electron", "version": "43.1.0", "main": "index.js" } + ELECTRON_PKG + + # Wrap the desktop launcher. The launcher (bin.ts) imports + # 'electron' to get the path, then spawns it with main.js. + makeWrapper ${pkgs.nodejs_22}/bin/node $out/bin/acryl-desktop \ + --add-flags "$out/lib/acryl-desktop/lib/bin.js" + + runHook postInstall + ''; + + meta = with pkgs.lib; { + description = "ACRYL local-first plugin-native agent workspace (Desktop)"; + homepage = "https://github.com/levonk/acryl"; + license = licenses.mit; + mainProgram = "acryl-desktop"; + platforms = platforms.unix; + }; + }); }); devShells = forAllSystems ({ pkgs, system }: { From 1f1985b2cb59acc1377db20e091e7b3c931312ca Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Tue, 1 Sep 2026 08:43:13 -0700 Subject: [PATCH 04/32] docs: record acryl-desktop Nix output in DEVELOPMENT-LOG.md Document implementation commit 397f91034cb6a6444c6dccf6f33d06e8b10bf43b which added the Electron desktop app as a separate Nix package output. --- docs/DEVELOPMENT-LOG.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/DEVELOPMENT-LOG.md b/docs/DEVELOPMENT-LOG.md index b600be8e..69c04495 100644 --- a/docs/DEVELOPMENT-LOG.md +++ b/docs/DEVELOPMENT-LOG.md @@ -656,6 +656,40 @@ re-basing the control plane onto the native `@deepseek-ai/dsh-*` / Cordis seams, the plugin path with one real model-facing Tool as the hard gate. Follow-on differentiators (authorization pipeline, room identity, relay/handoff, capability package, agent-agnostic canvas) are intentionally recorded as subsequent ledgers. +## 2026-08-31 - Nix flake: add acryl-desktop (Electron) output + +**Commit:** [`397f91034cb6a6444c6dccf6f33d06e8b10bf43b`](https://github.com/levonk/acryl/commit/397f91034cb6a6444c6dccf6f33d06e8b10bf43b) + +Extended the Nix flake to also build the Electron desktop app as +`packages.${system}.acryl-desktop`, alongside the existing TUI output. + +### Approach + +- Uses nixpkgs `electron` (43.1.0) as the runtime instead of the npm + `electron` package (which downloads a platform binary via postinstall, + blocked by `--ignore-scripts` in the Nix sandbox) +- Creates a CJS shim at `node_modules/electron/index.js` that exports the + nixpkgs electron path, replacing the real npm package. The desktop + launcher (`bin.ts`) does `import('electron')` to get the binary path, + then spawns it with `main.js` — the shim makes this work without the + npm electron binary +- Skips the `generate-*` build scripts (they use `sharp` for image + processing) since `build/` assets are already tracked in git +- Builds the full dependency chain: `acryl-control -> + acryl-harness-runtime -> dsh-community-market -> + acryl-development-canvas -> acryl-desktop` +- Refactors shared derivation attrs into `commonDerivationAttrs` to + avoid duplication between TUI and desktop derivations + +### Usage + +```sh +nix build .#acryl-desktop +nix run .#acryl-desktop -- --help +nix run .#acryl-desktop -- --version +``` + +--- ## 2026-08-31 - Nix flake support for acryl-tui From e40944c686115636c123fd079f727a995ffde154 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 01:25:00 -0700 Subject: [PATCH 05/32] fix(nix): align nixify artifacts with skill rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SHA-pin all GitHub Actions to 40-char commit SHAs (checkout@v5, nix-installer-action@v22, magic-nix-cache-action@v14) instead of mutable @v4/@main refs — prevents supply-chain attacks - Add if: github.event_name != 'pull_request' guard on nix run steps to prevent PR-controlled code from reaching GITHUB_TOKEN/OIDC - Add path filtering to nix.yml (flake.nix, flake.lock, **/*.nix, pnpm-lock.yaml, etc.) so CI only fires when Nix files change - Add nix run .#default -- --help test to CI - Add act to devbox.json packages (required for local CI validation) - Remove invalid nixpkgs.commit field from devbox.json (devbox 0.18 ignores it; was set to channel name not 40-char hash) - Add .devbox/ to .gitignore (devbox generated artifacts) - Add Nix (Flake) and Devbox install sections to README.md, README.en.md, and README.zh.md - Update bilingual-docs hash record in README.i18n.yaml devbox.lock cannot be generated on x86_64-darwin due to devbox 0.18 hardcoding a nixpkgs commit that dropped x86_64-darwin support; generate on aarch64-darwin or Linux. --- .github/workflows/nix.yml | 28 +++++++++++++++++++++++++--- .gitignore | 13 +++++++++++++ README.en.md | 38 ++++++++++++++++++++++++++++++++++++++ README.md | 38 ++++++++++++++++++++++++++++++++++++++ README.zh.md | 2 ++ devbox.json | 6 ++---- 6 files changed, 118 insertions(+), 7 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 8b909061..826255ba 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -3,8 +3,24 @@ name: Nix on: pull_request: branches: [main] + paths: + - flake.nix + - flake.lock + - "**/*.nix" + - .github/workflows/nix.yml + - pnpm-lock.yaml + - pnpm-workspace.yaml + - package.json push: branches: [main] + paths: + - flake.nix + - flake.lock + - "**/*.nix" + - .github/workflows/nix.yml + - pnpm-lock.yaml + - pnpm-workspace.yaml + - package.json workflow_dispatch: permissions: @@ -33,13 +49,13 @@ jobs: runner: macos-13 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 with: submodules: recursive - - uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 - - uses: DeterminateSystems/magic-nix-cache-action@main + - uses: DeterminateSystems/magic-nix-cache-action@908b263ff629f4cc17666315b7fd3ec127c6244d # v14 - name: Check flake run: nix flake check --no-build @@ -50,8 +66,14 @@ jobs: - name: Build acryl-desktop run: nix build .#acryl-desktop --system ${{ matrix.system }} + - name: Test default --help + if: github.event_name != 'pull_request' + run: nix run .#default -- --help + - name: Test TUI --help + if: github.event_name != 'pull_request' run: nix run .#acryl -- --help - name: Test desktop --help + if: github.event_name != 'pull_request' run: nix run .#acryl-desktop -- --help diff --git a/.gitignore b/.gitignore index d01733bf..ea9216ae 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,16 @@ release-artifacts/ .worktrees/ plugins/acryl-ui/.scratch-validate-registry-tests/ + +# Throwaway ACRYL_HOME for reproducing fresh-install/cold-start behavior +# (never-used package-fallback links, first profile creation, etc.) without +# touching a real ~/.acryl or Desktop's own persistent ~/.acryl-dev, both of +# which mask that class of bug once their fallback links are established. +.acryl-home-test/ + +# Nix build outputs +/result +/result-* + +# Devbox generated artifacts (machine-local paths and scripts) +.devbox/ diff --git a/README.en.md b/README.en.md index a6165b69..c9134d13 100644 --- a/README.en.md +++ b/README.en.md @@ -67,6 +67,44 @@ acryl The `acryl` command starts the TUI. It is separate from the Desktop app so terminal users do not need Electron, and desktop users do not receive an unexpected global executable. +### Nix (Flake) + +The project provides a Nix flake that builds the TUI and Desktop from source. Nix with flakes enabled is required. + +```bash +# Run the TUI (default output) +nix run github:levonk/acryl + +# Run the Desktop GUI +nix run github:levonk/acryl#acryl-desktop + +# Install to your Nix profile +nix profile install github:levonk/acryl + +# Specific release (the flake builds from source at every git tag) +nix run github:levonk/acryl/v0.1.19 + +# Enter a development shell +nix develop github:levonk/acryl +``` + +The flake exposes `packages..acryl` (TUI), `packages..acryl-desktop`, and `devShells..default`. + +### Devbox + +For a reproducible development environment without managing Nix tooling manually, use [Devbox](https://www.jetify.com/devbox): + +```bash +# Install Devbox (if not already installed) +curl -fsSL https://get.jetify.dev/devbox | bash + +# Enter the development environment +devbox shell + +# Build the project +corepack pnpm build +``` + ### Local Web surface Start the browser surface explicitly when you want it: diff --git a/README.md b/README.md index 583aa69e..849bca0a 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,44 @@ acryl The `acryl` command starts ACRYL's terminal UI. It is separate from the Desktop app so terminal users do not need Electron, and desktop users do not receive an unexpected global executable. +### Nix (Flake) + +The project provides a Nix flake that builds the TUI and Desktop from source. Nix with flakes enabled is required. + +```bash +# Run the TUI (default output) +nix run github:levonk/acryl + +# Run the Desktop GUI +nix run github:levonk/acryl#acryl-desktop + +# Install to your Nix profile +nix profile install github:levonk/acryl + +# Specific release (the flake builds from source at every git tag) +nix run github:levonk/acryl/v0.1.19 + +# Enter a development shell +nix develop github:levonk/acryl +``` + +The flake exposes `packages..acryl` (TUI), `packages..acryl-desktop`, and `devShells..default`. + +### Devbox + +For a reproducible development environment without managing Nix tooling manually, use [Devbox](https://www.jetify.com/devbox): + +```bash +# Install Devbox (if not already installed) +curl -fsSL https://get.jetify.dev/devbox | bash + +# Enter the development environment +devbox shell + +# Build the project +corepack pnpm build +``` + ### Local Web surface Start the browser surface explicitly when you want it: diff --git a/README.zh.md b/README.zh.md index 70b38434..858d0720 100644 --- a/README.zh.md +++ b/README.zh.md @@ -8,6 +8,8 @@ - 桌面 GUI 下载:[ACRYL v0.1.19 GitHub Release](https://github.com/acryldev/acryl/releases/tag/v0.1.19)([macOS Apple Silicon](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-mac-arm64.dmg)、[macOS Intel](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-mac-x64.dmg)、[Windows x64](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-win-x64.exe)、[Linux x64 DEB](https://github.com/acryldev/acryl/releases/download/v0.1.19/dsh-plugin-desktop_0.1.9_amd64.deb)、[Linux arm64 DEB](https://github.com/acryldev/acryl/releases/download/v0.1.19/dsh-plugin-desktop_0.1.9_arm64.deb))。桌面应用自带所需运行时,但不会把 `acryl` 安装到 shell PATH,也不会在退出后持续运行 Web 服务。 - 终端 CLI(推荐):使用独立安装脚本(无需 Node.js/npm,无安装警告,并自动把 `acryl` 加入 shell PATH):`curl -fsSL https://acryl.dev/install | bash`。它会把预编译的 `acryl` 安装到 `~/.acryl/bin` 并校验校验和,之后在新终端运行 `acryl`。 - npm 终端 CLI(备选):[acryl](https://www.npmjs.com/package/acryl),`npm install -g acryl`,然后运行 `acryl`。npm 11+ 会打印关于原生依赖(`node-pty`、`koffi` 等)的 `install-scripts` 安全提示,属正常现象,包仍会正常安装运行;如需无警告安装,请运行 `npm install -g acryl --allow-scripts=@deepseek-ai/dsh-subprocess-local,@google/genai,koffi,node-pty,protobufjs`。 +- Nix(Flake):`nix run github:levonk/acryl`(TUI)或 `nix run github:levonk/acryl#acryl-desktop`(桌面 GUI)。也可 `nix profile install github:levonk/acryl` 安装到 Nix profile。Flake 从源码构建,支持 tag pinning(如 `github:levonk/acryl/v0.1.19`)。 +- Devbox:`devbox shell` 进入可复现开发环境(需先安装 Devbox:`curl -fsSL https://get.jetify.dev/devbox | bash`)。 - 本地 Web 界面:运行 `acryl web`。它启动本地服务并打印 URL,直到命令停止为止,不是托管的云服务。 - `acryl gui` 预留给未来从 CLI 跳转到桌面应用的功能;目前请直接启动已安装的桌面应用。 - Discord:[加入 ACRYL 社区](https://discord.gg/cY9KXMex69) diff --git a/devbox.json b/devbox.json index adeee859..273ecedd 100644 --- a/devbox.json +++ b/devbox.json @@ -3,7 +3,8 @@ "packages": { "nodejs_22": "latest", "pnpm_11": "latest", - "esbuild": "latest" + "esbuild": "latest", + "act": "latest" }, "shell": { "init_hook": [ @@ -14,8 +15,5 @@ "scripts": { "sync-submodule": "corepack pnpm run upstream:sync" } - }, - "nixpkgs": { - "commit": "nixpkgs-unstable" } } From 656f618c5ed8de59ca54b3d948d20d2b709ef952 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 01:25:22 -0700 Subject: [PATCH 06/32] docs: record nixify skill alignment in DEVELOPMENT-LOG.md --- docs/DEVELOPMENT-LOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/DEVELOPMENT-LOG.md b/docs/DEVELOPMENT-LOG.md index 69c04495..f991831e 100644 --- a/docs/DEVELOPMENT-LOG.md +++ b/docs/DEVELOPMENT-LOG.md @@ -440,6 +440,28 @@ This is a decision-pending milestone: the grilling ticket *Lock the interchangeable harness-engine destination (DSH <-> pi)* (`specs/000-wayfinding/issues/04-lock-harness-engine-swap.md`) must resolve before `specs/028-acryl-harness-engine-swap/` is created with `/speckit-specify`. +## 2026-09-02 - align nixify artifacts with nixify skill rules + +Commit: `85374a5f3bbfe05e20d61d8af57996defd2dfb8f` + +Audited the `feature/nix-flake-support` branch against the nixify skill's +Definition of Done and fixed nine findings. SHA-pinned all GitHub Actions +in `nix.yml` to 40-char commit SHAs (checkout@v5, nix-installer-action@v22, +magic-nix-cache-action@v14) instead of mutable `@v4`/`@main` refs. Added +`if: github.event_name != 'pull_request'` guards on `nix run` steps to +prevent PR-controlled code from reaching `GITHUB_TOKEN`/OIDC. Added path +filtering so Nix CI only fires when `flake.nix`, `flake.lock`, `**/*.nix`, +`pnpm-lock.yaml`, or `package.json` change. Added `nix run .#default -- +--help` test. Added `act` to `devbox.json` for local CI validation. +Removed the invalid `nixpkgs.commit` field from `devbox.json` (devbox 0.18 +ignores it; was set to a channel name, not a 40-char hash). Added +`.devbox/` to `.gitignore`. Added Nix (Flake) and Devbox install sections +to `README.md`, `README.en.md`, and `README.zh.md`; updated the +bilingual-docs hash record in `README.i18n.yaml`. + +`devbox.lock` cannot be generated on x86_64-darwin because devbox 0.18 +hardcodes a nixpkgs commit that dropped x86_64-darwin support; it must be +generated on aarch64-darwin or Linux. ## 2026-09-02 - align exact PNPM pins to the 11.8.0 root release From 99066821044ab36aea85f67d7f414d7d484e9361 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 01:34:29 -0700 Subject: [PATCH 07/32] fix(devbox): pin all packages to nixpkgs-26.05-darwin for x86_64-darwin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit devbox 0.18 ignores the nixpkgs.commit field for regular package-name resolution and hardcodes nixpkgs 26.11, which dropped x86_64-darwin. Work around this by referencing every package as a flake URL pointing at the nixpkgs-26.05-darwin commit (f6107e5) — flake-based references bypass devbox's package index, and nixpkgs.commit controls the shell infrastructure (mkShell). This works on all platforms: x86_64-darwin, aarch64-darwin, and Linux. Generate and commit devbox.lock for reproducible environments. --- devbox.json | 11 +++++++---- devbox.lock | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 devbox.lock diff --git a/devbox.json b/devbox.json index 273ecedd..c7525be7 100644 --- a/devbox.json +++ b/devbox.json @@ -1,10 +1,10 @@ { "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/main/plugins/schemas/devbox.json", "packages": { - "nodejs_22": "latest", - "pnpm_11": "latest", - "esbuild": "latest", - "act": "latest" + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#nodejs_22": "", + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#pnpm_11": "", + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#esbuild": "", + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#act": "" }, "shell": { "init_hook": [ @@ -15,5 +15,8 @@ "scripts": { "sync-submodule": "corepack pnpm run upstream:sync" } + }, + "nixpkgs": { + "commit": "f6107e546a5012172d93e79f1f7950da02ad798f" } } diff --git a/devbox.lock b/devbox.lock new file mode 100644 index 00000000..3802e28c --- /dev/null +++ b/devbox.lock @@ -0,0 +1,25 @@ +{ + "lockfile_version": "1", + "packages": { + "github:NixOS/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f": { + "last_modified": "1970-01-01T00:00:00Z", + "resolved": "github:NixOS/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f" + }, + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#act": { + "last_modified": "1970-01-01T00:00:00Z", + "resolved": "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#act" + }, + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#esbuild": { + "last_modified": "1970-01-01T00:00:00Z", + "resolved": "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#esbuild" + }, + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#nodejs_22": { + "last_modified": "1970-01-01T00:00:00Z", + "resolved": "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#nodejs_22" + }, + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#pnpm_11": { + "last_modified": "1970-01-01T00:00:00Z", + "resolved": "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#pnpm_11" + } + } +} From 4c66fcf9757b506730ca1b66040437527b170781 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 01:42:14 -0700 Subject: [PATCH 08/32] fix(devbox): isolate x86_64-darwin workaround from normal platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use per-package platform scoping: clean package names (nodejs_22, pnpm_11, esbuild, act) for normal platforms (Linux, aarch64-darwin), and flake URL references to nixpkgs-26.05-darwin only for x86_64-darwin. The nixpkgs.commit field is set to the 26.05-darwin pin for the shell infrastructure (mkShell), which devbox 0.18 honors when all active packages on a platform are flake-based. On normal platforms, packages resolve from nixpkgs-unstable via devbox's index — the same behavior as before. On x86_64-darwin, the flake URL references bypass devbox's hardcoded nixpkgs 26.11 (which dropped x86_64-darwin) and pull from 26.05-darwin instead. The lock file records both resolution paths. Linux/aarch64-darwin entries will be populated when a user on that platform runs devbox install. --- devbox.json | 32 ++++++++++++++++++++++++++++---- devbox.lock | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/devbox.json b/devbox.json index c7525be7..66b1e449 100644 --- a/devbox.json +++ b/devbox.json @@ -1,10 +1,34 @@ { "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/main/plugins/schemas/devbox.json", "packages": { - "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#nodejs_22": "", - "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#pnpm_11": "", - "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#esbuild": "", - "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#act": "" + "nodejs_22": { + "version": "latest", + "excluded_platforms": ["x86_64-darwin"] + }, + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#nodejs_22": { + "platforms": ["x86_64-darwin"] + }, + "pnpm_11": { + "version": "latest", + "excluded_platforms": ["x86_64-darwin"] + }, + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#pnpm_11": { + "platforms": ["x86_64-darwin"] + }, + "esbuild": { + "version": "latest", + "excluded_platforms": ["x86_64-darwin"] + }, + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#esbuild": { + "platforms": ["x86_64-darwin"] + }, + "act": { + "version": "latest", + "excluded_platforms": ["x86_64-darwin"] + }, + "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#act": { + "platforms": ["x86_64-darwin"] + } }, "shell": { "init_hook": [ diff --git a/devbox.lock b/devbox.lock index 3802e28c..57a7e1db 100644 --- a/devbox.lock +++ b/devbox.lock @@ -20,6 +20,45 @@ "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#pnpm_11": { "last_modified": "1970-01-01T00:00:00Z", "resolved": "github:nixos/nixpkgs/f6107e546a5012172d93e79f1f7950da02ad798f#pnpm_11" + }, + "nodejs_22@latest": { + "last_modified": "2026-08-27T07:16:00Z", + "plugin_version": "0.0.4", + "resolved": "github:NixOS/nixpkgs/c27cdad491a991b11ed731760aa2ef8db0cb0410#nodejs_22", + "source": "devbox-search", + "version": "22.23.2", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/6hbiyfa4gzcjr6bnr440nnwznlsaldlc-nodejs-22.23.2", + "default": true + } + ], + "store_path": "/nix/store/6hbiyfa4gzcjr6bnr440nnwznlsaldlc-nodejs-22.23.2" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/v6xnbaql2wc91k13xcfhr60r52ich6bw-nodejs-22.23.2", + "default": true + } + ], + "store_path": "/nix/store/v6xnbaql2wc91k13xcfhr60r52ich6bw-nodejs-22.23.2" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/gf597zf0ysgbngwb92baxgxjd02px6jh-nodejs-22.23.2", + "default": true + } + ], + "store_path": "/nix/store/gf597zf0ysgbngwb92baxgxjd02px6jh-nodejs-22.23.2" + } + } } } } From 672eb4b650b9aefe4b56a63af431412b86eb79ee Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 01:42:34 -0700 Subject: [PATCH 09/32] docs: update DEVELOPMENT-LOG with per-package scoping approach --- docs/DEVELOPMENT-LOG.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/DEVELOPMENT-LOG.md b/docs/DEVELOPMENT-LOG.md index f991831e..d0c6a39c 100644 --- a/docs/DEVELOPMENT-LOG.md +++ b/docs/DEVELOPMENT-LOG.md @@ -442,7 +442,9 @@ interchangeable harness-engine destination (DSH <-> pi)* before `specs/028-acryl-harness-engine-swap/` is created with `/speckit-specify`. ## 2026-09-02 - align nixify artifacts with nixify skill rules -Commit: `85374a5f3bbfe05e20d61d8af57996defd2dfb8f` +Commits: `85374a5f3bbfe05e20d61d8af57996defd2dfb8f`, +`a2fd96b` (devbox x86_64-darwin first attempt), +`b79e414` (devbox x86_64-darwin per-package scoping) Audited the `feature/nix-flake-support` branch against the nixify skill's Definition of Done and fixed nine findings. SHA-pinned all GitHub Actions @@ -453,15 +455,21 @@ prevent PR-controlled code from reaching `GITHUB_TOKEN`/OIDC. Added path filtering so Nix CI only fires when `flake.nix`, `flake.lock`, `**/*.nix`, `pnpm-lock.yaml`, or `package.json` change. Added `nix run .#default -- --help` test. Added `act` to `devbox.json` for local CI validation. -Removed the invalid `nixpkgs.commit` field from `devbox.json` (devbox 0.18 -ignores it; was set to a channel name, not a 40-char hash). Added -`.devbox/` to `.gitignore`. Added Nix (Flake) and Devbox install sections -to `README.md`, `README.en.md`, and `README.zh.md`; updated the +Added `.devbox/` to `.gitignore`. Added Nix (Flake) and Devbox install +sections to `README.md`, `README.en.md`, and `README.zh.md`; updated the bilingual-docs hash record in `README.i18n.yaml`. -`devbox.lock` cannot be generated on x86_64-darwin because devbox 0.18 -hardcodes a nixpkgs commit that dropped x86_64-darwin support; it must be -generated on aarch64-darwin or Linux. +The `devbox.lock` blocker was resolved with per-package platform scoping: +clean package names (`nodejs_22`, `pnpm_11`, `esbuild`, `act`) for normal +platforms (Linux, aarch64-darwin), and flake URL references to +nixpkgs-26.05-darwin only for x86_64-darwin. The `nixpkgs.commit` field +is set to the 26.05-darwin pin for the shell infrastructure (`mkShell`). +On normal platforms, packages resolve from nixpkgs-unstable via devbox's +index — unchanged from before. On x86_64-darwin, the flake URL references +bypass devbox 0.18's hardcoded nixpkgs 26.11 (which dropped x86_64-darwin) +and pull from 26.05-darwin instead. `devbox.lock` is committed with both +resolution paths; Linux/aarch64-darwin entries will be populated when a +user on that platform runs `devbox install`. ## 2026-09-02 - align exact PNPM pins to the 11.8.0 root release From 6c4ae9dc851547f3ac5f8b83228a968d268e532a Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 01:50:38 -0700 Subject: [PATCH 10/32] fix(nix): use upstream acryldev/acryl in flake and README references Replace all github:levonk/acryl references with github:acryldev/acryl in flake.nix (homepage meta), README.md, README.en.md, README.zh.md, and DEVELOPMENT-LOG.md commit links. Update bilingual-docs hash record. --- README.en.md | 10 +++++----- README.md | 10 +++++----- README.zh.md | 2 +- docs/DEVELOPMENT-LOG.md | 4 ++-- flake.nix | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.en.md b/README.en.md index c9134d13..340aa891 100644 --- a/README.en.md +++ b/README.en.md @@ -73,19 +73,19 @@ The project provides a Nix flake that builds the TUI and Desktop from source. Ni ```bash # Run the TUI (default output) -nix run github:levonk/acryl +nix run github:acryldev/acryl # Run the Desktop GUI -nix run github:levonk/acryl#acryl-desktop +nix run github:acryldev/acryl#acryl-desktop # Install to your Nix profile -nix profile install github:levonk/acryl +nix profile install github:acryldev/acryl # Specific release (the flake builds from source at every git tag) -nix run github:levonk/acryl/v0.1.19 +nix run github:acryldev/acryl/v0.1.19 # Enter a development shell -nix develop github:levonk/acryl +nix develop github:acryldev/acryl ``` The flake exposes `packages..acryl` (TUI), `packages..acryl-desktop`, and `devShells..default`. diff --git a/README.md b/README.md index 849bca0a..775bc1bb 100644 --- a/README.md +++ b/README.md @@ -81,19 +81,19 @@ The project provides a Nix flake that builds the TUI and Desktop from source. Ni ```bash # Run the TUI (default output) -nix run github:levonk/acryl +nix run github:acryldev/acryl # Run the Desktop GUI -nix run github:levonk/acryl#acryl-desktop +nix run github:acryldev/acryl#acryl-desktop # Install to your Nix profile -nix profile install github:levonk/acryl +nix profile install github:acryldev/acryl # Specific release (the flake builds from source at every git tag) -nix run github:levonk/acryl/v0.1.19 +nix run github:acryldev/acryl/v0.1.19 # Enter a development shell -nix develop github:levonk/acryl +nix develop github:acryldev/acryl ``` The flake exposes `packages..acryl` (TUI), `packages..acryl-desktop`, and `devShells..default`. diff --git a/README.zh.md b/README.zh.md index 858d0720..9f251f15 100644 --- a/README.zh.md +++ b/README.zh.md @@ -8,7 +8,7 @@ - 桌面 GUI 下载:[ACRYL v0.1.19 GitHub Release](https://github.com/acryldev/acryl/releases/tag/v0.1.19)([macOS Apple Silicon](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-mac-arm64.dmg)、[macOS Intel](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-mac-x64.dmg)、[Windows x64](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-win-x64.exe)、[Linux x64 DEB](https://github.com/acryldev/acryl/releases/download/v0.1.19/dsh-plugin-desktop_0.1.9_amd64.deb)、[Linux arm64 DEB](https://github.com/acryldev/acryl/releases/download/v0.1.19/dsh-plugin-desktop_0.1.9_arm64.deb))。桌面应用自带所需运行时,但不会把 `acryl` 安装到 shell PATH,也不会在退出后持续运行 Web 服务。 - 终端 CLI(推荐):使用独立安装脚本(无需 Node.js/npm,无安装警告,并自动把 `acryl` 加入 shell PATH):`curl -fsSL https://acryl.dev/install | bash`。它会把预编译的 `acryl` 安装到 `~/.acryl/bin` 并校验校验和,之后在新终端运行 `acryl`。 - npm 终端 CLI(备选):[acryl](https://www.npmjs.com/package/acryl),`npm install -g acryl`,然后运行 `acryl`。npm 11+ 会打印关于原生依赖(`node-pty`、`koffi` 等)的 `install-scripts` 安全提示,属正常现象,包仍会正常安装运行;如需无警告安装,请运行 `npm install -g acryl --allow-scripts=@deepseek-ai/dsh-subprocess-local,@google/genai,koffi,node-pty,protobufjs`。 -- Nix(Flake):`nix run github:levonk/acryl`(TUI)或 `nix run github:levonk/acryl#acryl-desktop`(桌面 GUI)。也可 `nix profile install github:levonk/acryl` 安装到 Nix profile。Flake 从源码构建,支持 tag pinning(如 `github:levonk/acryl/v0.1.19`)。 +- Nix(Flake):`nix run github:acryldev/acryl`(TUI)或 `nix run github:acryldev/acryl#acryl-desktop`(桌面 GUI)。也可 `nix profile install github:acryldev/acryl` 安装到 Nix profile。Flake 从源码构建,支持 tag pinning(如 `github:acryldev/acryl/v0.1.19`)。 - Devbox:`devbox shell` 进入可复现开发环境(需先安装 Devbox:`curl -fsSL https://get.jetify.dev/devbox | bash`)。 - 本地 Web 界面:运行 `acryl web`。它启动本地服务并打印 URL,直到命令停止为止,不是托管的云服务。 - `acryl gui` 预留给未来从 CLI 跳转到桌面应用的功能;目前请直接启动已安装的桌面应用。 diff --git a/docs/DEVELOPMENT-LOG.md b/docs/DEVELOPMENT-LOG.md index d0c6a39c..3d186ddd 100644 --- a/docs/DEVELOPMENT-LOG.md +++ b/docs/DEVELOPMENT-LOG.md @@ -688,7 +688,7 @@ the plugin path with one real model-facing Tool as the hard gate. Follow-on diff canvas) are intentionally recorded as subsequent ledgers. ## 2026-08-31 - Nix flake: add acryl-desktop (Electron) output -**Commit:** [`397f91034cb6a6444c6dccf6f33d06e8b10bf43b`](https://github.com/levonk/acryl/commit/397f91034cb6a6444c6dccf6f33d06e8b10bf43b) +**Commit:** [`397f91034cb6a6444c6dccf6f33d06e8b10bf43b`](https://github.com/acryldev/acryl/commit/397f91034cb6a6444c6dccf6f33d06e8b10bf43b) Extended the Nix flake to also build the Electron desktop app as `packages.${system}.acryl-desktop`, alongside the existing TUI output. @@ -723,7 +723,7 @@ nix run .#acryl-desktop -- --version ## 2026-08-31 - Nix flake support for acryl-tui -**Commit:** [`d6d2e464db46fbe61c36e84136880d8c55ac5a0d`](https://github.com/levonk/acryl/commit/d6d2e464db46fbe61c36e84136880d8c55ac5a0d) +**Commit:** [`d6d2e464db46fbe61c36e84136880d8c55ac5a0d`](https://github.com/acryldev/acryl/commit/d6d2e464db46fbe61c36e84136880d8c55ac5a0d) Added Nix flake support targeting the `acryl-tui` terminal client. The flake builds the TUI and its workspace dependencies (`acryl-control`, diff --git a/flake.nix b/flake.nix index 68f9344f..2257b97f 100644 --- a/flake.nix +++ b/flake.nix @@ -180,7 +180,7 @@ meta = with pkgs.lib; { description = "ACRYL local-first plugin-native agent workspace (TUI)"; - homepage = "https://github.com/levonk/acryl"; + homepage = "https://github.com/acryldev/acryl"; license = licenses.mit; mainProgram = "acryl"; platforms = platforms.unix; @@ -264,7 +264,7 @@ meta = with pkgs.lib; { description = "ACRYL local-first plugin-native agent workspace (Desktop)"; - homepage = "https://github.com/levonk/acryl"; + homepage = "https://github.com/acryldev/acryl"; license = licenses.mit; mainProgram = "acryl-desktop"; platforms = platforms.unix; From 240fc4162989af9260b7553e7ba44fcc91c159ee Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 01:59:39 -0700 Subject: [PATCH 11/32] feat(nix): add #prebuilt output for prebuilt CLI release tarballs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add packages..prebuilt — fetches the prebuilt CLI tarball from GitHub releases (v0.1.19). Each tarball bundles its own Node runtime and native addons (node-pty, koffi, sharp), so no from-source build is needed for the prebuilt path. Uses autoPatchelfHook on Linux for glibc linking. The default output remains #acryl (from-source build), following Nix convention. #prebuilt is an optional fast path for users who want the exact release binary. Add CI steps to build and test #prebuilt on all 4 platforms. Update READMEs to document the #prebuilt output. --- .github/workflows/nix.yml | 7 +++++ README.en.md | 2 +- README.md | 2 +- README.zh.md | 2 +- flake.nix | 64 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 826255ba..3f06431f 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -66,6 +66,9 @@ jobs: - name: Build acryl-desktop run: nix build .#acryl-desktop --system ${{ matrix.system }} + - name: Build prebuilt + run: nix build .#prebuilt --system ${{ matrix.system }} + - name: Test default --help if: github.event_name != 'pull_request' run: nix run .#default -- --help @@ -74,6 +77,10 @@ jobs: if: github.event_name != 'pull_request' run: nix run .#acryl -- --help + - name: Test prebuilt --help + if: github.event_name != 'pull_request' + run: nix run .#prebuilt -- --help + - name: Test desktop --help if: github.event_name != 'pull_request' run: nix run .#acryl-desktop -- --help diff --git a/README.en.md b/README.en.md index 340aa891..03b32163 100644 --- a/README.en.md +++ b/README.en.md @@ -88,7 +88,7 @@ nix run github:acryldev/acryl/v0.1.19 nix develop github:acryldev/acryl ``` -The flake exposes `packages..acryl` (TUI), `packages..acryl-desktop`, and `devShells..default`. +The flake exposes `packages..acryl` (TUI, from source, also `#default`), `packages..prebuilt` (prebuilt release binary with bundled Node runtime), `packages..acryl-desktop`, and `devShells..default`. ### Devbox diff --git a/README.md b/README.md index 775bc1bb..c477826b 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ nix run github:acryldev/acryl/v0.1.19 nix develop github:acryldev/acryl ``` -The flake exposes `packages..acryl` (TUI), `packages..acryl-desktop`, and `devShells..default`. +The flake exposes `packages..acryl` (TUI, from source, also `#default`), `packages..prebuilt` (prebuilt release binary with bundled Node runtime), `packages..acryl-desktop`, and `devShells..default`. ### Devbox diff --git a/README.zh.md b/README.zh.md index 9f251f15..595eb00d 100644 --- a/README.zh.md +++ b/README.zh.md @@ -8,7 +8,7 @@ - 桌面 GUI 下载:[ACRYL v0.1.19 GitHub Release](https://github.com/acryldev/acryl/releases/tag/v0.1.19)([macOS Apple Silicon](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-mac-arm64.dmg)、[macOS Intel](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-mac-x64.dmg)、[Windows x64](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-win-x64.exe)、[Linux x64 DEB](https://github.com/acryldev/acryl/releases/download/v0.1.19/dsh-plugin-desktop_0.1.9_amd64.deb)、[Linux arm64 DEB](https://github.com/acryldev/acryl/releases/download/v0.1.19/dsh-plugin-desktop_0.1.9_arm64.deb))。桌面应用自带所需运行时,但不会把 `acryl` 安装到 shell PATH,也不会在退出后持续运行 Web 服务。 - 终端 CLI(推荐):使用独立安装脚本(无需 Node.js/npm,无安装警告,并自动把 `acryl` 加入 shell PATH):`curl -fsSL https://acryl.dev/install | bash`。它会把预编译的 `acryl` 安装到 `~/.acryl/bin` 并校验校验和,之后在新终端运行 `acryl`。 - npm 终端 CLI(备选):[acryl](https://www.npmjs.com/package/acryl),`npm install -g acryl`,然后运行 `acryl`。npm 11+ 会打印关于原生依赖(`node-pty`、`koffi` 等)的 `install-scripts` 安全提示,属正常现象,包仍会正常安装运行;如需无警告安装,请运行 `npm install -g acryl --allow-scripts=@deepseek-ai/dsh-subprocess-local,@google/genai,koffi,node-pty,protobufjs`。 -- Nix(Flake):`nix run github:acryldev/acryl`(TUI)或 `nix run github:acryldev/acryl#acryl-desktop`(桌面 GUI)。也可 `nix profile install github:acryldev/acryl` 安装到 Nix profile。Flake 从源码构建,支持 tag pinning(如 `github:acryldev/acryl/v0.1.19`)。 +- Nix(Flake):`nix run github:acryldev/acryl`(TUI,从源码构建,默认输出)或 `nix run github:acryldev/acryl#prebuilt`(预编译二进制,自带 Node 运行时)或 `nix run github:acryldev/acryl#acryl-desktop`(桌面 GUI)。也可 `nix profile install github:acryldev/acryl` 安装到 Nix profile。Flake 从源码构建,支持 tag pinning(如 `github:acryldev/acryl/v0.1.19`)。 - Devbox:`devbox shell` 进入可复现开发环境(需先安装 Devbox:`curl -fsSL https://get.jetify.dev/devbox | bash`)。 - 本地 Web 界面:运行 `acryl web`。它启动本地服务并打印 URL,直到命令停止为止,不是托管的云服务。 - `acryl gui` 预留给未来从 CLI 跳转到桌面应用的功能;目前请直接启动已安装的桌面应用。 diff --git a/flake.nix b/flake.nix index 2257b97f..b099ea2f 100644 --- a/flake.nix +++ b/flake.nix @@ -54,6 +54,28 @@ # Exclude Nix build outputs !pkgs'.lib.hasPrefix "/result" rel ); + + # Prebuilt CLI release tarballs (v0.1.19). Each tarball bundles its + # own Node runtime and native addons (node-pty, koffi, sharp). + releaseVersion = "0.1.19"; + prebuiltAssets = { + "x86_64-linux" = { + url = "https://github.com/acryldev/acryl/releases/download/v${releaseVersion}/acryl-cli-linux-x64.tar.gz"; + hash = "sha256-cTlDn36FUJ69bLLKSqfXYBCcU2AMVL0GuTJ+y32833s="; + }; + "aarch64-linux" = { + url = "https://github.com/acryldev/acryl/releases/download/v${releaseVersion}/acryl-cli-linux-arm64.tar.gz"; + hash = "sha256-/XNe8kTxF5/AgV1xeHg7kKeT9humvoH0MKcp81+/uLE="; + }; + "x86_64-darwin" = { + url = "https://github.com/acryldev/acryl/releases/download/v${releaseVersion}/acryl-cli-darwin-x64.tar.gz"; + hash = "sha256-8pvnuU0Z5+GOGAHKS+k6ucApZEBq55cnP0XK9H0t/hQ="; + }; + "aarch64-darwin" = { + url = "https://github.com/acryldev/acryl/releases/download/v${releaseVersion}/acryl-cli-darwin-arm64.tar.gz"; + hash = "sha256-8W0Df1ZyLSEr+aYDmxGIWqEv43mZwRIJYgoDyWlfTqA="; + }; + }; in { packages = forAllSystems ({ pkgs, system }: @@ -132,6 +154,48 @@ { default = self.packages.${system}.acryl; + # Prebuilt CLI tarball — bundles its own Node runtime and native + # addons (node-pty, koffi, sharp). Fast path for users who want + # the exact release binary without a from-source build. + prebuilt = pkgs.stdenv.mkDerivation { + pname = "acryl-prebuilt"; + inherit (commonDerivationAttrs) version; + + src = pkgs.fetchurl { + url = prebuiltAssets.${system}.url; + hash = prebuiltAssets.${system}.hash; + }; + + sourceRoot = "."; + + nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.autoPatchelfHook ]; + buildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.stdenv.cc.cc.lib ]; + + dontConfigure = true; + dontBuild = true; + + installPhase = '' + runHook preInstall + mkdir -p $out + cp -r acryl-cli-*/bin $out/bin + cp -r acryl-cli-*/lib $out/lib + cp -r acryl-cli-*/node_modules $out/node_modules + cp acryl-cli-*/package.json $out/ + chmod +x $out/bin/acryl + runHook postInstall + ''; + + meta = with pkgs.lib; { + description = "ACRYL TUI (prebuilt release binary)"; + homepage = "https://github.com/acryldev/acryl"; + downloadPage = "https://github.com/acryldev/acryl/releases"; + license = licenses.mit; + mainProgram = "acryl"; + platforms = builtins.attrNames prebuiltAssets; + sourceProvenance = [ sourceTypes.binaryNativeCode ]; + }; + }; + acryl = pkgs.stdenv.mkDerivation (finalAttrs: { pname = "acryl"; inherit (commonDerivationAttrs) version src pnpmDeps pnpm nativeBuildInputs preConfigure dontPnpmBuild dontStrip dontFixup; From ed071fed9701110e2e98f52d2b02c4dd0d62dd85 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 01:59:55 -0700 Subject: [PATCH 12/32] docs: record #prebuilt output in DEVELOPMENT-LOG.md --- docs/DEVELOPMENT-LOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/DEVELOPMENT-LOG.md b/docs/DEVELOPMENT-LOG.md index 3d186ddd..1e37758e 100644 --- a/docs/DEVELOPMENT-LOG.md +++ b/docs/DEVELOPMENT-LOG.md @@ -440,6 +440,19 @@ This is a decision-pending milestone: the grilling ticket *Lock the interchangeable harness-engine destination (DSH <-> pi)* (`specs/000-wayfinding/issues/04-lock-harness-engine-swap.md`) must resolve before `specs/028-acryl-harness-engine-swap/` is created with `/speckit-specify`. +## 2026-09-02 - add #prebuilt output for prebuilt CLI release tarballs + +Commit: `b90ced5cefce1cc439092158a7a0291b5b324165` + +Added `packages..prebuilt` to the Nix flake — fetches the prebuilt +CLI tarball from GitHub releases (v0.1.19) with per-platform SRI hashes. +Each tarball bundles its own Node runtime and native addons (node-pty, +koffi, sharp), so the prebuilt path needs no from-source build. Uses +`autoPatchelfHook` on Linux for glibc linking. The default output remains +`#acryl` (from-source build), following Nix convention; `#prebuilt` is an +optional fast path. CI now builds and tests `#prebuilt` on all 4 platforms. +READMEs updated to document the `#prebuilt` output. + ## 2026-09-02 - align nixify artifacts with nixify skill rules Commits: `85374a5f3bbfe05e20d61d8af57996defd2dfb8f`, From f5d1763ecd7c24479f647ec17a0b5fcc85225d2d Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 13:27:08 -0700 Subject: [PATCH 13/32] fix(nix): rebase on upstream/main, fix FlakeHub auth, timeout, and FOD hash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four fixes for the CI failures on PR #5: 1. Rebase onto upstream/main (was 11 commits behind — caused the "Typecheck, test, and build" failure on a test already fixed on main) 2. Add use-flakehub: false to magic-nix-cache-action (the action defaults to use-flakehub: true, which attempts FlakeHub OIDC auth and breaks CI for orgs without a FlakeHub account — root cause of the "Unable to authenticate to FlakeHub" error) 3. Add timeout-minutes: 20 to the build job (was missing — GitHub's default max is 6h, caused the aarch64-darwin job to hang) 4. Update fetchPnpmDeps hash (stale after rebase picked up new upstream pnpm-lock.yaml changes) --- .github/workflows/nix.yml | 3 +++ flake.nix | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 3f06431f..068f211a 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -34,6 +34,7 @@ jobs: build: name: Build (${{ matrix.system }}) runs-on: ${{ matrix.runner }} + timeout-minutes: 20 strategy: fail-fast: false matrix: @@ -56,6 +57,8 @@ jobs: - uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 - uses: DeterminateSystems/magic-nix-cache-action@908b263ff629f4cc17666315b7fd3ec127c6244d # v14 + with: + use-flakehub: false - name: Check flake run: nix flake check --no-build diff --git a/flake.nix b/flake.nix index b099ea2f..2c1d8081 100644 --- a/flake.nix +++ b/flake.nix @@ -93,7 +93,7 @@ pname = "acryl"; inherit version src pnpm; fetcherVersion = 4; - hash = "sha256-eSJETc4rpA3jrGHOqVcatiLxlhOeg5cpX9wOL2r+3eA="; + hash = "sha256-z/LRm/EyIZxXgXVNMWTe+7DdfnwyzYBpoWjw8yzZrbI="; }; # Shared flags for both TUI and desktop derivations. From 1ffae9a16b1d16aac22c5bc7d5aac177b88fdb07 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 15:38:02 -0700 Subject: [PATCH 14/32] fix(nix): replace isolated linker with hoisted, not just insert The preConfigure hook checked `if ! grep -q "nodeLinker"` and only inserted `nodeLinker: hoisted` when the key was absent. But pnpm-workspace.yaml already had `nodeLinker: isolated`, so the sed never ran. The isolated linker creates a .pnpm/ virtual store with symlinks that break when copied to the Nix store, leaving node_modules/ with only 3 entries (the workspace packages) and no registry dependencies like @deepseek-ai/dsh-llm. Replace the value when the key exists, instead of only inserting when missing. After this fix, node_modules/ has 648 packages and all four outputs (default, acryl, prebuilt, acryl-desktop) pass smoke tests. --- flake.nix | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 2c1d8081..eff998e7 100644 --- a/flake.nix +++ b/flake.nix @@ -115,9 +115,15 @@ # Force hoisted node-linker so all dependencies are flattened # into a single node_modules/ directory (like npm's layout). # In pnpm 11, this setting moved from .npmrc to pnpm-workspace.yaml - # as "nodeLinker". The project's .npmrc still has the old key. + # as "nodeLinker". The project's pnpm-workspace.yaml has + # nodeLinker: isolated (symlink-based .pnpm/ virtual store) which + # doesn't survive the Nix store copy — symlinks break. Replace it + # with hoisted so all packages are real directories. preConfigure = '' - if ! grep -q "nodeLinker" pnpm-workspace.yaml; then + if grep -q "nodeLinker" pnpm-workspace.yaml; then + sed -i.bak 's/nodeLinker:.*/nodeLinker: hoisted/' pnpm-workspace.yaml + rm -f pnpm-workspace.yaml.bak + else sed -i.bak '1i nodeLinker: hoisted' pnpm-workspace.yaml rm -f pnpm-workspace.yaml.bak fi From 9d3dddc976f8738cbde33547c621278b2ba067b8 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 16:09:32 -0700 Subject: [PATCH 15/32] fix(nix): add musl to prebuilt buildInputs for koffi musl binary The prebuilt release tarball bundles both glibc-linked and musl-linked native koffi addons (musl_x64/koffi.node alongside linux_x64/koffi.node). autoPatchelfHook was only finding glibc (stdenv.cc.cc.lib), so it failed with "could not satisfy dependency libc.musl-x86_64.so.1" on Linux. Add pkgs.musl to buildInputs so autoPatchelf can patch both variants. --- flake.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index eff998e7..d7c23aee 100644 --- a/flake.nix +++ b/flake.nix @@ -174,8 +174,15 @@ sourceRoot = "."; + # The prebuilt tarball bundles both glibc-linked and musl-linked + # native addons (koffi ships musl_x64/koffi.node alongside + # linux_x64/koffi.node). autoPatchelf needs both glibc and musl + # available to satisfy all shared library dependencies. nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.autoPatchelfHook ]; - buildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.stdenv.cc.cc.lib ]; + buildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ + pkgs.stdenv.cc.cc.lib + pkgs.musl + ]; dontConfigure = true; dontBuild = true; From b6a2a76a0b32f898143ab0d78f7d009879f5eca1 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Wed, 2 Sep 2026 17:14:40 -0700 Subject: [PATCH 16/32] ci(nix): disable magic-nix-cache on darwin runners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The magic-nix-cache v14 static binary for arm64-darwin fails on the macos-14 runner with: dyld: Symbol not found: __ZNSt13exception_ptr31__from_native_exception_pointerEPv Expected in: /usr/lib/libc++.1.dylib This is a DeterminateSystems binary incompatibility — the binary was built against a newer libc++ than the runner ships. The build itself never starts; the job hangs for 20 minutes then gets cancelled. Make the cache action Linux-only. Darwin builds work without it, just slower (no cache acceleration). The flake and builds are unaffected. --- .github/workflows/nix.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 068f211a..baefec89 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -56,7 +56,13 @@ jobs: - uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 + # magic-nix-cache is Linux-only: the v14 static binary on arm64-darwin + # fails with `dyld: Symbol not found: __ZNSt13exception_ptr...` because + # it was built against a newer libc++ than the macos-14 runner ships. + # See DeterminateSystems/nix-installer#1684 and llvm/llvm-project#86077. + # Darwin builds work without the cache, just slower. - uses: DeterminateSystems/magic-nix-cache-action@908b263ff629f4cc17666315b7fd3ec127c6244d # v14 + if: runner.os == 'Linux' with: use-flakehub: false From aecb5af7a9496f6ca45d00145bc99953fb8288ad Mon Sep 17 00:00:00 2001 From: Alex Musichen Date: Fri, 11 Sep 2026 19:06:14 +0200 Subject: [PATCH 17/32] docs(dev-log): re-point Nix flake entries at the rebased commit hashes --- docs/DEVELOPMENT-LOG.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/DEVELOPMENT-LOG.md b/docs/DEVELOPMENT-LOG.md index 1e37758e..ee8f1245 100644 --- a/docs/DEVELOPMENT-LOG.md +++ b/docs/DEVELOPMENT-LOG.md @@ -442,7 +442,7 @@ interchangeable harness-engine destination (DSH <-> pi)* before `specs/028-acryl-harness-engine-swap/` is created with `/speckit-specify`. ## 2026-09-02 - add #prebuilt output for prebuilt CLI release tarballs -Commit: `b90ced5cefce1cc439092158a7a0291b5b324165` +Commit: `c01bbfc73bfc8c1ca7edfd5ec4a76aee6c7d6a51` Added `packages..prebuilt` to the Nix flake — fetches the prebuilt CLI tarball from GitHub releases (v0.1.19) with per-platform SRI hashes. @@ -455,9 +455,9 @@ READMEs updated to document the `#prebuilt` output. ## 2026-09-02 - align nixify artifacts with nixify skill rules -Commits: `85374a5f3bbfe05e20d61d8af57996defd2dfb8f`, -`a2fd96b` (devbox x86_64-darwin first attempt), -`b79e414` (devbox x86_64-darwin per-package scoping) +Commits: `a3ebe71686e01efa923f8b0df44068527752e401`, +`122f207` (devbox x86_64-darwin first attempt), +`2d895f6` (devbox x86_64-darwin per-package scoping) Audited the `feature/nix-flake-support` branch against the nixify skill's Definition of Done and fixed nine findings. SHA-pinned all GitHub Actions @@ -701,7 +701,7 @@ the plugin path with one real model-facing Tool as the hard gate. Follow-on diff canvas) are intentionally recorded as subsequent ledgers. ## 2026-08-31 - Nix flake: add acryl-desktop (Electron) output -**Commit:** [`397f91034cb6a6444c6dccf6f33d06e8b10bf43b`](https://github.com/acryldev/acryl/commit/397f91034cb6a6444c6dccf6f33d06e8b10bf43b) +**Commit:** [`47840639adafd11c4531f096bec5fba44ce49c99`](https://github.com/acryldev/acryl/commit/47840639adafd11c4531f096bec5fba44ce49c99) Extended the Nix flake to also build the Electron desktop app as `packages.${system}.acryl-desktop`, alongside the existing TUI output. @@ -736,7 +736,7 @@ nix run .#acryl-desktop -- --version ## 2026-08-31 - Nix flake support for acryl-tui -**Commit:** [`d6d2e464db46fbe61c36e84136880d8c55ac5a0d`](https://github.com/acryldev/acryl/commit/d6d2e464db46fbe61c36e84136880d8c55ac5a0d) +**Commit:** [`f8f7efcd8a56f0942fee49a36ebacec493655210`](https://github.com/acryldev/acryl/commit/f8f7efcd8a56f0942fee49a36ebacec493655210) Added Nix flake support targeting the `acryl-tui` terminal client. The flake builds the TUI and its workspace dependencies (`acryl-control`, From a5be01700254bb558b7366793768d8774dbe0ca5 Mon Sep 17 00:00:00 2001 From: Alex Musichen Date: Fri, 11 Sep 2026 19:06:14 +0200 Subject: [PATCH 18/32] ci(nix): drop x86_64-darwin job - Determinate Nix cannot install on Intel macOS runners The macos-13 runner can no longer bootstrap Determinate Nix (DeterminateSystems/nix-src#224), so the x86_64-darwin CI job fails before building anything. Keep the derivation in flake.nix for local Intel builders; restore the job via a Rosetta cross-build from macos-14 when feasible. --- .github/workflows/nix.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index baefec89..80a1e339 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -45,9 +45,11 @@ jobs: runner: ubuntu-24.04-arm - system: aarch64-darwin runner: macos-14 - # x86_64-darwin uses nixpkgs-26.05-darwin legacy pin - - system: x86_64-darwin - runner: macos-13 + # x86_64-darwin (nixpkgs-26.05-darwin legacy pin) has no CI job: + # the Determinate Nix installer no longer supports Intel macOS on + # GitHub-hosted runners (DeterminateSystems/nix-src#224). The + # derivation stays in flake.nix for local Intel builders; restore + # the job via a Rosetta cross-build from macos-14 when feasible. steps: - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 From d42c91d4bb9422ab47d695f727643043c7d04a45 Mon Sep 17 00:00:00 2001 From: Alex Musichen Date: Fri, 11 Sep 2026 19:09:42 +0200 Subject: [PATCH 19/32] fix(nix): refresh pnpmDeps FOD hash for main's current pnpm-lock.yaml --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index d7c23aee..85c509ad 100644 --- a/flake.nix +++ b/flake.nix @@ -93,7 +93,7 @@ pname = "acryl"; inherit version src pnpm; fetcherVersion = 4; - hash = "sha256-z/LRm/EyIZxXgXVNMWTe+7DdfnwyzYBpoWjw8yzZrbI="; + hash = "sha256-nFn3Dg1gM+HvagWiAFZ4BnJFQlGILg15JZYmT2JfFqc="; }; # Shared flags for both TUI and desktop derivations. From f5a8891f1d924bb382583bb99ba954b9bdfda746 Mon Sep 17 00:00:00 2001 From: Alex Musichen Date: Fri, 11 Sep 2026 19:15:55 +0200 Subject: [PATCH 20/32] fix(nix): follow upstream acryl-tui -> acryl-cli package rename --- flake.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 85c509ad..6d30225d 100644 --- a/flake.nix +++ b/flake.nix @@ -220,10 +220,10 @@ # Build the TUI dependency chain. # acryl-harness-runtime imports types from acryl-control, so # acryl-control must be built first. Then acryl-harness-runtime, - # then acryl-tui (which depends on both). + # then acryl-cli (which depends on both; renamed from acryl-tui upstream). pnpm --filter acryl-control run build pnpm --filter acryl-harness-runtime run build - pnpm --filter acryl-tui run build + pnpm --filter acryl-cli run build runHook postBuild ''; @@ -234,8 +234,8 @@ mkdir -p $out/lib/acryl $out/bin # Copy the built TUI - cp -r acryl-tui/lib $out/lib/acryl/lib - cp acryl-tui/package.json $out/lib/acryl/ + cp -r acryl-cli/lib $out/lib/acryl/lib + cp acryl-cli/package.json $out/lib/acryl/ # With node-linker=hoisted, node_modules/ is a flat directory # (like npm's layout) with no .pnpm/ virtual store symlinks. From cdd89324109596efb882b07800f4cb8a96526984 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Fri, 11 Sep 2026 17:53:28 -0700 Subject: [PATCH 21/32] fix(nix): update prebuilt to v0.1.36, add hash automation, use newest runner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nixify skill compliance fixes after rebasing on upstream/main: 1. Update prebuilt version from v0.1.19 to v0.1.36 (latest release). Refresh all three per-platform SRI hashes by prefetching the new release assets. Remove x86_64-darwin from prebuiltAssets because v0.1.36 does not ship a darwin-x64 CLI tarball. 2. Make #prebuilt conditional via optionalAttrs so it is only exposed on platforms with a release asset (x86_64-linux, aarch64-linux, aarch64-darwin). On x86_64-darwin, nix run .#prebuilt correctly errors "package not available" instead of failing with a missing attribute error. 3. Add .github/workflows/nix-release.yml — daily hash automation workflow (scheduled lag-check template, required by nixify Step 16 for prebuilt tarball flakes). Detects when flake.nix lags behind the latest GitHub release, prefetches new SRI hashes, and opens a PR. Uses GITHUB_TOKEN (releases are created with GITHUB_TOKEN via softprops/action-gh-release, so release: published would never fire). 4. Update aarch64-darwin CI runner from macos-14 to macos-26 (nixify Step 16: always use the newest runner). --- .github/workflows/nix-release.yml | 170 ++++++++++++++++++++++++++++++ .github/workflows/nix.yml | 2 +- flake.nix | 116 ++++++++++---------- 3 files changed, 229 insertions(+), 59 deletions(-) create mode 100644 .github/workflows/nix-release.yml diff --git a/.github/workflows/nix-release.yml b/.github/workflows/nix-release.yml new file mode 100644 index 00000000..f3ba7d08 --- /dev/null +++ b/.github/workflows/nix-release.yml @@ -0,0 +1,170 @@ +name: Update Nix flake + +# Checks whether flake.nix lags behind the latest GitHub release. If it does, +# prefetches the new release's per-platform SRI hashes, rewrites flake.nix, +# and opens a PR. +# +# Runs on a schedule instead of release: published because releases are +# created with GITHUB_TOKEN via softprops/action-gh-release, which does not +# start new workflow runs. A daily lag-check is fully decoupled from how +# releases are created and needs no PAT. + +on: + schedule: + - cron: "17 6 * * *" + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +concurrency: + group: nix-flake-release + cancel-in-progress: true + +jobs: + update-flake: + name: Bump flake version + hashes if lagging + runs-on: ubuntu-latest + if: github.repository == 'acryldev/acryl' + steps: + - name: Checkout + uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 + with: + persist-credentials: false + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 + + - name: Check for lag and rewrite flake.nix + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # system|asset-substring — one per line. The substring must uniquely + # match the release asset filename for that system. + ASSET_MAP: | + x86_64-linux|acryl-cli-linux-x64.tar.gz + aarch64-linux|acryl-cli-linux-arm64.tar.gz + aarch64-darwin|acryl-cli-darwin-arm64.tar.gz + run: | + set -euo pipefail + python3 <<'PYEOF' + import json, os, re, subprocess, urllib.request + repo = os.environ["GITHUB_REPOSITORY"] + token = os.environ["GH_TOKEN"] + req = urllib.request.Request( + f"https://api.github.com/repos/{repo}/releases/latest", + headers={ + "Accept": "application/vnd.github+json", + "Authorization": f"Bearer {token}", + "X-GitHub-Api-Version": "2022-11-28", + }) + with urllib.request.urlopen(req) as r: + release = json.load(r) + tag = release["tag_name"] + version = tag.lstrip("v") + src = open("flake.nix").read() + m = re.search(r'releaseVersion = "([^"]*)";', src) + if not m: + raise SystemExit('could not find releaseVersion = "..." in flake.nix') + current = m.group(1) + print(f"flake.nix releaseVersion: {current} | latest release: {version} (tag {tag})") + if current == version: + print("flake.nix is up to date; nothing to do.") + with open(os.environ["GITHUB_ENV"], "a") as f: + f.write("LAGGING=no\n") + raise SystemExit(0) + with open(os.environ["GITHUB_ENV"], "a") as f: + f.write("LAGGING=yes\n") + f.write(f"VERSION={version}\n") + # Drop sibling checksum files (.sha256) so a tarball substring does + # not also match its ".sha256" companion. + names = {a["name"] for a in release["assets"] + if not a["name"].endswith(".sha256")} + asset_map = {} + for line in os.environ["ASSET_MAP"].splitlines(): + line = line.strip() + if not line or line.startswith("#"): + continue + sys_, sub = line.split("|", 1) + asset_map[sys_.strip()] = sub.strip() + # Reverse-check guard: flag any .tar.gz/.zip release asset that no + # ASSET_MAP substring matches. If a project ships for 4 platforms + # but ASSET_MAP only lists 3, the omitted platform's hash goes stale + # while its URL still gets the version bump — users on that platform + # get a hash mismatch. This catches the omission class of bug that + # CI cannot see (nix flake check --all-systems --no-build evaluates + # without realising fetchurl derivations, and nix build only runs on + # the runner's own system). + # Nix does not support native Windows (only WSL), so Windows + # .zip assets are always intentionally excluded from the flake. + # acryl-web-* archives are separate web runtime tarballs, not CLI. + IGNORED = ("musl", "pnpr-", "-source", "source-code", "win32", "win-x64", + "win-arm64", "windows", "acryl-web", "acryl-release-manifest", + "checksums", "release-receipt", ".receipt.json") + matched_subs = set(asset_map.values()) + unmatched = [ + name for name in sorted(names) + if name.endswith((".tar.gz", ".zip")) + and not any(sub in name for sub in matched_subs) + and not any(ign in name.lower() for ign in IGNORED) + ] + if unmatched: + plats = ", ".join(unmatched) + raise SystemExit( + f"RELEASE ASSET COMPLETENESS CHECK FAILED: release {tag} has " + f"platform archives not covered by ASSET_MAP: {plats}. " + f"Add them to ASSET_MAP or the hash for those platforms will " + f"go stale while the URL gets the version bump — users on the " + f"omitted platform get a hash mismatch. ASSET_MAP currently " + f"covers: {sorted(asset_map.keys())}") + src = open("flake.nix").read() + src, n = re.subn(r'releaseVersion = "[^"]*";', f'releaseVersion = "{version}";', src, count=1) + if n != 1: + raise SystemExit('could not find releaseVersion = "..." in flake.nix') + for sys_, sub in asset_map.items(): + match = next((n for n in names if sub in n), None) + if not match: + raise SystemExit(f"no asset for {sys_} ({sub}) in {tag}; have: {sorted(names)}") + url = f"https://github.com/{repo}/releases/download/{tag}/{match}" + # Cross-check against the published .sha256 sibling asset before + # pinning the hash. Without this, a corrupted or replaced release + # artifact would be pinned silently. + expected = None + if f"{match}.sha256" in {a["name"] for a in release["assets"]}: + with urllib.request.urlopen(f"{url}.sha256") as r: + hexd = r.read().decode().split()[0] + expected = "sha256:" + hexd + out = json.loads(subprocess.check_output( + ["nix", "store", "prefetch-file", "--json", "--hash-type", "sha256"] + + (["--expected-hash", expected] if expected else []) + + [url])) + sri = out["hash"] + pat = re.compile(r'("' + re.escape(sys_) + r'" = \{[^}]*\})', re.S) + def repl(m): + b = m.group(1) + b = re.sub(r'hash = "[^"]*";', f'hash = "{sri}";', b, count=1) + return b + src, n = pat.subn(repl, src, count=1) + if n != 1: + raise SystemExit(f"could not find prebuiltAssets block for {sys_} in flake.nix") + open("flake.nix", "w").write(src) + print(f"bumped flake.nix to {version}: {list(asset_map)}") + PYEOF + + - name: Open PR + if: env.LAGGING == 'yes' + uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v8 + with: + commit-message: "chore(nix): bump flake to v${{ env.VERSION }}" + title: "chore(nix): bump flake to v${{ env.VERSION }}" + branch: chore/nix-flake-v${{ env.VERSION }} + base: main + body: | + Auto-generated by the `Update Nix flake` workflow (daily lag-check). + The latest GitHub release is v${{ env.VERSION }} but `flake.nix` was + pinned to an older version. This PR bumps `releaseVersion` and refreshes + the per-platform SRI hashes by prefetching the new release assets. + + Note: PRs opened by `GITHUB_TOKEN` do not trigger downstream workflow runs (e.g. CI), + so this PR will show no checks. Review the diff before merging — it should be a + version bump plus per-platform hash refresh with no source changes. diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 80a1e339..c8a5a856 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -44,7 +44,7 @@ jobs: - system: aarch64-linux runner: ubuntu-24.04-arm - system: aarch64-darwin - runner: macos-14 + runner: macos-26 # x86_64-darwin (nixpkgs-26.05-darwin legacy pin) has no CI job: # the Determinate Nix installer no longer supports Intel macOS on # GitHub-hosted runners (DeterminateSystems/nix-src#224). The diff --git a/flake.nix b/flake.nix index 6d30225d..6d21f2fe 100644 --- a/flake.nix +++ b/flake.nix @@ -55,25 +55,23 @@ !pkgs'.lib.hasPrefix "/result" rel ); - # Prebuilt CLI release tarballs (v0.1.19). Each tarball bundles its + # Prebuilt CLI release tarballs (v0.1.36). Each tarball bundles its # own Node runtime and native addons (node-pty, koffi, sharp). - releaseVersion = "0.1.19"; + # v0.1.36 does not ship a darwin-x64 tarball, so #prebuilt is not + # available on x86_64-darwin — use #default or #acryl there. + releaseVersion = "0.1.36"; prebuiltAssets = { "x86_64-linux" = { url = "https://github.com/acryldev/acryl/releases/download/v${releaseVersion}/acryl-cli-linux-x64.tar.gz"; - hash = "sha256-cTlDn36FUJ69bLLKSqfXYBCcU2AMVL0GuTJ+y32833s="; + hash = "sha256-hGYEZPmdPC9IfRyIcwWsvq3wiDGHPJ2AHGumKI2UJSE="; }; "aarch64-linux" = { url = "https://github.com/acryldev/acryl/releases/download/v${releaseVersion}/acryl-cli-linux-arm64.tar.gz"; - hash = "sha256-/XNe8kTxF5/AgV1xeHg7kKeT9humvoH0MKcp81+/uLE="; - }; - "x86_64-darwin" = { - url = "https://github.com/acryldev/acryl/releases/download/v${releaseVersion}/acryl-cli-darwin-x64.tar.gz"; - hash = "sha256-8pvnuU0Z5+GOGAHKS+k6ucApZEBq55cnP0XK9H0t/hQ="; + hash = "sha256-6Op6wXArwHQuGd42feZeDXRMEsLRE2He4TvxzmcbFOk="; }; "aarch64-darwin" = { url = "https://github.com/acryldev/acryl/releases/download/v${releaseVersion}/acryl-cli-darwin-arm64.tar.gz"; - hash = "sha256-8W0Df1ZyLSEr+aYDmxGIWqEv43mZwRIJYgoDyWlfTqA="; + hash = "sha256-aP2zpAdfML8VJXinM0AqSKPdHNECB4EqarPoGAbXJyo="; }; }; in @@ -160,55 +158,6 @@ { default = self.packages.${system}.acryl; - # Prebuilt CLI tarball — bundles its own Node runtime and native - # addons (node-pty, koffi, sharp). Fast path for users who want - # the exact release binary without a from-source build. - prebuilt = pkgs.stdenv.mkDerivation { - pname = "acryl-prebuilt"; - inherit (commonDerivationAttrs) version; - - src = pkgs.fetchurl { - url = prebuiltAssets.${system}.url; - hash = prebuiltAssets.${system}.hash; - }; - - sourceRoot = "."; - - # The prebuilt tarball bundles both glibc-linked and musl-linked - # native addons (koffi ships musl_x64/koffi.node alongside - # linux_x64/koffi.node). autoPatchelf needs both glibc and musl - # available to satisfy all shared library dependencies. - nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.autoPatchelfHook ]; - buildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ - pkgs.stdenv.cc.cc.lib - pkgs.musl - ]; - - dontConfigure = true; - dontBuild = true; - - installPhase = '' - runHook preInstall - mkdir -p $out - cp -r acryl-cli-*/bin $out/bin - cp -r acryl-cli-*/lib $out/lib - cp -r acryl-cli-*/node_modules $out/node_modules - cp acryl-cli-*/package.json $out/ - chmod +x $out/bin/acryl - runHook postInstall - ''; - - meta = with pkgs.lib; { - description = "ACRYL TUI (prebuilt release binary)"; - homepage = "https://github.com/acryldev/acryl"; - downloadPage = "https://github.com/acryldev/acryl/releases"; - license = licenses.mit; - mainProgram = "acryl"; - platforms = builtins.attrNames prebuiltAssets; - sourceProvenance = [ sourceTypes.binaryNativeCode ]; - }; - }; - acryl = pkgs.stdenv.mkDerivation (finalAttrs: { pname = "acryl"; inherit (commonDerivationAttrs) version src pnpmDeps pnpm nativeBuildInputs preConfigure dontPnpmBuild dontStrip dontFixup; @@ -347,6 +296,57 @@ platforms = platforms.unix; }; }); + } + // pkgs.lib.optionalAttrs (prebuiltAssets ? ${system}) { + # Prebuilt CLI tarball — bundles its own Node runtime and native + # addons (node-pty, koffi, sharp). Fast path for users who want + # the exact release binary without a from-source build. + # Only exposed on platforms with a release asset. + prebuilt = pkgs.stdenv.mkDerivation { + pname = "acryl-prebuilt"; + inherit (commonDerivationAttrs) version; + + src = pkgs.fetchurl { + url = prebuiltAssets.${system}.url; + hash = prebuiltAssets.${system}.hash; + }; + + sourceRoot = "."; + + # The prebuilt tarball bundles both glibc-linked and musl-linked + # native addons (koffi ships musl_x64/koffi.node alongside + # linux_x64/koffi.node). autoPatchelf needs both glibc and musl + # available to satisfy all shared library dependencies. + nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.autoPatchelfHook ]; + buildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ + pkgs.stdenv.cc.cc.lib + pkgs.musl + ]; + + dontConfigure = true; + dontBuild = true; + + installPhase = '' + runHook preInstall + mkdir -p $out + cp -r acryl-cli-*/bin $out/bin + cp -r acryl-cli-*/lib $out/lib + cp -r acryl-cli-*/node_modules $out/node_modules + cp acryl-cli-*/package.json $out/ + chmod +x $out/bin/acryl + runHook postInstall + ''; + + meta = with pkgs.lib; { + description = "ACRYL TUI (prebuilt release binary)"; + homepage = "https://github.com/acryldev/acryl"; + downloadPage = "https://github.com/acryldev/acryl/releases"; + license = licenses.mit; + mainProgram = "acryl"; + platforms = builtins.attrNames prebuiltAssets; + sourceProvenance = [ sourceTypes.binaryNativeCode ]; + }; + }; }); devShells = forAllSystems ({ pkgs, system }: { From 305f3d986cc33030379e56c51da09080c4f60d71 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Fri, 11 Sep 2026 17:54:39 -0700 Subject: [PATCH 22/32] docs(nix): update READMEs to v0.1.36 and note #prebuilt platform scope - Bump the Nix tag-pinning example from v0.1.19 to v0.1.36 in all three READMEs (README.md, README.en.md, README.zh.md). - Note that #prebuilt is available on x86_64-linux, aarch64-linux, and aarch64-darwin only (v0.1.36 does not ship a darwin-x64 CLI tarball). - Re-record the bilingual-docs blob hashes in README.i18n.yaml. --- README.en.md | 4 ++-- README.md | 4 ++-- README.zh.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.en.md b/README.en.md index 03b32163..1b1ffdc0 100644 --- a/README.en.md +++ b/README.en.md @@ -82,13 +82,13 @@ nix run github:acryldev/acryl#acryl-desktop nix profile install github:acryldev/acryl # Specific release (the flake builds from source at every git tag) -nix run github:acryldev/acryl/v0.1.19 +nix run github:acryldev/acryl/v0.1.36 # Enter a development shell nix develop github:acryldev/acryl ``` -The flake exposes `packages..acryl` (TUI, from source, also `#default`), `packages..prebuilt` (prebuilt release binary with bundled Node runtime), `packages..acryl-desktop`, and `devShells..default`. +The flake exposes `packages..acryl` (TUI, from source, also `#default`), `packages..prebuilt` (prebuilt release binary with bundled Node runtime; available on `x86_64-linux`, `aarch64-linux`, and `aarch64-darwin`), `packages..acryl-desktop`, and `devShells..default`. ### Devbox diff --git a/README.md b/README.md index c477826b..30f31a88 100644 --- a/README.md +++ b/README.md @@ -90,13 +90,13 @@ nix run github:acryldev/acryl#acryl-desktop nix profile install github:acryldev/acryl # Specific release (the flake builds from source at every git tag) -nix run github:acryldev/acryl/v0.1.19 +nix run github:acryldev/acryl/v0.1.36 # Enter a development shell nix develop github:acryldev/acryl ``` -The flake exposes `packages..acryl` (TUI, from source, also `#default`), `packages..prebuilt` (prebuilt release binary with bundled Node runtime), `packages..acryl-desktop`, and `devShells..default`. +The flake exposes `packages..acryl` (TUI, from source, also `#default`), `packages..prebuilt` (prebuilt release binary with bundled Node runtime; available on `x86_64-linux`, `aarch64-linux`, and `aarch64-darwin`), `packages..acryl-desktop`, and `devShells..default`. ### Devbox diff --git a/README.zh.md b/README.zh.md index 595eb00d..e80f4d69 100644 --- a/README.zh.md +++ b/README.zh.md @@ -8,7 +8,7 @@ - 桌面 GUI 下载:[ACRYL v0.1.19 GitHub Release](https://github.com/acryldev/acryl/releases/tag/v0.1.19)([macOS Apple Silicon](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-mac-arm64.dmg)、[macOS Intel](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-mac-x64.dmg)、[Windows x64](https://github.com/acryldev/acryl/releases/download/v0.1.19/acryl-desktop-win-x64.exe)、[Linux x64 DEB](https://github.com/acryldev/acryl/releases/download/v0.1.19/dsh-plugin-desktop_0.1.9_amd64.deb)、[Linux arm64 DEB](https://github.com/acryldev/acryl/releases/download/v0.1.19/dsh-plugin-desktop_0.1.9_arm64.deb))。桌面应用自带所需运行时,但不会把 `acryl` 安装到 shell PATH,也不会在退出后持续运行 Web 服务。 - 终端 CLI(推荐):使用独立安装脚本(无需 Node.js/npm,无安装警告,并自动把 `acryl` 加入 shell PATH):`curl -fsSL https://acryl.dev/install | bash`。它会把预编译的 `acryl` 安装到 `~/.acryl/bin` 并校验校验和,之后在新终端运行 `acryl`。 - npm 终端 CLI(备选):[acryl](https://www.npmjs.com/package/acryl),`npm install -g acryl`,然后运行 `acryl`。npm 11+ 会打印关于原生依赖(`node-pty`、`koffi` 等)的 `install-scripts` 安全提示,属正常现象,包仍会正常安装运行;如需无警告安装,请运行 `npm install -g acryl --allow-scripts=@deepseek-ai/dsh-subprocess-local,@google/genai,koffi,node-pty,protobufjs`。 -- Nix(Flake):`nix run github:acryldev/acryl`(TUI,从源码构建,默认输出)或 `nix run github:acryldev/acryl#prebuilt`(预编译二进制,自带 Node 运行时)或 `nix run github:acryldev/acryl#acryl-desktop`(桌面 GUI)。也可 `nix profile install github:acryldev/acryl` 安装到 Nix profile。Flake 从源码构建,支持 tag pinning(如 `github:acryldev/acryl/v0.1.19`)。 +- Nix(Flake):`nix run github:acryldev/acryl`(TUI,从源码构建,默认输出)或 `nix run github:acryldev/acryl#prebuilt`(预编译二进制,自带 Node 运行时;支持 `x86_64-linux`、`aarch64-linux`、`aarch64-darwin`)或 `nix run github:acryldev/acryl#acryl-desktop`(桌面 GUI)。也可 `nix profile install github:acryldev/acryl` 安装到 Nix profile。Flake 从源码构建,支持 tag pinning(如 `github:acryldev/acryl/v0.1.36`)。 - Devbox:`devbox shell` 进入可复现开发环境(需先安装 Devbox:`curl -fsSL https://get.jetify.dev/devbox | bash`)。 - 本地 Web 界面:运行 `acryl web`。它启动本地服务并打印 URL,直到命令停止为止,不是托管的云服务。 - `acryl gui` 预留给未来从 CLI 跳转到桌面应用的功能;目前请直接启动已安装的桌面应用。 From 4aa1b0fcd7b7003159f146b22d5ce89e73978dd4 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Fri, 11 Sep 2026 17:56:12 -0700 Subject: [PATCH 23/32] docs(dev-log): record v0.1.36 bump, hash automation, and rebase Add a development-log entry for the v0.1.36 prebuilt bump, the new nix-release.yml hash automation workflow, the macos-26 runner update, and the rebase onto upstream/main 0822873. Re-point the two earlier Nix entries (acryl-desktop output and acryl-tui flake support) at their rebased commit hashes. --- docs/DEVELOPMENT-LOG.md | 97 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/docs/DEVELOPMENT-LOG.md b/docs/DEVELOPMENT-LOG.md index ee8f1245..b0067b97 100644 --- a/docs/DEVELOPMENT-LOG.md +++ b/docs/DEVELOPMENT-LOG.md @@ -701,7 +701,7 @@ the plugin path with one real model-facing Tool as the hard gate. Follow-on diff canvas) are intentionally recorded as subsequent ledgers. ## 2026-08-31 - Nix flake: add acryl-desktop (Electron) output -**Commit:** [`47840639adafd11c4531f096bec5fba44ce49c99`](https://github.com/acryldev/acryl/commit/47840639adafd11c4531f096bec5fba44ce49c99) +**Commit:** [`7383dd9d9e6b619fcec51c5f7567d6b1488d02b6`](https://github.com/acryldev/acryl/commit/7383dd9d9e6b619fcec51c5f7567d6b1488d02b6) Extended the Nix flake to also build the Electron desktop app as `packages.${system}.acryl-desktop`, alongside the existing TUI output. @@ -736,7 +736,7 @@ nix run .#acryl-desktop -- --version ## 2026-08-31 - Nix flake support for acryl-tui -**Commit:** [`f8f7efcd8a56f0942fee49a36ebacec493655210`](https://github.com/acryldev/acryl/commit/f8f7efcd8a56f0942fee49a36ebacec493655210) +**Commit:** [`4f15a00d778c8b01af8f536b78e04fbf3372f8ee`](https://github.com/acryldev/acryl/commit/4f15a00d778c8b01af8f536b78e04fbf3372f8ee) Added Nix flake support targeting the `acryl-tui` terminal client. The flake builds the TUI and its workspace dependencies (`acryl-control`, @@ -4657,7 +4657,51 @@ CLI's own install verb (spec 034 T006's original "at least one non-Electron surface" wording covers either) remains open - Web was the one driven to completion because it was the one under active user testing. -## 2026-09-13 - fix: Desktop's Market install was blocked by pnpm-workspace.yaml, not just a missing flag (spec 034 T006) +--- + +## 2026-09-11 - Nix flake: bump prebuilt to v0.1.36, add hash automation, newest runner + +**Commits:** [`cfa0c03a55adb34e3db4251cdd35ef50073d78a3`](https://github.com/acryldev/acryl/commit/cfa0c03a55adb34e3db4251cdd35ef50073d78a3) (implementation), [`d2e7ef2d0f6b6f8246be48a621bb59407bc31ddd`](https://github.com/acryldev/acryl/commit/d2e7ef2d0f6b6f8246be48a621bb59407bc31ddd) (docs) + +Rebased `feature/nix-flake-support` onto the latest `upstream/main` +(`0822873`) and applied the remaining nixify skill compliance fixes. + +### Changes + +- Bumped the prebuilt CLI version from v0.1.19 to v0.1.36 (latest + release). Refreshed all three per-platform SRI hashes by prefetching + the new release assets. +- Removed `x86_64-darwin` from `prebuiltAssets` because v0.1.36 does not + ship a darwin-x64 CLI tarball. Made `#prebuilt` conditional via + `optionalAttrs` so it is only exposed on platforms with a release + asset (`x86_64-linux`, `aarch64-linux`, `aarch64-darwin`). On + `x86_64-darwin`, `nix run .#prebuilt` correctly errors "package not + available" instead of failing with a missing attribute error. +- Added `.github/workflows/nix-release.yml` — daily hash automation + workflow (scheduled lag-check template, required by nixify Step 16 + for prebuilt tarball flakes). Detects when `flake.nix` lags behind + the latest GitHub release, prefetches new SRI hashes, and opens a + PR. Uses `GITHUB_TOKEN` (releases are created with `GITHUB_TOKEN` + via `softprops/action-gh-release`, so `release: published` would + never fire). +- Updated the `aarch64-darwin` CI runner from `macos-14` to `macos-26` + (nixify Step 16: always use the newest runner). +- Updated all three READMEs to reference v0.1.36 in the Nix tag-pinning + example and noted the `#prebuilt` platform scope. Re-recorded the + bilingual-docs blob hashes in `README.i18n.yaml`. +- Re-pointed the two earlier Nix development-log entries at their + rebased commit hashes. + +### Validation + +- `nix flake check --no-build` passes on `x86_64-darwin`. +- `nix build .#default` succeeds (from-source TUI build). +- `nix run .#default -- --help` shows the correct help output. +- `nix build .#prebuilt` correctly errors on `x86_64-darwin` (no + prebuilt asset for this platform). +- `validate-action-pins.sh` — all actions pinned to commit SHAs. +- `validate-pre-push.sh` — magic-nix-cache guard, timeout, runner + labels, action pins, and branch-not-stale checks all pass.## 2026-09-13 - fix: Desktop's Market install was blocked by pnpm-workspace.yaml, not just a missing flag (spec 034 T006) Commits: `71c7df7`, `e321be1` @@ -4727,6 +4771,50 @@ spec 034 to close: T007 (retire `acryl-desktop`'s now-dead private plugin-lifecycle duplication), T008 (the cross-surface duplicate-loader-entry parity gap), and the real end-to-end GUI retest on Desktop. +## 2026-09-11 - Nix flake: bump prebuilt to v0.1.36, add hash automation, newest runner + +**Commits:** [`cfa0c03a55adb34e3db4251cdd35ef50073d78a3`](https://github.com/acryldev/acryl/commit/cfa0c03a55adb34e3db4251cdd35ef50073d78a3) (implementation), [`d2e7ef2d0f6b6f8246be48a621bb59407bc31ddd`](https://github.com/acryldev/acryl/commit/d2e7ef2d0f6b6f8246be48a621bb59407bc31ddd) (docs) + +Rebased `feature/nix-flake-support` onto the latest `upstream/main` +(`0822873`) and applied the remaining nixify skill compliance fixes. + +### Changes + +- Bumped the prebuilt CLI version from v0.1.19 to v0.1.36 (latest + release). Refreshed all three per-platform SRI hashes by prefetching + the new release assets. +- Removed `x86_64-darwin` from `prebuiltAssets` because v0.1.36 does not + ship a darwin-x64 CLI tarball. Made `#prebuilt` conditional via + `optionalAttrs` so it is only exposed on platforms with a release + asset (`x86_64-linux`, `aarch64-linux`, `aarch64-darwin`). On + `x86_64-darwin`, `nix run .#prebuilt` correctly errors "package not + available" instead of failing with a missing attribute error. +- Added `.github/workflows/nix-release.yml` — daily hash automation + workflow (scheduled lag-check template, required by nixify Step 16 + for prebuilt tarball flakes). Detects when `flake.nix` lags behind + the latest GitHub release, prefetches new SRI hashes, and opens a + PR. Uses `GITHUB_TOKEN` (releases are created with `GITHUB_TOKEN` + via `softprops/action-gh-release`, so `release: published` would + never fire). +- Updated the `aarch64-darwin` CI runner from `macos-14` to `macos-26` + (nixify Step 16: always use the newest runner). +- Updated all three READMEs to reference v0.1.36 in the Nix tag-pinning + example and noted the `#prebuilt` platform scope. Re-recorded the + bilingual-docs blob hashes in `README.i18n.yaml`. +- Re-pointed the two earlier Nix development-log entries at their + rebased commit hashes. + +### Validation + +- `nix flake check --no-build` passes on `x86_64-darwin`. +- `nix build .#default` succeeds (from-source TUI build). +- `nix run .#default -- --help` shows the correct help output. +- `nix build .#prebuilt` correctly errors on `x86_64-darwin` (no + prebuilt asset for this platform). +- `validate-action-pins.sh` — all actions pinned to commit SHAs. +- `validate-pre-push.sh` — magic-nix-cache guard, timeout, runner + labels, action pins, and branch-not-stale checks all pass. + ## 2026-09-14 - fix(desktop): report restartRequired for a live plugin disable/enable Commit: `46ff326` @@ -4917,6 +5005,7 @@ into the temp profile rather than symlinking them, making them resolvable in the isolated context. Verified: `corepack pnpm --filter acryl-desktop run check` now passes end to end with exit code 0. +<<<<<<< HEAD ## 2026-09-15/16 - feat(cli): /plugins fuzzy search + navigation-while-filtering fix Commits: `82d316c`, `2785545` @@ -5263,3 +5352,5 @@ binary directly rather than through whatever bare `pnpm` resolves to on - Not done, on purpose or by decision: steps 9-11 of T045's own checklist - push the registry, resync both sites (acryldev.github.io/ui and acrylblends.github.io/ui) and push the commits - were reserved for the operator at review time, so everything above is committed locally and unPushed. `questionnaire` and `message-scroller` stay blocked rather than ported narrower. Nothing else in T045 is open: the 26 ports are in the manifest, contracted, categorised (both sites render a component only inside a category, so an uncategorised port is invisible - a bug class that shipped twice before the ingest gate checked it), tested and browser-verified. +======= +>>>>>>> 9a172dc (docs(dev-log): record v0.1.36 bump, hash automation, and rebase) From 903c6d0f62107d44fdce34ae46bce4139e07b078 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Sat, 12 Sep 2026 15:51:18 -0700 Subject: [PATCH 24/32] fix(nix): refresh pnpmDeps FOD hash after rebase onto 227c3f9 The rebase onto upstream/main 227c3f9 pulled in a new pnpm-lock.yaml (7869 lines changed) which invalidated the fetchPnpmDeps hash. Updated to sha256-gqs/PgXIBj8+YsH/z/qIPa68XVNO7hu4eDxvShYkyxI= as reported by the aarch64-darwin CI failure. --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 6d21f2fe..b3c239a4 100644 --- a/flake.nix +++ b/flake.nix @@ -91,7 +91,7 @@ pname = "acryl"; inherit version src pnpm; fetcherVersion = 4; - hash = "sha256-nFn3Dg1gM+HvagWiAFZ4BnJFQlGILg15JZYmT2JfFqc="; + hash = "sha256-gqs/PgXIBj8+YsH/z/qIPa68XVNO7hu4eDxvShYkyxI="; }; # Shared flags for both TUI and desktop derivations. From d6500874c2c31b71a32ca799435f5216e8a80821 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Sat, 12 Sep 2026 16:05:57 -0700 Subject: [PATCH 25/32] chore(nix): trigger CI after FOD hash refresh From aee4007eba0425ae0a3e5295075496649af67e94 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Mon, 14 Sep 2026 19:32:11 -0700 Subject: [PATCH 26/32] fix(nix): adapt flake to apps/runtime/plugins reorg on main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Main reorganized workspace packages from the root into apps/, runtime/, plugins/, distribution/, and examples/ directories. The flake's build and install phases still referenced the old flat paths (acryl-cli/lib, acryl-control/lib, etc.). - Update all source paths in build and install phases to use the new directory structure (apps/acryl-cli, runtime/acryl-control, plugins/dsh-community-market, apps/acryl-desktop). - Add dsh-community-market to the CLI (#default) build chain — main added a /market command to acryl-cli that imports dsh-community-market, so it must be built before acryl-cli. - Remove acryl-development-canvas from the desktop build chain — the package no longer exists in the workspace. - Split installWorkspacePackage into srcDir (workspace path) and pkgName (node_modules name) since they now differ. Add an extraDirs parameter to copy non-compiled runtime assets (dsh-community-market reads JSON schemas from docs/schemas/ at runtime via readFileSync relative to lib/). --- flake.nix | 53 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/flake.nix b/flake.nix index b3c239a4..02174383 100644 --- a/flake.nix +++ b/flake.nix @@ -147,12 +147,21 @@ # Helper to install a built workspace package into a node_modules # directory, replacing any symlink/dir that the hoisted linker - # may have created. - installWorkspacePackage = pkgDir: destDir: '' - rm -rf ${destDir}/${pkgDir} - mkdir -p ${destDir}/${pkgDir} - cp -r ${pkgDir}/lib ${destDir}/${pkgDir}/lib - cp ${pkgDir}/package.json ${destDir}/${pkgDir}/ + # may have created. srcDir is the workspace path (e.g. + # "runtime/acryl-control"), pkgName is the node_modules name + # (e.g. "acryl-control"). extraDirs is a list of additional + # subdirectories to copy (e.g. ["docs"] for packages that read + # non-compiled assets at runtime; pass [] when not needed). + installWorkspacePackage = srcDir: pkgName: destDir: extraDirs: + let copyExtra = pkgs.lib.concatMapStrings (d: '' + cp -r ${srcDir}/${d} ${destDir}/${pkgName}/${d} + '') extraDirs; + in '' + rm -rf ${destDir}/${pkgName} + mkdir -p ${destDir}/${pkgName} + cp -r ${srcDir}/lib ${destDir}/${pkgName}/lib + cp ${srcDir}/package.json ${destDir}/${pkgName}/ + ${copyExtra} ''; in { @@ -169,9 +178,12 @@ # Build the TUI dependency chain. # acryl-harness-runtime imports types from acryl-control, so # acryl-control must be built first. Then acryl-harness-runtime, - # then acryl-cli (which depends on both; renamed from acryl-tui upstream). + # then dsh-community-market (imported by acryl-cli's /market + # command), then acryl-cli (which depends on all three; + # renamed from acryl-tui upstream). pnpm --filter acryl-control run build pnpm --filter acryl-harness-runtime run build + pnpm --filter dsh-community-market run build pnpm --filter acryl-cli run build runHook postBuild @@ -183,8 +195,8 @@ mkdir -p $out/lib/acryl $out/bin # Copy the built TUI - cp -r acryl-cli/lib $out/lib/acryl/lib - cp acryl-cli/package.json $out/lib/acryl/ + cp -r apps/acryl-cli/lib $out/lib/acryl/lib + cp apps/acryl-cli/package.json $out/lib/acryl/ # With node-linker=hoisted, node_modules/ is a flat directory # (like npm's layout) with no .pnpm/ virtual store symlinks. @@ -194,8 +206,9 @@ # Replace workspace package symlinks/dirs with actual built # packages (the hoisted linker may have created symlinks for # workspace packages that point to source directories). - ${installWorkspacePackage "acryl-control" "$out/lib/acryl/node_modules"} - ${installWorkspacePackage "acryl-harness-runtime" "$out/lib/acryl/node_modules"} + ${installWorkspacePackage "runtime/acryl-control" "acryl-control" "$out/lib/acryl/node_modules" []} + ${installWorkspacePackage "runtime/acryl-harness-runtime" "acryl-harness-runtime" "$out/lib/acryl/node_modules" []} + ${installWorkspacePackage "plugins/dsh-community-market" "dsh-community-market" "$out/lib/acryl/node_modules" ["docs"]} # Wrap the TUI entry point makeWrapper ${pkgs.nodejs_22}/bin/node $out/bin/acryl \ @@ -230,7 +243,6 @@ pnpm --filter acryl-control run build pnpm --filter acryl-harness-runtime run build pnpm --filter dsh-community-market run build - pnpm --filter acryl-development-canvas run build # Build the desktop package. Skip the generate-* scripts # (they use sharp for image processing) since the build/ @@ -250,20 +262,19 @@ mkdir -p $out/lib/acryl-desktop $out/bin # Copy the built desktop package - cp -r acryl-desktop/lib $out/lib/acryl-desktop/lib - cp -r acryl-desktop/build $out/lib/acryl-desktop/build - cp acryl-desktop/package.json $out/lib/acryl-desktop/ - cp acryl-desktop/cordis.patch.yml $out/lib/acryl-desktop/ 2>/dev/null || true + cp -r apps/acryl-desktop/lib $out/lib/acryl-desktop/lib + cp -r apps/acryl-desktop/build $out/lib/acryl-desktop/build + cp apps/acryl-desktop/package.json $out/lib/acryl-desktop/ + cp apps/acryl-desktop/cordis.patch.yml $out/lib/acryl-desktop/ 2>/dev/null || true # Copy node_modules (hoisted, flat layout) cp -a node_modules $out/lib/acryl-desktop/node_modules # Replace workspace packages with built versions - ${installWorkspacePackage "acryl-control" "$out/lib/acryl-desktop/node_modules"} - ${installWorkspacePackage "acryl-harness-runtime" "$out/lib/acryl-desktop/node_modules"} - ${installWorkspacePackage "dsh-community-market" "$out/lib/acryl-desktop/node_modules"} - ${installWorkspacePackage "acryl-development-canvas" "$out/lib/acryl-desktop/node_modules"} - ${installWorkspacePackage "acryl-desktop" "$out/lib/acryl-desktop/node_modules"} + ${installWorkspacePackage "runtime/acryl-control" "acryl-control" "$out/lib/acryl-desktop/node_modules" []} + ${installWorkspacePackage "runtime/acryl-harness-runtime" "acryl-harness-runtime" "$out/lib/acryl-desktop/node_modules" []} + ${installWorkspacePackage "plugins/dsh-community-market" "dsh-community-market" "$out/lib/acryl-desktop/node_modules" ["docs"]} + ${installWorkspacePackage "apps/acryl-desktop" "acryl-desktop" "$out/lib/acryl-desktop/node_modules" []} # Create a shim for the 'electron' npm package that exports # the nixpkgs electron path. The desktop launcher does From 34c5213965712124a90e1c461cdb033de9c3f422 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Mon, 14 Sep 2026 19:39:32 -0700 Subject: [PATCH 27/32] fix(ci): build dsh-community-market before typecheck MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit acryl-cli now imports dsh-community-market (added by the /market command), but the CI workflow's 'Build workspace type providers' step only built acryl-control and acryl-harness-runtime. The typecheck step then fails with TS2307 for dsh-community-market. This is a pre-existing issue on main — it was hidden because main's CI fails earlier at the bilingual-docs gate before reaching typecheck. --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71e53ad3..ab0e835e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,13 +65,17 @@ jobs: # The workspace packages export their types from a built lib/. On a fresh # checkout those are absent, so consumers (acryl-cli -> acryl-harness- - # runtime -> acryl-control, cordis-plugin-market) cannot typecheck until - # the providers are built. + # runtime -> acryl-control, cordis-plugin-market, and acryl-cli -> dsh- + # community-market) cannot typecheck until the providers are built. The + # web serve test also loads dsh-client-ui-brand-acryl as a profile plugin, + # so its lib/ must exist before the test step. - name: Build workspace type providers run: | corepack pnpm --filter acryl-control run build corepack pnpm --filter acryl-harness-runtime run build + corepack pnpm --filter dsh-community-market run build corepack pnpm --filter cordis-plugin-market run build + corepack pnpm --filter dsh-client-ui-brand-acryl run build - name: Typecheck run: corepack pnpm run typecheck From 0ecbae348934cc8729ccdfa2f47cb5d8ac86b79a Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Thu, 17 Sep 2026 15:14:58 -0700 Subject: [PATCH 28/32] ci(nix): restore x86_64-darwin job on macos-26-intel with upstream installer The job was dropped after the Determinate installer failed on the deprecated macos-13 image. The actual constraint is narrower: Determinate stopped shipping Intel *host* builds in Nov 2025 (DeterminateSystems/nix-src#224), but GitHub still provides Intel runners and upstream Nix installs fine on them. Run the leg on macos-26-intel (the current Intel label, GA Feb 2026) using cachix/install-nix-action with flakes enabled explicitly; other legs keep the Determinate installer. --- .github/workflows/nix.yml | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index c8a5a856..7beb0e45 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -45,18 +45,33 @@ jobs: runner: ubuntu-24.04-arm - system: aarch64-darwin runner: macos-26 - # x86_64-darwin (nixpkgs-26.05-darwin legacy pin) has no CI job: - # the Determinate Nix installer no longer supports Intel macOS on - # GitHub-hosted runners (DeterminateSystems/nix-src#224). The - # derivation stays in flake.nix for local Intel builders; restore - # the job via a Rosetta cross-build from macos-14 when feasible. + # x86_64-darwin uses the nixpkgs-26.05-darwin legacy pin. + # macos-26-intel is the current Intel macOS runner label (GA Feb + # 2026). Determinate dropped Intel *hosts* in Nov 2025 + # (DeterminateSystems/nix-src#224), so this leg installs upstream + # Nix via cachix/install-nix-action instead of the Determinate + # installer below. + - system: x86_64-darwin + runner: macos-26-intel steps: - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5 with: submodules: recursive + # Determinate Nix installer — not usable on x86_64-darwin hosts since + # Nov 2025 (DeterminateSystems/nix-src#224). - uses: DeterminateSystems/nix-installer-action@ef8a148080ab6020fd15196c2084a2eea5ff2d25 # v22 + if: matrix.system != 'x86_64-darwin' + + # Upstream Nix installer for the Intel macOS leg (Determinate no longer + # ships an x86_64-darwin host build). Vanilla Nix needs flakes enabled + # explicitly; the Determinate installer does it implicitly. + - uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1 + if: matrix.system == 'x86_64-darwin' + with: + extra_nix_config: | + experimental-features = nix-command flakes # magic-nix-cache is Linux-only: the v14 static binary on arm64-darwin # fails with `dyld: Symbol not found: __ZNSt13exception_ptr...` because From dbb3a5aa4024b403d3bf28e3af601de02f74a218 Mon Sep 17 00:00:00 2001 From: levonk <277861+levonk@users.noreply.github.com> Date: Thu, 17 Sep 2026 15:30:00 -0700 Subject: [PATCH 29/32] ci(nix): skip #prebuilt steps on systems without a release asset --- .github/workflows/nix.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 7beb0e45..c82cb793 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -92,8 +92,15 @@ jobs: - name: Build acryl-desktop run: nix build .#acryl-desktop --system ${{ matrix.system }} + # #prebuilt exists only on systems with a release asset — x86_64-darwin + # has no darwin-x64 tarball, so the attribute is absent there. - name: Build prebuilt - run: nix build .#prebuilt --system ${{ matrix.system }} + run: | + if nix flake show --json 2>/dev/null | jq -e '.packages["${{ matrix.system }}"].prebuilt' >/dev/null; then + nix build .#prebuilt --system ${{ matrix.system }} + else + echo "No #prebuilt output for ${{ matrix.system }} — skipping" + fi - name: Test default --help if: github.event_name != 'pull_request' @@ -105,7 +112,12 @@ jobs: - name: Test prebuilt --help if: github.event_name != 'pull_request' - run: nix run .#prebuilt -- --help + run: | + if nix flake show --json 2>/dev/null | jq -e '.packages["${{ matrix.system }}"].prebuilt' >/dev/null; then + nix run .#prebuilt -- --help + else + echo "No #prebuilt output for ${{ matrix.system }} — skipping" + fi - name: Test desktop --help if: github.event_name != 'pull_request' From 873a09e40b06b4fab1b2461e77230094945bd478 Mon Sep 17 00:00:00 2001 From: Alex Musichen Date: Wed, 23 Sep 2026 18:15:18 +0200 Subject: [PATCH 30/32] fix(test): give protected plugin entry a unique module name to avoid ambiguity in findLiveEntry --- runtime/acryl-control/tests/plugin-lifecycle.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/acryl-control/tests/plugin-lifecycle.spec.ts b/runtime/acryl-control/tests/plugin-lifecycle.spec.ts index 02c3fc19..5e271d44 100644 --- a/runtime/acryl-control/tests/plugin-lifecycle.spec.ts +++ b/runtime/acryl-control/tests/plugin-lifecycle.spec.ts @@ -100,12 +100,13 @@ async function harness(overrides: Partial = {}): Promise } From 141009f5d4acbf5f4bf0b99a56cc94aeff1bd0c8 Mon Sep 17 00:00:00 2001 From: Alex Musichen Date: Wed, 23 Sep 2026 20:58:05 +0200 Subject: [PATCH 31/32] fix(i18n): re-record README blob hashes to match rebased README content --- README.i18n.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.i18n.yaml b/README.i18n.yaml index 061e7c13..24fb2d6e 100644 --- a/README.i18n.yaml +++ b/README.i18n.yaml @@ -1,5 +1,5 @@ # Bilingual-pair consistency record: the git blob hash of each side as of the last # confirmed-consistent state. Both languages carry equal authority. Update both files # and re-record their hashes after editing either side. -README.md: 583aa69ea97b093f36ccadad0fb7e6824691e96d -README.en.md: a6165b692aaf57f4374f2a557ff09e604831cb58 +README.md: 30f31a88cc22a53089ce593dd3d7b1276e46e03e +README.en.md: 1b1ffdc0a9b64b9952f121c136f9c0f51ae61afb From cbc98d1cab7cec2f4bbb8e2c680935da263c47ed Mon Sep 17 00:00:00 2001 From: Alex Musichen Date: Wed, 23 Sep 2026 21:04:13 +0200 Subject: [PATCH 32/32] fix(nix): update pnpmDeps hash for pnpm 11.11.0 lockfile --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 02174383..bcbaee41 100644 --- a/flake.nix +++ b/flake.nix @@ -91,7 +91,7 @@ pname = "acryl"; inherit version src pnpm; fetcherVersion = 4; - hash = "sha256-gqs/PgXIBj8+YsH/z/qIPa68XVNO7hu4eDxvShYkyxI="; + hash = "sha256-vBmWX7p/3ic/8VQj0tqlEIGHll3x8UJ4kQuT3fEWKlQ="; }; # Shared flags for both TUI and desktop derivations.