From 349b54ae9ef8a8d2991394632fce224cae63eae0 Mon Sep 17 00:00:00 2001 From: gavrielc Date: Wed, 25 Mar 2026 23:54:05 +0200 Subject: [PATCH] fix(add-statusbar): derive log path from binary location, fix SKILL.md - statusbar.swift: derive project root from binary location instead of hardcoding ~/Documents/Projects/nanoclaw - SKILL.md: remove references to non-existent apply-skill.ts, compile directly from skill directory using ${CLAUDE_SKILL_DIR} - SKILL.md: add xattr -cr step for Gatekeeper on macOS Sequoia+ - Remove unused manifest.yaml Co-Authored-By: tomermesser Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/skills/add-statusbar/SKILL.md | 51 ++++++++----------- .../add-statusbar/add/src/statusbar.swift | 10 +++- .claude/skills/add-statusbar/manifest.yaml | 10 ---- 3 files changed, 31 insertions(+), 40 deletions(-) delete mode 100644 .claude/skills/add-statusbar/manifest.yaml diff --git a/.claude/skills/add-statusbar/SKILL.md b/.claude/skills/add-statusbar/SKILL.md index c0f343c..07012bf 100644 --- a/.claude/skills/add-statusbar/SKILL.md +++ b/.claude/skills/add-statusbar/SKILL.md @@ -1,11 +1,12 @@ --- name: add-statusbar -description: Add a macOS menu bar status indicator for NanoClaw. Shows a ⚡ icon with a green/red dot indicating whether NanoClaw is running, with Start, Stop, and Restart controls. macOS only. +description: Add a macOS menu bar status indicator for NanoClaw. Shows a bolt icon with a green/red dot indicating whether NanoClaw is running, with Start, Stop, and Restart controls. macOS only. --- # Add macOS Menu Bar Status Indicator -Adds a persistent menu bar icon that shows NanoClaw's running status and lets the user start, stop, or restart the service — similar to how Docker Desktop appears in the menu bar. +Adds a persistent menu bar icon that shows NanoClaw's running status and lets the user +start, stop, or restart the service — similar to how Docker Desktop appears in the menu bar. **macOS only.** Requires Xcode Command Line Tools (`swiftc`). @@ -39,45 +40,38 @@ If not found, tell the user: launchctl list | grep com.nanoclaw.statusbar ``` -If it returns a PID (not `-`), tell the user it's already installed and skip to Phase 4 (Verify). +If it returns a PID (not `-`), tell the user it's already installed and skip to Phase 3 (Verify). -## Phase 2: Apply Code Changes - -### Initialize skills system (if needed) - -If `.nanoclaw/` directory doesn't exist yet: - -```bash -npx tsx scripts/apply-skill.ts --init -``` - -### Apply the skill - -```bash -npx tsx scripts/apply-skill.ts .claude/skills/add-statusbar -``` - -This copies `src/statusbar.swift` into the project and records the application in `.nanoclaw/state.yaml`. - -## Phase 3: Compile and Install +## Phase 2: Compile and Install ### Compile the Swift binary +The source lives in the skill directory. Compile it into `dist/`: + ```bash -swiftc -O -o dist/statusbar src/statusbar.swift +mkdir -p dist +swiftc -O -o dist/statusbar "${CLAUDE_SKILL_DIR}/add/src/statusbar.swift" ``` -This produces a small (~55KB) native binary at `dist/statusbar`. +This produces a small native binary at `dist/statusbar`. + +On macOS Sequoia or later, clear the quarantine attribute so the binary can run: + +```bash +xattr -cr dist/statusbar +``` ### Create the launchd plist -Determine the absolute project root: +Determine the absolute project root and home directory: ```bash pwd +echo $HOME ``` -Create `~/Library/LaunchAgents/com.nanoclaw.statusbar.plist`, substituting the actual values for `{PROJECT_ROOT}` and `{HOME}`: +Create `~/Library/LaunchAgents/com.nanoclaw.statusbar.plist`, substituting the actual values +for `{PROJECT_ROOT}` and `{HOME}`: ```xml @@ -113,7 +107,7 @@ Create `~/Library/LaunchAgents/com.nanoclaw.statusbar.plist`, substituting the a launchctl load ~/Library/LaunchAgents/com.nanoclaw.statusbar.plist ``` -## Phase 4: Verify +## Phase 3: Verify ```bash launchctl list | grep com.nanoclaw.statusbar @@ -123,7 +117,7 @@ The first column should show a PID (not `-`). Tell the user: -> The ⚡ icon should now appear in your macOS menu bar. Click it to see NanoClaw's status and control the service. +> The bolt icon should now appear in your macOS menu bar. Click it to see NanoClaw's status and control the service. > > - **Green dot** — NanoClaw is running > - **Red dot** — NanoClaw is stopped @@ -136,5 +130,4 @@ Tell the user: launchctl unload ~/Library/LaunchAgents/com.nanoclaw.statusbar.plist rm ~/Library/LaunchAgents/com.nanoclaw.statusbar.plist rm dist/statusbar -rm src/statusbar.swift ``` diff --git a/.claude/skills/add-statusbar/add/src/statusbar.swift b/.claude/skills/add-statusbar/add/src/statusbar.swift index 6fff79a..2577380 100644 --- a/.claude/skills/add-statusbar/add/src/statusbar.swift +++ b/.claude/skills/add-statusbar/add/src/statusbar.swift @@ -7,6 +7,14 @@ class StatusBarController: NSObject { private let plistPath = "\(NSHomeDirectory())/Library/LaunchAgents/com.nanoclaw.plist" + /// Derive the NanoClaw project root from the binary location. + /// The binary is compiled to {project}/dist/statusbar, so the parent of + /// the parent directory is the project root. + private static let projectRoot: String = { + let binary = URL(fileURLWithPath: CommandLine.arguments[0]).resolvingSymlinksInPath() + return binary.deletingLastPathComponent().deletingLastPathComponent().path + }() + override init() { super.init() setupStatusItem() @@ -108,7 +116,7 @@ class StatusBarController: NSObject { } @objc private func viewLogs() { - let logPath = "\(NSHomeDirectory())/Documents/Projects/nanoclaw/logs/nanoclaw.log" + let logPath = "\(StatusBarController.projectRoot)/logs/nanoclaw.log" NSWorkspace.shared.open(URL(fileURLWithPath: logPath)) } diff --git a/.claude/skills/add-statusbar/manifest.yaml b/.claude/skills/add-statusbar/manifest.yaml deleted file mode 100644 index 0d7d720..0000000 --- a/.claude/skills/add-statusbar/manifest.yaml +++ /dev/null @@ -1,10 +0,0 @@ -skill: statusbar -version: 1.0.0 -description: "macOS menu bar status indicator — shows NanoClaw running state with start/stop/restart controls" -core_version: 0.1.0 -adds: - - src/statusbar.swift -modifies: [] -structured: {} -conflicts: [] -depends: []