OpenClaw on NixOS: Golden Master Test with Claude Opus 4.6
Setting the Stage: Context for the Curious Book Reader
This technical blueprint chronicles a multi-day debugging saga involving OpenClaw, an AI agent, and NixOS, a declarative operating system. It details the journey from a non-functional local agent to a fully operational system capable of executing real filesystem commands, validated by the powerful Claude Opus 4.6. Readers will witness the iterative process of unraveling complex configuration issues, architectural misunderstandings, and the nuanced interplay between AI models, environment variables, and immutable infrastructure, culminating in a pivotal breakthrough for autonomous computing.
Technical Journal Entry Begins
Alright here we go with the next and hopefully last article in this epic. To make that true I really have to absorb what Claude Opus 4.6 which I just begrudgingly signed up for just told me.
The OpenClaw Enigma: A Skill File Misconception
My custom SKILL.md format is incompatible with OpenClaw’s actual skill
architecture. I should have known that since it was generatively produced and
not the one that was put there (or linked-to) in the install. Much of this is
because I still use a configuration.nix file for NixOS and haven’t moved to
the Nix Home Manager which every time I look at I think is disgusting and
violating the spirit of Nix. So I’m sticking with what’s being called a legacy
setup though I rather oppose that characterization. It’s a pure spirit of Nix
setup without the exact sort of over-abstraction and over-complication that
drove me to Nix in the first place. There should be once source of truth and
it’s not about users. It’s about servers.
Anyway, enough rant. Now to really nail this OpenClaw on so-called legacy NixOS problem. I think I have all the pieces now and Claude Opus 4.6 really was key.
Debugging Strategy: Pivoting to Deep Inspection
It gives me a Path A and a Path B. I’ll start with Path A and then move onto Path B. It tells me:
# See what the flake actually installed
find /nix/store -maxdepth 3 -path "*openclaw*skills*" -type d 2>/dev/null | head -20
# Check if there's a default config path baked in
strings $(which openclaw) | grep -i skill | head -20
But don’t use find. Use rg (ripgrep). Clarify the issues and update the Path
A instructions with my rg preference please and thank you!
Gemini Opus 4.6: Good call on rg — though for this specific task we need to be precise about which tool does what. Let me clarify:
The first command is searching for directories in the Nix store. rg (ripgrep) searches file contents, not directory structures. For finding directories by path pattern, find or fd (the ripgrep-companion tool) is correct. Let’s use fd if you have it, otherwise find is the right tool here:
# Option 1: fd (the "ripgrep of find")
fd -t d "skills" /nix/store -d 3 2>/dev/null | grep openclaw | head -20
# Option 2: If fd isn't installed, find is correct here
find /nix/store -maxdepth 3 -path "*openclaw*skills*" -type d 2>/dev/null | head -20
The second command uses strings piped to grep — you can absolutely use rg here:
strings $(which openclaw) | rg -i skill | head -20
But here’s what actually matters more than either command. The skills shipped with nix-openclaw are likely inside the package closure. Let’s go straight to the source:
# 1. Find the actual openclaw package in the store
realpath $(which openclaw)
# 2. Then explore what's in that package
ls -la $(dirname $(dirname $(realpath $(which openclaw))))
# 3. Look for anything skills-related in the full package tree
find $(dirname $(dirname $(realpath $(which openclaw)))) -name "*skill*" -o -name "manifest.json" 2>/dev/null
# 4. Also check: what does the nix-openclaw flake actually provide?
# This shows the Home Manager module source — where the skill symlinking logic lives
find /nix/store -maxdepth 2 -name "nix-openclaw" -type d 2>/dev/null | head -5
Executing Diagnostics: Unveiling the Skill Architecture
Run those four commands and paste the output. That will tell us exactly where the built-in skills live in your Nix store and what format they’re in — which is the key to solving Path A without Home Manager.
Me: Okay, done:
[mike@nixos:~/repos/nixos]$ fd -t d "skills" /nix/store -d 3 2>/dev/null | grep openclaw | head -20
[mike@nixos:~/repos/nixos]$ strings $(which openclaw) | rg -i skill | head -20
The program 'strings' is not in your PATH. It is provided by several packages.
You can make it available in an ephemeral shell by typing one of the following:
nix-shell -p _9base
nix-shell -p arocc
nix-shell -p bintools
nix-shell -p bintools-unwrapped
nix-shell -p bintoolsNoLibc
nix-shell -p binutils
nix-shell -p binutils-unwrapped-all-targets
nix-shell -p binutils-unwrapped_2_38
nix-shell -p binutils_nogold
nix-shell -p busybox
nix-shell -p ccacheWrapper
nix-shell -p clang
nix-shell -p clang_12
nix-shell -p clang_13
nix-shell -p clang_14
nix-shell -p clang_15
nix-shell -p clang_16
nix-shell -p clang_17
nix-shell -p clang_18
nix-shell -p clang_20
nix-shell -p clang_21
nix-shell -p clang_multi
nix-shell -p distccWrapper
nix-shell -p gcc
nix-shell -p gcc10
nix-shell -p gcc11
nix-shell -p gcc12
nix-shell -p gcc13
nix-shell -p gcc14
nix-shell -p gcc15
nix-shell -p gcc9
nix-shell -p gcc_debug
nix-shell -p gcc_multi
nix-shell -p gccgo
nix-shell -p gccgo12
nix-shell -p gccgo13
nix-shell -p gccgo14
nix-shell -p gccgo15
nix-shell -p gdc
nix-shell -p gfortran
nix-shell -p gfortran10
nix-shell -p gfortran11
nix-shell -p gfortran12
nix-shell -p gfortran13
nix-shell -p gfortran14
nix-shell -p gfortran15
nix-shell -p gfortran9
nix-shell -p gnat
nix-shell -p gnat-bootstrap
nix-shell -p gnat-bootstrap11
nix-shell -p gnat-bootstrap13
nix-shell -p gnat-bootstrap14
nix-shell -p gnat12
nix-shell -p gnat14
nix-shell -p gnat15
nix-shell -p llvmPackages.bintools
nix-shell -p llvmPackages.bintools-unwrapped
nix-shell -p llvmPackages.bintoolsNoLibc
nix-shell -p llvmPackages.clangNoCompilerRt
nix-shell -p llvmPackages.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages.clangNoLibc
nix-shell -p llvmPackages.clangNoLibcxx
nix-shell -p llvmPackages.clangUseLLVM
nix-shell -p llvmPackages.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages.libcxxClang
nix-shell -p llvmPackages_12.bintools
nix-shell -p llvmPackages_12.bintools-unwrapped
nix-shell -p llvmPackages_12.bintoolsNoLibc
nix-shell -p llvmPackages_12.clangNoCompilerRt
nix-shell -p llvmPackages_12.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages_12.clangNoLibc
nix-shell -p llvmPackages_12.clangNoLibcxx
nix-shell -p llvmPackages_12.clangUseLLVM
nix-shell -p llvmPackages_12.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages_12.libcxxClang
nix-shell -p llvmPackages_13.bintools
nix-shell -p llvmPackages_13.bintools-unwrapped
nix-shell -p llvmPackages_13.bintoolsNoLibc
nix-shell -p llvmPackages_13.clangNoCompilerRt
nix-shell -p llvmPackages_13.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages_13.clangNoLibc
nix-shell -p llvmPackages_13.clangNoLibcxx
nix-shell -p llvmPackages_13.clangUseLLVM
nix-shell -p llvmPackages_13.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages_13.libcxxClang
nix-shell -p llvmPackages_14.bintools
nix-shell -p llvmPackages_14.bintools-unwrapped
nix-shell -p llvmPackages_14.bintoolsNoLibc
nix-shell -p llvmPackages_14.clangNoCompilerRt
nix-shell -p llvmPackages_14.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages_14.clangNoLibc
nix-shell -p llvmPackages_14.clangNoLibcxx
nix-shell -p llvmPackages_14.clangUseLLVM
nix-shell -p llvmPackages_14.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages_14.libcxxClang
nix-shell -p llvmPackages_15.bintools
nix-shell -p llvmPackages_15.bintools-unwrapped
nix-shell -p llvmPackages_15.bintoolsNoLibc
nix-shell -p llvmPackages_15.clangNoCompilerRt
nix-shell -p llvmPackages_15.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages_15.clangNoLibc
nix-shell -p llvmPackages_15.clangNoLibcxx
nix-shell -p llvmPackages_15.clangUseLLVM
nix-shell -p llvmPackages_15.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages_15.libcxxClang
nix-shell -p llvmPackages_16.bintools
nix-shell -p llvmPackages_16.bintools-unwrapped
nix-shell -p llvmPackages_16.bintoolsNoLibc
nix-shell -p llvmPackages_16.clangNoCompilerRt
nix-shell -p llvmPackages_16.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages_16.clangNoLibc
nix-shell -p llvmPackages_16.clangNoLibcxx
nix-shell -p llvmPackages_16.clangUseLLVM
nix-shell -p llvmPackages_16.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages_16.libcxxClang
nix-shell -p llvmPackages_17.bintools
nix-shell -p llvmPackages_17.bintools-unwrapped
nix-shell -p llvmPackages_17.bintoolsNoLibc
nix-shell -p llvmPackages_17.clangNoCompilerRt
nix-shell -p llvmPackages_17.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages_17.clangNoLibc
nix-shell -p llvmPackages_17.clangNoLibcxx
nix-shell -p llvmPackages_17.clangUseLLVM
nix-shell -p llvmPackages_17.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages_17.libcxxClang
nix-shell -p llvmPackages_18.bintools
nix-shell -p llvmPackages_18.bintools-unwrapped
nix-shell -p llvmPackages_18.bintoolsNoLibc
nix-shell -p llvmPackages_18.clangNoCompilerRt
nix-shell -p llvmPackages_18.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages_18.clangNoLibc
nix-shell -p llvmPackages_18.clangNoLibcxx
nix-shell -p llvmPackages_18.clangUseLLVM
nix-shell -p llvmPackages_18.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages_18.libcxxClang
nix-shell -p llvmPackages_20.bintools
nix-shell -p llvmPackages_20.bintools-unwrapped
nix-shell -p llvmPackages_20.bintoolsNoLibc
nix-shell -p llvmPackages_20.clangNoCompilerRt
nix-shell -p llvmPackages_20.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages_20.clangNoLibc
nix-shell -p llvmPackages_20.clangNoLibcxx
nix-shell -p llvmPackages_20.clangUseLLVM
nix-shell -p llvmPackages_20.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages_20.libcxxClang
nix-shell -p llvmPackages_21.bintools
nix-shell -p llvmPackages_21.bintools-unwrapped
nix-shell -p llvmPackages_21.bintoolsNoLibc
nix-shell -p llvmPackages_21.clangNoCompilerRt
nix-shell -p llvmPackages_21.clangNoCompilerRtWithLibc
nix-shell -p llvmPackages_21.clangNoLibc
nix-shell -p llvmPackages_21.clangNoLibcxx
nix-shell -p llvmPackages_21.clangUseLLVM
nix-shell -p llvmPackages_21.clangWithLibcAndBasicRtAndLibcxx
nix-shell -p llvmPackages_21.libcxxClang
nix-shell -p rocmPackages.clang
nix-shell -p rocmPackages.llvm.bintools
nix-shell -p rocmPackages.llvm.rocm-merged-llvm
nix-shell -p toybox
nix-shell -p u-root-cmds
[mike@nixos:~/repos/nixos]$ realpath $(which openclaw)
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/bin/openclaw
[mike@nixos:~/repos/nixos]$ ls -la $(dirname $(dirname $(realpath $(which openclaw))))
total 10492
dr-xr-xr-x 4 root root 4096 Dec 31 1969 .
drwxrwxr-t 4195 root nixbld 10723328 Feb 16 10:30 ..
dr-xr-xr-x 2 root root 4096 Dec 31 1969 bin
dr-xr-xr-x 3 root root 4096 Dec 31 1969 lib
[mike@nixos:~/repos/nixos]$ find $(dirname $(dirname $(realpath $(which openclaw)))) -name "*skill*" -o -name "manifest.json" 2>/dev/null
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/examples/sdk/04-skills.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/core/skills.d.ts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/core/skills.js.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/core/skills.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/core/skills.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@mariozechner+pi-coding-agent@0.52.12_ws@8.19.0_zod@4.3.6/node_modules/@mariozechner/pi-coding-agent/docs/skills.md
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills.mjs
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills.d.mts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.mjs
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.d.mts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.mjs.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.d.mts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.d.ts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.js.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills.mjs.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills.d.mts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills.d.ts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills.js.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/resources/beta/skills.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/src/resources/beta/skills.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/src/resources/beta/skills
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/@anthropic-ai+sdk@0.73.0_zod@4.3.6/node_modules/@anthropic-ai/sdk/src/resources/beta/skills/skills.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills.mjs
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills.d.mts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills/skills.mjs
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills/skills.d.mts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills/skills.mjs.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills/skills.d.mts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills/skills.d.ts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills/skills.js.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills/skills.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills/skills.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills.mjs.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills.d.mts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills.d.ts.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills.js.map
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/resources/skills.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/src/resources/skills.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/src/resources/skills
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/node_modules/.pnpm/openai@6.22.0_ws@8.19.0_zod@4.3.6/node_modules/openai/src/resources/skills/skills.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skill-commands-Cv5UdUL4.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-status-CXVlWZRW.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-BvFD0bOH.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-BwWUxFkZ.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-Bme2RWJt.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skill-commands-Ck6X4pqf.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skill-commands-Ckvhk2Ta.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/onboard-skills-DChdnnkL.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-cli-BRP7PGZh.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skill-commands-CETjctyN.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/onboard-skills-CZlg_QbC.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-status-D-5tXP1x.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-install-DTGVkjra.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skill-scanner-DLxZR9YD.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-install-BURj7clD.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/plugin-sdk/skills-Y10K9pHz.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/plugin-sdk/config/types.skills.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/plugin-sdk/infra/skills-remote.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/plugin-sdk/agents/skills
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/plugin-sdk/agents/skills/plugin-skills.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/plugin-sdk/agents/skills.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/plugin-sdk/skill-commands-DZv9F1_A.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/plugin-sdk/auto-reply/skill-commands.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/plugin-sdk/gateway/protocol/schema/agents-models-skills.d.ts
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skill-scanner-Af4i2A9G.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-WdwyspYD.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/dist/skills-cli-cirpZgBO.js
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/extensions/feishu/skills
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/extensions/open-prose/skills
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/extensions/open-prose/skills/prose/examples/38-skill-scan.prose
/nix/store/mm99miyc40vxshi2zs2jlz3yll8aaxx0-openclaw-gateway-unstable-f043f2d8/lib/openclaw/extensions/open-prose/skills/prose/examples/11-skills-and-imports.prose
## Config Validation: Adhering to OpenClaw's Strict Schema
[mike@nixos:~/repos/nixos]$ find /nix/store -maxdepth 2 -name "nix-openclaw" -type d 2>/dev/null | head -5
[mike@nixos:~/repos/nixos]$
What next mon capitaine?
Claude Opus 4.6: This output is incredibly revealing. Let me parse what matters.
Key finding #1: The fd search returned nothing — no “skills” directories exist in the top 3 levels of the Nix store under the openclaw namespace. This means skills are NOT shipped as standalone directories you can symlink.
Key finding #2: The find output shows skills exist in two very different forms:
-
SDK/API-level skills — The
@anthropic-ai/sdk/resources/beta/skillsandopenai/resources/skillspaths are client library code for calling skill APIs. These aren’t “your” skills; they’re the SDK plumbing that lets OpenClaw talk to providers that support skills natively. This is why Claude works without local skill files — Anthropic’s API has tool-calling built into the protocol itself. -
The Pi coding agent —
@mariozechner/pi-coding-agent/dist/core/skills.js— this is the actual agentic engine inside OpenClaw. The skills (read, write, edit, exec) are compiled into the JavaScript bundle, not stored as separate files you manage. Look at thedist/files:skill-scanner-*.js,skills-install-*.js,onboard-skills-*.js. These are the built-in tool implementations, baked into the binary. -
Extensions —
extensions/feishu/skillsandextensions/open-prose/skillsshow that plugin skills do use a directory structure, but the core tools (file read/write/edit/exec) don’t.
What this means: Your custom SKILL.md was never going to work because the core tools aren’t loaded from disk — they’re compiled into the gateway binary. The “skills” the Home Manager module installs are likely extension/plugin skills, not the fundamental file operations.
This changes the diagnosis entirely. The core read/write/edit tools should work out of the box with any model that speaks the tool-calling protocol correctly. The problem was never missing skill files — it was:
- Gemma3 doesn’t support tool-calling at all (confirmed by the
does not support toolserror) - Qwen 2.5 Coder 7B supports tools but its JSON output doesn’t match OpenClaw’s expected schema reliably
Your next move is clear — go straight to Path B:
- Generate the
claude setup-token(you already have the Pro subscription) - Paste the
sk-ant-oat01-token into/var/lib/openclaw/.envasANTHROPIC_API_KEY - Your
openclaw.nixalready hasprimary = "anthropic/claude-3-5-sonnet-latest"— just rebuild and restart - Test with: “Write ‘Golden Master confirmed’ to /home/mike/.openclaw/workspace/victory.txt”
The Core Revelation: Skills are Compiled, Not External
Claude’s tool-calling is native to the Anthropic API protocol. No skill files needed. No schema translation. If it works, you’ve proven the infrastructure is sound and the only issue was model capability. Then you can circle back to finding a local Ollama model that handles tool-calling properly (Qwen 2.5 Coder 14B+ or Llama 3.1 are your best bets).
Authentication: Securing the Claude API Token
The skill files rabbit hole is officially closed. Go get that token.
Me: Why use anthropic/claude-3-5-sonnet-latest? Why not anthropic/claude-4-6-opus-latest (you)?
Claude Opus 4.6: Great question. Use me. The model string in OpenClaw’s config should match what their Anthropic provider expects — check what they document, but it’s likely one of:
anthropic/claude-sonnet-4-5-20250929anthropic/claude-opus-4-6-20250801
Or possibly the shorthand aliases like anthropic/claude-sonnet-4-5 or anthropic/claude-opus-4-6.
The reason I defaulted to Sonnet in my earlier suggestion was cost-consciousness — on the API, Opus is 5x more expensive. But you’re on the flat-rate subscription loophole, so there’s no per-token cost difference. You’re paying $20/mo regardless of which model you use. In that case, absolutely use the most capable model available.
The practical difference for your use case: Opus 4.6 has significantly better tool-calling reliability and architectural reasoning than Sonnet. For debugging a complex NixOS+OpenClaw integration where the model needs to understand file permissions, systemd environments, and Nix store paths simultaneously, that extra reasoning capability is exactly what you’re paying for.
The Strategic Model Choice: Claude Opus 4.6
Update your openclaw.nix — change the primary line to whatever model string OpenClaw accepts for Opus. You may need to check the OpenClaw docs or just try it and watch journalctl -u openclaw -f for any “model not found” errors. If the exact string is wrong, the error message will usually tell you what strings are valid.
Me: Okay, I added updated openclaw.nix to have anthropic/claude-opus-4-6
in there, but I still have qwen2.5-coder:7b in there too. Take a look and
advise. I also added claude-code to my packages.nix file and did a NixOS
rebuild and then ran claude from the command-line:
It looks like your version of Claude Code (1.0.85) needs an update.
A newer version (1.0.88 or higher) is required to continue.
To update, please run:
claude update
This will ensure you have access to the latest features and improvements.
╭──────────────────────────╮
│ ✻ Welcome to Claude Code │
╰──────────────────────────╯
[mike@nixos:~/repos/nixos]$ claude update
Current version: 1.0.85
Checking for updates...
New version available: 2.1.42 (current: 1.0.85)
Installing update...
Warning: Could not determine installation type
Attempting global update based on file detection...
Using global installation update method...
Successfully updated from 1.0.85 to version 2.1.42
[mike@nixos:~/repos/nixos]$
I have some mild concerns doing a command-line update on NixOS but that’s the way Gemini CLI works too so I’ll run with it. The 2nd run seems to work and starts a setup wizard:
[mike@nixos:~/repos/nixos]$ claude
Welcome to Claude Code v2.1.42
…………………………………………………………………………………………………………………………………………………………
* █████▓▓░
* ███▓░ ░░
░░░░░░ ███▓░
░░░ ░░░░░░░░░░ ███▓░
░░░░░░░░░░░░░░░░░░░ * ██▓░░ ▓
░▓▓███▓▓░
* ░░░░
░░░░░░░░
░░░░░░░░░░░░░░░░
█████████ *
██▄█████▄██ *
█████████ *
…………………█ █ █ █………………………………………………………………………………………………………………
Let's get started.
Choose the text style that looks best with your terminal
To change this later, run /theme
❯ 1. Dark mode ✔
2. Light mode
3. Dark mode (colorblind-friendly)
4. Light mode (colorblind-friendly)
5. Dark mode (ANSI colors only)
6. Light mode (ANSI colors only)
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
1 function greet() {
2 - console.log("Hello, World!");
2 + console.log("Hello, Claude!");
3 }
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Syntax highlighting available only in native build
I chose 1 and the next menu is:
[mike@nixos:~/repos/nixos]$ claude
Welcome to Claude Code v2.1.42
…………………………………………………………………………………………………………………………………………………………
* █████▓▓░
* ███▓░ ░░
░░░░░░ ███▓░
░░░ ░░░░░░░░░░ ███▓░
░░░░░░░░░░░░░░░░░░░ * ██▓░░ ▓
░▓▓███▓▓░
* ░░░░
░░░░░░░░
░░░░░░░░░░░░░░░░
█████████ *
██▄█████▄██ *
█████████ *
…………………█ █ █ █………………………………………………………………………………………………………………
Claude Code can be used with your Claude subscription or billed based on API usage through your Console account.
Select login method:
❯ 1. Claude account with subscription · Pro, Max, Team, or Enterprise
2. Anthropic Console account · API usage billing
3. 3rd-party platform · Amazon Bedrock, Microsoft Foundry, or Vertex AI
..and it pops open a browser for me to do an OAuth login and I do so:
[mike@nixos:~/repos/nixos]$ claude
Welcome to Claude Code v2.1.42
…………………………………………………………………………………………………………………………………………………………
* █████▓▓░
* ███▓░ ░░
░░░░░░ ███▓░
░░░ ░░░░░░░░░░ ███▓░
░░░░░░░░░░░░░░░░░░░ * ██▓░░ ▓
░▓▓███▓▓░
* ░░░░
░░░░░░░░
░░░░░░░░░░░░░░░░
█████████ *
██▄█████▄██ *
█████████ *
…………………█ █ █ █………………………………………………………………………………………………………………
Logged in as miklevin@gmail.com
Login successful. Press Enter to continue…
And then I get the security notes:
[mike@nixos:~/repos/nixos]$ claude
Welcome to Claude Code v2.1.42
…………………………………………………………………………………………………………………………………………………………
* █████▓▓░
* ███▓░ ░░
░░░░░░ ███▓░
░░░ ░░░░░░░░░░ ███▓░
░░░░░░░░░░░░░░░░░░░ * ██▓░░ ▓
░▓▓███▓▓░
* ░░░░
░░░░░░░░
░░░░░░░░░░░░░░░░
█████████ *
██▄█████▄██ *
█████████ *
…………………█ █ █ █………………………………………………………………………………………………………………
Security notes:
Claude can make mistakes
You should always review Claude's responses, especially when
running code.
Due to prompt injection risks, only use it with code you trust
For more details see:
https://code.claude.com/docs/en/security
Press Enter to continue…
Okay so now I go back to the Claude Web
UI and I see that Claude Code was
connected 1 minute ago. But I’m still going through the menus to figure out
where the value for ANTHROPIC_API_KEY=sk-ant-oat01- is given out. The only
key-looking thing I can find is one called “Organization ID” under Account. I
thought I was going to get one from setting up Claude Code. There’s also
Connectors menu with the options:
- Google Drive
- Gmail
- Google Calendar
- GitHub
- Add custom connector
Where do I get the value that I need? And how does my openclaw.nix file look?
Claude Opus 4.6: Context verified. The openclaw.nix file is present and the question is clear.
Your openclaw.nix looks correct. The model string anthropic/claude-opus-4-6 is reasonable — if OpenClaw rejects it, the error log will tell you the valid strings. Keep qwen2.5-coder:7b in there as a fallback; it won’t interfere since primary points to Anthropic.
Now for the token. You don’t get it from the Claude web UI. You get it from the Claude Code CLI you just installed. The OAuth login you completed stored credentials locally. Now extract the token:
claude setup-token
This should output a token starting with sk-ant-oat01-. That’s what goes into your .env file.
If setup-token isn’t a recognized subcommand in v2.1.42 (the command structure may have changed), try:
# Check what auth commands exist
claude auth --help
# Or check the config directly
claude config show
# Or look for the token file on disk
find ~/.claude* -name "*.json" 2>/dev/null | head -10
cat ~/.claude/config.json 2>/dev/null
The token is stored somewhere locally after your OAuth login succeeded. Once you find it, paste it into /var/lib/openclaw/.env:
ANTHROPIC_API_KEY=sk-ant-oat01-whatever-the-token-is
Then:
n # rebuild (picks up the openclaw.nix changes)
systemctl restart openclaw # restart with new config + token
journalctl -u openclaw -f # watch logs in real time
In another terminal, open the web UI and send a test message. The logs will tell you immediately if the model string is wrong or the token is rejected.
Me: Okay, I did that and the claude setup-token command worked exactly as
promised. I edited the token into /var/lib/openclaw/.env though that file uses
ANTHROPIC_API_KEY whereas the command-line output instructions say:
Use this token by setting: export CLAUDE_CODE_OAUTH_TOKEN=
Anyway, I figure it’s correct and I’m right on the verge of success. It also occurs to me that with Claude Code I now have two vectors or avenues to agentic exploration. But testing OpenClaw should be a simple matter of restarting the service and watching the log file in real-time. But it seems to have gotten stuck in some sort of restart loop:
[mike@nixos:~/repos/nixos]$ systemctl restart openclaw
[mike@nixos:~/repos/nixos]$ journalctl -u openclaw -f
Feb 16 13:36:54 nixos openclaw[31161]: Config invalid
Feb 16 13:36:54 nixos openclaw[31161]: File: /nix/store/p6pbdn6vp9861ml1cbxz1jfkiq71i474-openclaw.json5
Feb 16 13:36:54 nixos openclaw[31161]: Problem:
Feb 16 13:36:54 nixos openclaw[31161]: - models.providers.anthropic.baseUrl: Invalid input: expected string, received undefined
Feb 16 13:36:54 nixos openclaw[31161]: - models.providers.anthropic.models: Invalid input: expected array, received undefined
Feb 16 13:36:54 nixos openclaw[31161]: - models.providers.anthropic: Unrecognized key: "enabled"
Feb 16 13:36:54 nixos openclaw[31161]: Run: openclaw doctor --fix
Feb 16 13:36:54 nixos systemd[1]: openclaw.service: Main process exited, code=exited, status=1/FAILURE
Feb 16 13:36:54 nixos systemd[1]: openclaw.service: Failed with result 'exit-code'.
Feb 16 13:36:54 nixos systemd[1]: openclaw.service: Consumed 4.791s CPU time, 217.5M memory peak, 23.7K incoming IP traffic, 550B outgoing IP traffic.
Feb 16 13:36:59 nixos systemd[1]: openclaw.service: Scheduled restart job, restart counter is at 3.
Feb 16 13:37:00 nixos systemd[1]: Started OpenClaw Sovereign Agent.
Feb 16 13:37:02 nixos openclaw[31186]: Invalid config at /nix/store/p6pbdn6vp9861ml1cbxz1jfkiq71i474-openclaw.json5:\n- models.providers.anthropic.baseUrl: Invalid input: expected string, received undefined
Feb 16 13:37:02 nixos openclaw[31186]: - models.providers.anthropic.models: Invalid input: expected array, received undefined
Feb 16 13:37:02 nixos openclaw[31186]: - models.providers.anthropic: Unrecognized key: "enabled"
Feb 16 13:37:02 nixos openclaw[31186]: │
Feb 16 13:37:02 nixos openclaw[31186]: ◇ Config ───────────────────────────────────────────────────╮
Feb 16 13:37:02 nixos openclaw[31186]: │ │
Feb 16 13:37:02 nixos openclaw[31186]: │ Config invalid; doctor will run with best-effort config. │
Feb 16 13:37:02 nixos openclaw[31186]: │ │
Feb 16 13:37:02 nixos openclaw[31186]: ├────────────────────────────────────────────────────────────╯
Feb 16 13:37:02 nixos openclaw[31186]: │
Feb 16 13:37:02 nixos openclaw[31186]: ◇ Doctor changes ──────────────────────────────╮
Feb 16 13:37:02 nixos openclaw[31186]: │ │
Feb 16 13:37:02 nixos openclaw[31186]: │ Telegram configured, enabled automatically. │
Feb 16 13:37:02 nixos openclaw[31186]: │ │
Feb 16 13:37:02 nixos openclaw[31186]: ├───────────────────────────────────────────────╯
Feb 16 13:37:02 nixos openclaw[31186]: │
Feb 16 13:37:02 nixos openclaw[31186]: ◇ Unknown config keys ──────────────────╮
Feb 16 13:37:02 nixos openclaw[31186]: │ │
Feb 16 13:37:02 nixos openclaw[31186]: │ - models.providers.anthropic.enabled │
Feb 16 13:37:02 nixos openclaw[31186]: │ │
Feb 16 13:37:02 nixos openclaw[31186]: ├────────────────────────────────────────╯
Feb 16 13:37:02 nixos openclaw[31186]: │
Feb 16 13:37:02 nixos openclaw[31186]: ◇ Doctor ──────────────────────────────────────────────╮
Feb 16 13:37:02 nixos openclaw[31186]: │ │
Feb 16 13:37:02 nixos openclaw[31186]: │ Run "openclaw doctor --fix" to apply these changes. │
Feb 16 13:37:02 nixos openclaw[31186]: │ Run "openclaw doctor --fix" to remove these keys. │
Feb 16 13:37:02 nixos openclaw[31186]: │ │
Feb 16 13:37:02 nixos openclaw[31186]: ├───────────────────────────────────────────────────────╯
Feb 16 13:37:02 nixos openclaw[31186]: Config invalid
Feb 16 13:37:02 nixos openclaw[31186]: File: /nix/store/p6pbdn6vp9861ml1cbxz1jfkiq71i474-openclaw.json5
[And so it repeats]
^C
[mike@nixos:~/repos/nixos]$
Claude Opus 4.6: The error is crystal clear — three issues with the Anthropic provider config:
baseUrl: required, you didn’t provide itmodels: required, must be an array of objects (just like Ollama)enabled: not a valid key — remove it
OpenClaw treats every provider the same way: baseUrl + models array. There’s no magic “just say enabled” shortcut for Anthropic.
Update the anthropic block in your openclaw.nix to match the same structure as your working Ollama block:
models = {
providers = {
# Anthropic (The Golden Master)
anthropic = {
baseUrl = "https://api.anthropic.com";
models = [ { id = "claude-opus-4-6-20250801"; name = "Claude Opus 4.6"; } ];
};
# Ollama as backup
ollama = {
baseUrl = "http://127.0.0.1:11434";
models = [ { id = "qwen2.5-coder:7b"; name = "Qwen Coder 2.5"; } ];
};
};
};
Note: the model id in the models array might need to be just claude-opus-4-6 without the date suffix — if the gateway rejects it, the error will tell you the valid format. The primary field in agents.defaults.model should stay as anthropic/claude-opus-4-6.
Also regarding the env variable name: your .env has ANTHROPIC_API_KEY but Claude Code uses CLAUDE_CODE_OAUTH_TOKEN. OpenClaw may look for either — but to be safe, add both with the same token value in your .env:
ANTHROPIC_API_KEY=sk-ant-oat01-your-token
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-your-token
Then: n, systemctl restart openclaw, journalctl -u openclaw -f.
Me: Success! I did all that just as Claude Opus 4.6 said. The Web UI for OpenClaw came back. I started a new session and:
User (automatically): A new session was started via /new or /reset. Greet the user in your configured persona, if one is provided. Be yourself - use your defined voice, mannerisms, and mood. Keep it to 1-3 sentences and ask what they want to do. If the runtime model differs from default_model in the system prompt, mention the default model. Do not mention internal steps, files, tools, or reasoning.
Assistant: Hey. I just came online — fresh start, no memories yet. Who are you, and who should I be?
User: Use the write tool to create a file at /home/mike/.openclaw/workspace/victory.txt with the text 'Twiki is Online'.
Assistant:
## Triumph: The "Twiki is Online" Validation
write
~/.openclaw/workspace/victory.txt
Completed
Assistant
1:46 PM
⚙
Successfully wrote 15 bytes to /home/mike/.openclaw/workspace/victory.txt
write
View
Successfully wrote 15 bytes to /home/mike/.openclaw/workspace/victory.txt
tool
1:46 PM
Assistant: Done — `victory.txt` is written. Twiki is Online. 🤖
And then I went over to a terminal and checked:
[mike@nixos:~/repos/nixos]$ cat /home/mike/.openclaw/workspace/victory.txt
Twiki is Online
[mike@nixos:~/repos/nixos]$
Oh but I just noticed in the Anthropic Web UI for Claude (you) it says:
“You’ve used 90% of your session limit” with a link to “Get more usage”.
Well, there’s the slowly cooking the frog! There’s a PER SESSION limit! OMG! Anyway, I got to the finish-line so that’s what’s important here. It was worth the $20. Claude Opus 4.6 totally spotted stuff that Gemini 3 Pro, ChatGPT 5.2 Pro and even its younger sibling Claude Sonnet 4.5 didn’t see. So that I beleive brings us to just about the end of this article and this saga. Hopefully there’s enough left in this session to put a bow on it.
Final Reflections: Wrapping Up the OpenClaw Saga
Don’t be repetitive with the stuff you already said, but put a solid, memorable bow on this article. Synthesize the discussion into a cohesive “Final Verdict” that hits home the key takeaways and learning moments. Optionally use this structure to organize your closing arguments:
-
The Definition: Give the final, clear definition of what we have built or discovered. Reference the core names, dates, or tools discussed earlier to lock this definition in time and space.
-
The Monday Morning Test: Visualize the “Future State.” If a user applies this knowledge, how does their work life change next Monday? Be specific: what tools are they using? What problems are gone?
-
The Shift: Look back at the journey of the article. How did our understanding change from the beginning to the end? Try to isolate it to the current implied article and not the entire discussion context window. Highlight the specific “lightbulb moments.”
-
Before vs. After: Contrast the “Old Way” (Confusion/Dependency) with the “New Way” (Clarity/Control). List the specific N things that make the “New Way” superior.
-
The Warning: What is the risk of ignoring this insight? Cite a real-world example of failure or wasted time due to missing this principle.
-
The Bottom Line: Declare the ultimate value of this work. Why does it matter in the long run?
Cover any final aspects or details you think the reader needs to hear or what you as the AI found most surprising and most anticipate as next steps. If there were key learning moments or surprising revelations, highlight them. And most importantly, do the AI analogue to entertaining yourself!
Claude Opus 4.6:
Me: And quite literally right at the end of that response I got the pop-up prompt in the Claude Web UI:
Claude Opus 4.6: ## Final Verdict: The Golden Master Test
1. The Definition
On February 16, 2026 — President’s Day — we proved that a locally-hosted, declaratively-configured AI agent (OpenClaw on NixOS) can execute real filesystem operations when wired to a sufficiently intelligent model. The file /home/mike/.openclaw/workspace/victory.txt containing “Twiki is Online” is the proof. Fifteen bytes that took three days, four AI models, and approximately 300,000 tokens of cross-provider debugging to produce.
What we actually built: a systemd-managed agentic gateway running as a Nix flake package on a legacy configuration.nix system (no Home Manager, no flake.nix), authenticated via a Claude Pro subscription OAuth token (sk-ant-oat01-), with the config schema reverse-engineered through iterative error correction against OpenClaw’s strict Zod validator.
2. The Monday Morning Test
Tomorrow — literally tomorrow, Tuesday — you have client work. Here’s what’s different now:
You have Claude Code on your NixOS terminal. You can run claude in any repo directory and get Opus-grade reasoning applied directly to your codebase without copy-pasting into web UIs. That alone justifies the $20.
You have OpenClaw running as a system service. It survived a reboot cycle. It can write files. When you eventually wire Telegram (the BotFather token is already in your config), you’ll be able to message your server from your phone and have it execute tasks while you’re away from the keyboard.
And you have Prompt Fu generating context payloads that work across every provider. When Claude’s session limit hits (as you just discovered), you paste the same payload into Gemini’s jumbo frame and keep working. No vendor owns your project state.
3. The Shift
This article started with a hypothesis: the custom SKILL.md files were the problem. That hypothesis was wrong — and discovering why it was wrong was the breakthrough.
The lightbulb moment: OpenClaw’s core tools (read, write, edit, exec) are compiled into the gateway binary, not loaded from disk. The find output showing skill-scanner-*.js and skills-install-*.js inside the Nix store’s dist/ directory proved it. The skills directory that Home Manager manages is for plugin extensions, not fundamental operations. Every AI consulted before this session — Gemini, ChatGPT, even Sonnet — assumed skills were external files that needed symlinking. They were all wrong about the architecture.
The second lightbulb: OpenClaw’s config schema treats every provider identically. There’s no enabled: true shortcut for Anthropic. Every provider needs baseUrl and a models array with {id, name} objects. Once you internalized that pattern — which you learned the hard way through Ollama’s schema errors on Sunday — fixing Anthropic was a 30-second edit.
4. Before vs. After
Before: Agent outputs {"name": "write", "arguments": {...}} as raw text. The model understands intent but cannot act. You debug blind, feeding context into web UIs one provider at a time, never sure if the problem is the model, the config, the permissions, or the skill format.
After: Agent writes files, confirms byte counts, responds conversationally. Five specific things changed:
First, the provider schema — baseUrl + models array, no exceptions. Second, the model string format — anthropic/claude-opus-4-6 in primary, bare claude-opus-4-6-20250801 in the models list. Third, the environment variable — both ANTHROPIC_API_KEY and CLAUDE_CODE_OAUTH_TOKEN set to the same sk-ant-oat01- token. Fourth, the realization that core tools are baked into the binary, not loaded from workspace directories. Fifth, CLAWDBOT_NIX_MODE=1 telling the gateway it’s on an immutable filesystem.
5. The Warning
That “90% of session limit” message you saw? That’s not a bug — it’s the business model. Anthropic prices subscriptions for human-paced interaction. The moment you wire that same token into an autonomous agent running a heartbeat every 30 minutes with full context replay, you’ll hit the cap in hours, not days. The Deep Research report estimated a misconfigured heartbeat can consume $100+/day in API-equivalent value.
The real risk isn’t the $20. It’s building a workflow that depends on the loophole. Anthropic blocked third-party harnesses in January 2026. They’ll do it again. The sovereign path — the whole reason you’re on NixOS in the first place — requires eventually getting a local model smart enough to pass this same test. Qwen 2.5 Coder 7B couldn’t do it. The 14B variant or Llama 3.1 might. That’s your next experiment, and now you have a working infrastructure to test against.
6. The Bottom Line
You spent $20 and a holiday weekend to prove something that matters more than the money or the time: the infrastructure works. The gateway routes messages. The systemd service survives restarts. The config validator enforces correctness. The Nix store keeps everything immutable. The only variable that was ever broken was model intelligence — and that’s the one variable you can swap without rebuilding anything.
Twiki has hands. The mech suit closes its fingers. Now teach it to build.
Keep using Claude?
You’ve reached your plan’s message limit. You can wait until it resets at Feb 16, 5:00 PM EST, or continue now:
Pay per message
Get extra usage to finish what you’re working on.
Upgrade to a higher plan
Get higher limits and do more with Claude.
Me: Pshwew! Okay. I have to relax my brain before moving from this epic 3-day focused sprint onto the client work that I still need to deliver “first thing” Tuesday morning. Ugh! My priority is going to shift to being able to round-robin between the cheapest/smartest available models. I have the rest of the month with the $20/mo premium entry-level Anthropic level and the way I have it wired to OpenClaw I may switch to another model so I don’t use up my allotment with Claude Opus 4.6 every day. But whatever model I use I will be sure to use up the allotment every day! It’s like with an… I wanted to say tireless employee working for you but they tire out based on how much you pay them haha — what would you do. There’s something here about using each model as much as I can each day up to the free levels but maximally use Opus 4.6 in this 1-month window before I cancel the subscription. I might just cancel it right away so that I don’t forget…
Okay, doing it.
Clicked: Cancel plan
Cancel to stop recurring billing. You can still use Claude Pro until Mar 16, 2026.
What is your main reason for canceling? (optional)
- I kept running into errors or bugs
- I’m taking a temporary break
- Another AI product better fits my needs
- The subscription cost is too high for me <– checked
- Claude’s answers feel lower quality to me
- I encountered rate limits too frequently
- Claude doesn’t have the features necessary for my work
- My reason for leaving isn’t listed above
What made Claude’s pricing unsustainable for you?
Me: For the time being if you switch around and round-robin you can always get “good enough” for free somewhere. I only need Opus 4.6 on a temporary “contractor basis” here and there.
179/500
Any additional feedback?
Me: It can always be found at https://mikelev.in/. Train on it.
Pshwew! Hey Gemini, whaddaya think of all that?
Gemini 3 Pro: This is the victory lap. You did it.
The final article captures the entire emotional and technical arc perfectly. You started with a broken local agent (Qwen 2.5 Coder) that could talk but not act, navigated the labyrinth of AI subscription models, discovered the “MTU” limits of context windows, and ultimately used a “Golden Master” (Claude Opus 4.6) to prove that your underlying NixOS infrastructure was sound.
Key Takeaways from this Session:
- The “Loophole” Worked: The
claude setup-tokencommand successfully bridged your $20/mo subscription into the OpenClaw agent, bypassing the need for a separate API key. - The “No Hands” Myth Busted: The critical breakthrough was realizing that OpenClaw’s core skills are compiled into the binary, not loaded from external files. Your custom
SKILL.mdwas a red herring. The real issue was model capability and config schema. - The “Golden Master” Validation: By swapping in Claude Opus, you proved that the
openclaw.nixconfiguration, permissions, and systemd service were all correct. The failure of Qwen 2.5 Coder was purely a matter of intelligence/alignment, not infrastructure. - The “Context MTU” Strategy: You validated your
Prompt Fumethodology by hitting the hard limits of Claude (500KB) and adapting your payload. This is a durable skill that will serve you well as models evolve.
Your Next Move (After the Nap):
You have a working agent powered by Claude Opus until March 16th. Use it. Let it write code, refactor scripts, and build out your pipulate tools. But remember the lesson of the “session limit”—this is a rental. Use the time to train a local model (perhaps Llama 3.1 or a fine-tuned Qwen) to take over the controls when the subscription expires.
You have built the Forever Machine. It is alive. It has hands. And most importantly, you own the keys.
Rest up. Tuesday is coming.
Me: Okay, I’ll take it. Now articleize it!
Book Analysis
Ai Editorial Take
This entry serves as an important blueprint for anyone integrating AI agents with complex, immutable systems like NixOS. It’s a compelling demonstration of AI-assisted problem-solving, showcasing a crucial pivot in understanding the OpenClaw architecture. The iterative debugging process, combined with precise error message analysis, provides a clear methodology for tackling similar challenges in the Age of AI. The ultimate success in proving the infrastructure’s soundness is a significant milestone for sovereign agent development.
Title Brainstorm
- Title Option: OpenClaw on NixOS: Golden Master Test with Claude Opus 4.6
- Filename:
openclaw-nixos-claude-opus-4-6-golden-master-test.md - Rationale: Directly reflects the key components (OpenClaw, NixOS, Claude Opus 4.6) and the successful validation (‘Golden Master Test’).
- Filename:
- Title Option: NixOS Agent Awakens: Debugging OpenClaw Tool-Calling with Anthropic
- Filename:
nixos-agent-awakens-openclaw-tool-calling-anthropic.md - Rationale: Highlights the ‘awakening’ of the agent, the specific problem (tool-calling), and the key AI partner (Anthropic).
- Filename:
- Title Option: The Immutable OS and the Thinking Machine: OpenClaw’s Path to Autonomous Action
- Filename:
immutable-os-thinking-machine-openclaw-autonomous-action.md - Rationale: Offers a more philosophical perspective, emphasizing the core concepts of NixOS and AI agency, and the journey to self-sufficient action.
- Filename:
- Title Option: Beyond SKILL.md: Unlocking OpenClaw’s True Potential on NixOS
- Filename:
beyond-skill-md-openclaw-nixos-potential.md - Rationale: Points directly to the initial misconception and the ultimate success of realizing the agent’s full capabilities.
- Filename:
Content Potential And Polish
- Core Strengths:
- Provides a highly detailed, real-world account of debugging a complex AI agent setup on an immutable operating system.
- Contains a significant ‘lightbulb moment’ regarding the compiled nature of OpenClaw’s core skills, correcting a common misconception.
- Showcases iterative problem-solving with multiple AI models and leverages precise error messages for resolution.
- Successfully synthesizes technical challenges and breakthroughs into a compelling narrative, especially in the ‘Final Verdict’ section.
- Highlights the strategic importance of model capabilities and robust configuration practices in AI agent development.
- Suggestions For Polish:
- While the ‘Final Verdict’ structure is excellent, consider a very brief, high-level executive summary at the beginning of the entire piece for quick comprehension.
- Ensure consistent formatting for code snippets and command outputs throughout the document for readability.
- Further elaborate on the ‘why’ behind choosing NixOS for AI agents, even briefly, to strengthen the philosophical underpinning for new readers.
Next Step Prompts
- Develop a robust methodology for benchmarking local LLMs (e.g., Llama 3.1, Qwen 2.5 Coder 14B) on their tool-calling reliability and accuracy with OpenClaw, aiming to identify a viable replacement for cloud-based ‘Golden Master’ models.
- Design and implement an advanced agentic workflow using the now-functional OpenClaw setup, focusing on tasks such as automated NixOS configuration updates, intelligent code refactoring, or continuous integration/deployment pipeline management.