Skip to content
Merged
1 change: 1 addition & 0 deletions .local-binaries.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
~/ghq/github.com/Dicklesworthstone/coding_agent_session_search/target/release/cass
~/ghq/github.com/Dicklesworthstone/destructive_command_guard/target/release/dcg
~/ghq/github.com/Dicklesworthstone/ultimate_bug_scanner/ubs
~/ghq/github.com/dlorenc/multiclaude/multiclaude
~/ghq/github.com/nwiizo/ccswarm/target/release/ccswarm
~/ghq/github.com/steveyegge/beads/bd
~/ghq/github.com/steveyegge/gastown/gt
2 changes: 1 addition & 1 deletion config/codex/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ model_provider = "ollama"
model = "openai/gpt-oss-120b"
model_provider = "lmstudio"

[profiles.glm-4.7-flash]
[profiles.glm-4-7-flash]
model = "zai-org/glm-4.7-flash"

Copilot AI Jan 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The profile name was changed to 'glm-4-7-flash' (with hyphens), but the model name itself is still 'zai-org/glm-4.7-flash' (with a dot). This inconsistency could cause confusion. Consider updating the model name to use hyphens consistently, i.e., 'zai-org/glm-4-7-flash'.

Suggested change
model = "zai-org/glm-4.7-flash"
model = "zai-org/glm-4-7-flash"

Copilot uses AI. Check for mistakes.
model_provider = "lmstudio"
20 changes: 16 additions & 4 deletions home-manager/modules/cargo-globals/install-cargo-globals.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ if ! command -v jq &>/dev/null; then
fi

# Parse dependencies from standard Cargo.toml format
DEPS=$(dasel -f "$CARGO_TOML" -r toml -w json 'dependencies' 2>/dev/null | jq -r 'to_entries[] | "\(.key)@\(.value)"' 2>/dev/null || true)
DEPS=$(dasel -f "$CARGO_TOML" -r toml -w json 'dependencies' 2>/dev/null | jq -r 'to_entries[] | "\(.key)@\(.value.version // .value)"' 2>/dev/null || true)

if [ -z "$DEPS" ]; then
echo "No dependencies found in Cargo.toml"
Expand All @@ -39,13 +39,25 @@ fi

# Get currently installed packages (cargo's native cache)
INSTALLED=$(cargo install --list 2>/dev/null || true)
declare -A INSTALLED_MAP=()

echo "$DEPS" | while read -r pkg; do
while read -r line; do
case "$line" in
"" | " "*) continue ;;
*)
if [[ $line =~ ^([^[:space:]]+)[[:space:]]v([^:]+): ]]; then
INSTALLED_MAP["${BASH_REMATCH[1]}"]="${BASH_REMATCH[2]}"
fi
;;
esac
done <<<"$INSTALLED"

while read -r pkg; do
CRATE=$(echo "$pkg" | cut -d'@' -f1)
VERSION=$(echo "$pkg" | cut -d'@' -f2)
Comment on lines 56 to 57

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better performance and to follow shell scripting best practices, consider using shell parameter expansion to extract the crate name and version instead of forking cut twice in a loop. This avoids creating subshells for each dependency.

