fix: repair skills symlinks broken by Windows git + auto-activate brave-search (#156)#169
Open
1aifanatic wants to merge 1 commit into
Open
fix: repair skills symlinks broken by Windows git + auto-activate brave-search (#156)#1691aifanatic wants to merge 1 commit into
1aifanatic wants to merge 1 commit into
Conversation
…ve-search Fixes stephengpope#156 ## Root Cause On Windows hosts with `git core.symlinks=false`, git checks out mode-120000 symlink entries (e.g. `.pi/skills`, `skills/active/browser-tools`) as plain text files whose content is the symlink target path. `bin/cli.js init()` copied these text files into the user's project via `fs.copyFileSync`, then its symlink-creation guard used `fs.existsSync()` which returned true for the text file — so the real symlink was silently skipped. The text files were committed to git as mode 100644. When the Docker agent later cloned the repo on Linux, `.pi/skills` was a text file, not a directory, causing the Pi agent to crash: ln: failed to create symbolic link '/job/.pi/skills/brave-search': No such file or directory The second issue: users set `USE_BRAVE_SEARCH=true` expecting it to enable the skill, but that env var is not processed anywhere. Brave Search is activated by a `skills/active/brave-search` symlink; if only `BRAVE_API_KEY` is set (via `AGENT_BRAVE_API_KEY` GitHub secret) the skill stayed inactive. ## Fix **bin/cli.js** — Add `isTextFileSymlink(filePath, expectedTarget)` that uses `lstatSync` to distinguish a real symlink from a text-file artifact. Before each `createDirLink()` call in `init()`, remove any text-file artifact so the symlink is always created correctly regardless of host OS. **entrypoint.sh (both pi-coding-agent-job and claude-code-job)** — Add a `repair_dir_symlink` function that runs after `git clone` inside the Docker container. It detects text-file artifacts (Windows git) and replaces them with proper symlinks, and creates any missing symlinks. Also auto-activates the brave-search skill when `BRAVE_API_KEY` is present in the environment but the `skills/active/brave-search` symlink is missing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #156 — Agent does not use tools (Brave Search, Date Tool) despite configuration
Two root causes identified and fixed:
Skills symlinks become text files on Windows git (
core.symlinks=false): git checks out mode-120000 symlink entries as plain text files.bin/cli.js init()copied these into the user's project, then the symlink-creation guard sawfs.existsSync() === truefor the text file and silently skipped creating the real symlink. Those text files were committed as mode 100644. When the Docker agent cloned the repo on Linux,.pi/skillswas a regular file — causing the Pi agent to crash:ln: failed to create symbolic link '/job/.pi/skills/brave-search': No such file or directoryBRAVE_API_KEYdoesn't auto-activate brave-search: Users setAGENT_BRAVE_API_KEYas a GitHub secret expecting the skill to work, but only the symlinkskills/active/brave-searchactivates it. Without running the setup wizard, the symlink never gets created.Changes
bin/cli.jsisTextFileSymlink(filePath, expectedTarget)— usesfs.lstatSyncto detect a text-file symlink artifact (Windows git) vs a real symlink or directoryinit(), callisTextFileSymlinkbefore eachcreateDirLinkcall; remove the text-file artifact if found so the real symlink is always createdtemplates/docker/pi-coding-agent-job/entrypoint.shtemplates/docker/claude-code-job/entrypoint.shrepair_dir_symlinkfunction: runs aftergit clone, detects text-file artifacts and replaces them with properln -sfsymlinks; also creates any symlinks that are missing entirelybrave-searchskill whenBRAVE_API_KEYis present in the environment butskills/active/brave-searchsymlink is absent (BRAVE_API_KEYis injected fromAGENT_BRAVE_API_KEYGitHub secret via the existing SECRETS eval pipeline)Test Plan
isTextFileSymlinkunit-tested across 6 cases: exact match, wrong content, directory, missing file, trailing newline, real symlink — all passinit()flow simulated in Node.js: text-file artifacts replaced by real symlinks end-to-endbash -npasses on both entrypointsrepair_dir_symlinklogic verified: only removes files whose content exactly matches the expected symlink target — unrelated files are left untouchedBackward Compatibility
isTextFileSymlinkreturns false → no change in behaviorrepair_dir_symlinkin entrypoints: no-ops on valid symlinks ([ -L ]check passes, function returns immediately)🤖 Generated with Claude Code