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:

  1. SDK/API-level skills — The @anthropic-ai/sdk/resources/beta/skills and openai/resources/skills paths 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.

  2. 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 the dist/ files: skill-scanner-*.js, skills-install-*.js, onboard-skills-*.js. These are the built-in tool implementations, baked into the binary.

  3. Extensionsextensions/feishu/skills and extensions/open-prose/skills show 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:

  1. Gemma3 doesn’t support tool-calling at all (confirmed by the does not support tools error)
  2. 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:

  1. Generate the claude setup-token (you already have the Pro subscription)
  2. Paste the sk-ant-oat01- token into /var/lib/openclaw/.env as ANTHROPIC_API_KEY
  3. Your openclaw.nix already has primary = "anthropic/claude-3-5-sonnet-latest" — just rebuild and restart
  4. 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-20250929
  • anthropic/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:

  1. baseUrl: required, you didn’t provide it
  2. models: required, must be an array of objects (just like Ollama)
  3. 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:

  1. 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.

  2. 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?

  3. 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.”

  4. 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.

  5. 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.

  6. 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:

  1. The “Loophole” Worked: The claude setup-token command successfully bridged your $20/mo subscription into the OpenClaw agent, bypassing the need for a separate API key.
  2. 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.md was a red herring. The real issue was model capability and config schema.
  3. The “Golden Master” Validation: By swapping in Claude Opus, you proved that the openclaw.nix configuration, permissions, and systemd service were all correct. The failure of Qwen 2.5 Coder was purely a matter of intelligence/alignment, not infrastructure.
  4. The “Context MTU” Strategy: You validated your Prompt Fu methodology 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’).
  • 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).
  • 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.
  • 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.

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.