Suggested change
CRATE=$(echo "$pkg" | cut -d'@' -f1)
VERSION=$(echo "$pkg" | cut -d'@' -f2)
CRATE=${pkg%@*}
VERSION=${pkg#*@}

if [ -n "$CRATE" ]; then
# Check if already installed at this version (format: "crate_name v1.2.3:")
if echo "$INSTALLED" | grep -q "^${CRATE} v${VERSION}:"; then
if [ "${INSTALLED_MAP[$CRATE]:-}" = "$VERSION" ]; then
echo "$CRATE@$VERSION already installed, skipping"
continue
fi
Expand All @@ -54,6 +66,6 @@ echo "$DEPS" | while read -r pkg; do
cargo install "$CRATE" --version "$VERSION" 2>/dev/null ||
echo "Failed to install $CRATE@$VERSION, skipping..."
fi
done
done <<<"$DEPS"

echo "cargo globals check complete"
9 changes: 7 additions & 2 deletions home-manager/modules/clawdbot/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,18 @@ lib.mkIf (!env.isCI) {
);

# Auto-start Clawdbot.app on login (galactica only)
# App is installed to /Applications/Nix Apps/ via nix-darwin
# Use /usr/bin/open to launch the app properly with full bundle context,
# rather than running the binary directly which breaks Bundle.module lookups
launchd.agents.clawdbot-app = lib.mkIf (pkgs.stdenv.isDarwin && host.isGalactica) {
enable = true;
config = {
Label = "com.clawdbot.app";
ProgramArguments = [
"/Applications/Clawdbot.app/Contents/MacOS/Clawdbot"
"open"

Copilot AI Jan 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using 'open' as a direct command in ProgramArguments may not work as expected in launchd. The 'open' command typically requires a full path. Consider using '/usr/bin/open' instead of just 'open' to ensure launchd can find and execute the command reliably.

Suggested change
"open"
"/usr/bin/open"

Copilot uses AI. Check for mistakes.
"-a"
"/Applications/Clawdbot.app"
"--args"
"--launched-from-launchd"
];
RunAtLoad = true;
KeepAlive = false;
Expand Down
9 changes: 9 additions & 0 deletions home-manager/programs/fish/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
direnv hook fish | source
'';
loginShellInit = ''
if test -f /opt/homebrew/bin/brew
eval "$(/opt/homebrew/bin/brew shellenv)"
end

fish_add_path -p ~/.local/bin
fish_add_path -p ~/.bun/bin
fish_add_path -p ~/.cargo/bin
Expand All @@ -41,6 +45,11 @@
_hm_load_env_file
set fish_greeting
set fish_theme dracula

if test -f /opt/homebrew/bin/brew
eval "$(/opt/homebrew/bin/brew shellenv)"
end
Comment on lines +49 to +51

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Homebrew environment setup is duplicated in both loginShellInit and interactiveShellInit. Since a login shell is typically also interactive, this can lead to eval "$(/opt/homebrew/bin/brew shellenv)" being executed twice, which is unnecessary and can slightly slow down shell startup.

To avoid this duplication, you could move this block to shellInit (around line 25), which is sourced only once for all shell sessions. This would ensure the Homebrew environment is set up correctly and efficiently for all shell types.


Comment on lines +49 to +52

Copilot AI Jan 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Homebrew environment loading is duplicated in both loginShellInit and interactiveShellInit. This could lead to unnecessary overhead and potential issues. The brew shellenv should typically only be loaded once, preferably in loginShellInit.

Suggested change
if test -f /opt/homebrew/bin/brew
eval "$(/opt/homebrew/bin/brew shellenv)"
end

Copilot uses AI. Check for mistakes.
fish_add_path -p ~/.local/bin
fish_add_path -p ~/.bun/bin
fish_add_path -p ~/.cargo/bin
Expand Down
2 changes: 1 addition & 1 deletion home-manager/programs/fish/functions/_coxe_function.fish
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ function _coxe_function --description "Run Codex with a free-form prompt"
codex --model 'gpt-5.2-codex' --full-auto -c model_reasoning_summary_format=experimental
else
set -l prompt (string join " " -- $argv)
codex --model 'gpt-5.2-codex' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt"
codex exec --model 'gpt-5.2-codex' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt"
end
end
2 changes: 1 addition & 1 deletion home-manager/programs/fish/functions/_coxeh_function.fish
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ function _coxeh_function --description "Run Codex headlessly with a prompted inp
return 1
end

codex --model 'gpt-5.2-codex' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt"
codex exec --model 'gpt-5.2-codex' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt"
end
8 changes: 4 additions & 4 deletions home-manager/programs/fish/functions/_coxel_function.fish
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
function _coxel_function --description "Run Codex with a free-form prompt using the local glm-4.7-flash model"
# Run Codex with a free-form prompt (spaces allowed) using the local glm-4.7-flash model
function _coxel_function --description "Run Codex with a free-form prompt using the local glm-4-7-flash model"
# Run Codex with a free-form prompt (spaces allowed) using the local glm-4-7-flash model
# Usage: cxel [<prompt words...>]

if test (count $argv) -eq 0
codex --profile 'glm-4.7-flash' --full-auto -c model_reasoning_summary_format=experimental
codex --profile 'glm-4-7-flash' --full-auto -c model_reasoning_summary_format=experimental
else
set -l prompt (string join " " -- $argv)
codex --profile 'glm-4.7-flash' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt"
codex exec --profile 'glm-4-7-flash' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt"
end
end
4 changes: 2 additions & 2 deletions home-manager/programs/fish/functions/_coxelh_function.fish
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function _coxelh_function --description "Run Codex headlessly with local glm-4.7-flash model"
function _coxelh_function --description "Run Codex headlessly with local glm-4-7-flash model"
# Prompt for input and run Codex with local model
# Usage: coxelh

Expand All @@ -8,5 +8,5 @@ function _coxelh_function --description "Run Codex headlessly with local glm-4.7
return 1
end

codex --profile 'glm-4.7-flash' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt"
codex exec --profile 'glm-4-7-flash' --full-auto -c model_reasoning_summary_format=experimental -- "$prompt"
end
5 changes: 5 additions & 0 deletions home-manager/programs/zsh/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@

# envExtra goes to .zshenv (always sourced)
envExtra = ''
# Load Homebrew environment
if [ -f /opt/homebrew/bin/brew ]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
fi

# Set XDG_RUNTIME_DIR on Linux for consistent socket paths (e.g., zellij)
if [ "$(uname)" = "Linux" ]; then
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
Expand Down
6 changes: 4 additions & 2 deletions nix-darwin/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ in
time
];

# Clawdbot.app: Symlink to /Applications/ (galactica only)
# Clawdbot.app: Install to /Applications/ (galactica only)
# Use ditto instead of cp -R to preserve all macOS bundle attributes,
# extended attributes, and resource forks required for Bundle.module lookups
system.activationScripts.postActivation.text = lib.mkIf (!env.isCI && host.isGalactica) ''
echo "Installing Clawdbot.app to /Applications..."
rm -rf /Applications/Clawdbot.app
cp -R ${pkgs.clawdbot-app}/Applications/Clawdbot.app /Applications/
ditto "${pkgs.clawdbot-app}/Applications/Clawdbot.app" /Applications/Clawdbot.app
'';
}
2 changes: 1 addition & 1 deletion overlays/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ in
echo "Clawdbot.app not found in $src" >&2
exit 1
fi
cp -R "$app_path" "$out/Applications/Clawdbot.app"
cp -pR "$app_path" "$out/Applications/Clawdbot.app"

Copilot AI Jan 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While cp -pR preserves permissions and timestamps, it doesn't preserve macOS extended attributes and resource forks which are critical for Bundle.module lookups. Consider using ditto here as well (similar to the fix in nix-darwin/default.nix) or using rsync -a --xattrs to ensure all macOS bundle attributes are preserved.

Suggested change
cp -pR "$app_path" "$out/Applications/Clawdbot.app"
ditto "$app_path" "$out/Applications/Clawdbot.app"

Copilot uses AI. Check for mistakes.
'';
meta = with prev.lib; {
description = "Clawdbot macOS app bundle";
Expand Down
20 changes: 18 additions & 2 deletions scripts/update-local-binaries.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ get_repo_dir() {
done

# Fallback: assume 4 levels deep from ghq root (github.com/owner/repo)
echo "$binary_path" | sed -E 's|(~/ghq/[^/]+/[^/]+/[^/]+)/.*|\1|' | sed "s|~|$HOME|"
# Note: binary_path is already expanded, so match against the full path
echo "$binary_path" | sed -E 's|(.*/ghq/[^/]+/[^/]+/[^/]+)/.*|\1|'
}

# Get repo name for display
Expand Down Expand Up @@ -107,8 +108,23 @@ build_repo() {
else
return 1
fi
elif [ -f "$repo_dir/go.mod" ]; then
# Go project: build ./cmd/{repo_name} if it exists, otherwise build root
if [ -d "$repo_dir/cmd/$repo_name" ]; then
if (cd "$repo_dir" && go build "./cmd/$repo_name" 2>&1); then

Copilot AI Jan 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The go build command for cmd/{repo_name} pattern doesn't specify an output location, which means the binary will be placed in the cmd/{repo_name} directory rather than at the repository root where other build systems typically place their outputs. Consider using 'go build -o {repo_name} ./cmd/{repo_name}' to place the output binary at the repository root for consistency with Rust and Make builds.

Suggested change
if (cd "$repo_dir" && go build "./cmd/$repo_name" 2>&1); then
if (cd "$repo_dir" && go build -o "$repo_name" "./cmd/$repo_name" 2>&1); then

Copilot uses AI. Check for mistakes.
return 0
else
return 1
fi
else
if (cd "$repo_dir" && go build 2>&1); then
return 0
else
return 1
fi
Comment on lines +113 to +124

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for building a Go project can be refactored to be more concise and less repetitive. You can determine the build path first and then have a single go build command.

Suggested change
if [ -d "$repo_dir/cmd/$repo_name" ]; then
if (cd "$repo_dir" && go build "./cmd/$repo_name" 2>&1); then
return 0
else
return 1
fi
else
if (cd "$repo_dir" && go build 2>&1); then
return 0
else
return 1
fi
local build_path="."
if [ -d "$repo_dir/cmd/$repo_name" ]; then
build_path="./cmd/$repo_name"
fi
if (cd "$repo_dir" && go build "$build_path" 2>&1); then
return 0
else
return 1
fi

fi
else
log_warn " No Makefile or Cargo.toml found, skipping build"
log_warn " No Makefile, Cargo.toml, or go.mod found, skipping build"
return 0
fi
}
Expand Down
10 changes: 10 additions & 0 deletions spec/cargo_globals_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ When run bash -c "grep 'dasel' '$SCRIPT'"
The output should include 'dasel'
End

It 'supports table-style dependency versions'
When run bash -c "grep 'version // .value' '$SCRIPT'"
The output should include 'version // .value'
End

It 'uses cargo install with version'
When run bash -c "grep 'cargo install' '$SCRIPT'"
The output should include '--version'
Expand All @@ -67,5 +72,10 @@ It 'parses dependencies section'
When run bash -c "grep 'dependencies' '$SCRIPT'"
The output should include 'dependencies'
End

It 'builds an installed version map'
When run bash -c "grep 'INSTALLED_MAP' '$SCRIPT'"
The output should include 'INSTALLED_MAP'
End
End
End
2 changes: 1 addition & 1 deletion spec/spec_helper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ spec_helper_precheck() {
}

spec_helper_configure() {
import 'support/custom_matcher'
import 'test_helpers'
}
File renamed without changes.
47 changes: 44 additions & 3 deletions spec/update_local_binaries_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,23 @@ It 'runs cargo build --release for Rust projects'
When run bash -c "grep 'cargo build --release' '$SCRIPT'"
The output should include 'cargo build --release'
End

It 'detects go.mod for go build'
When run bash -c "grep 'go.mod' '$SCRIPT'"
The output should include 'go.mod'
End

It 'runs go build for Go projects'
When run bash -c "grep 'go build' '$SCRIPT'"
The output should include 'go build'
End

It 'supports go build ./cmd/{repo_name} pattern'
# shellcheck disable=SC2016
When run bash -c 'grep "cmd/\$repo_name" '"'$SCRIPT'"
# shellcheck disable=SC2016
The output should include 'cmd/$repo_name'
End
End

Describe 'git operations'
Expand Down Expand Up @@ -297,7 +314,8 @@ get_repo_dir() {
done

# Fallback: assume 4 levels deep from ghq root (github.com/owner/repo)
echo "$binary_path" | sed -E 's|(~/ghq/[^/]+/[^/]+/[^/]+)/.*|\1|' | sed "s|~|$HOME|"
# Note: binary_path is already expanded, so match against the full path
echo "$binary_path" | sed -E 's|(.*/ghq/[^/]+/[^/]+/[^/]+)/.*|\1|'
}

# Test with actual path
Expand Down Expand Up @@ -362,8 +380,15 @@ build_repo() {
elif [ -f "$repo_dir/Cargo.toml" ]; then
echo "Would run: cargo build --release"
return 0
elif [ -f "$repo_dir/go.mod" ]; then
if [ -d "$repo_dir/cmd/$repo_name" ]; then
echo "Would run: go build ./cmd/$repo_name"
else
echo "Would run: go build"
fi
return 0
else
log_warn " No Makefile or Cargo.toml found, skipping build"
log_warn " No Makefile, Cargo.toml, or go.mod found, skipping build"
return 0
fi
}
Expand Down Expand Up @@ -396,10 +421,26 @@ The output should include 'Building rust-repo'
The output should include 'cargo build --release'
End

It 'detects go.mod and uses go build'
mkdir -p "$TEMP_DIR/go-repo"
touch "$TEMP_DIR/go-repo/go.mod"
When run bash "$TEMP_SCRIPT" "$TEMP_DIR/go-repo"
The output should include 'Building go-repo'
The output should include 'go build'
End

It 'uses go build ./cmd/{repo_name} when cmd dir exists'
mkdir -p "$TEMP_DIR/multiclaude/cmd/multiclaude"
touch "$TEMP_DIR/multiclaude/go.mod"
When run bash "$TEMP_SCRIPT" "$TEMP_DIR/multiclaude"
The output should include 'Building multiclaude'
The output should include 'go build ./cmd/multiclaude'
End

It 'warns when no build system found'
mkdir -p "$TEMP_DIR/unknown-repo"
When run bash "$TEMP_SCRIPT" "$TEMP_DIR/unknown-repo"
The output should include 'No Makefile or Cargo.toml found'
The output should include 'No Makefile, Cargo.toml, or go.mod found'
End
End

Expand Down
Loading