Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a44a387
feat(dock): add codex-app between chatgpt and claude
shunkakinoki Apr 17, 2026
12204f3
chore: fix formatting in config and update dotagents submodule
shunkakinoki Apr 17, 2026
970abd2
feat(decafinate): add macOS support with caffeinate and PID-based ser…
shunkakinoki Apr 17, 2026
0867b73
fix(docker-postgres): disable postgres service on galactica and matic
shunkakinoki Apr 17, 2026
5eebaff
feat(docker-postgres): guard service with isGalactica/isMatic
shunkakinoki Apr 17, 2026
5e372cd
fix(uv-globals): use wrapper scripts instead of symlinks for per-tool…
shunkakinoki Apr 17, 2026
2cb5436
fix(docker-postgres): use module path instead of eager import
shunkakinoki Apr 17, 2026
db045d9
fix(ollama): guard service with isGalactica/isMatic and bind to local…
shunkakinoki Apr 17, 2026
0c58107
fix(docker): enable nix sandbox in Dockerfile
shunkakinoki Apr 17, 2026
ff9779e
fix(paperclip): bind to 127.0.0.1 instead of 0.0.0.0
shunkakinoki Apr 17, 2026
8062ada
feat(secure-dotenv): enforce 600 permissions on .env files
shunkakinoki Apr 17, 2026
9cfd6ed
fix(uv-globals): use portable python3 fallback in wrapper
shunkakinoki Apr 17, 2026
9233cd7
fix(uv-globals): rm stale symlinks before writing python3 wrappers
shunkakinoki Apr 17, 2026
187310a
chore: update
shunkakinoki Apr 17, 2026
8099906
chore: update
shunkakinoki Apr 17, 2026
f7816de
chore: update
shunkakinoki Apr 18, 2026
0ad62ae
Merge remote-tracking branch 'refs/remotes/origin/feat/dock-add-codex…
shunkakinoki Apr 18, 2026
d629b3c
Merge remote-tracking branch 'origin/main' into feat/dock-add-codex
shunkakinoki Apr 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
ARG USER_UID=1001
ARG USER_GID=$USER_UID
ARG COMMIT_SHA=main
ARG GITHUB_TOKEN

Check warning on line 30 in Dockerfile

View workflow job for this annotation

GitHub Actions / docker-build-push (linux/amd64, amd64, ubuntu-latest)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "GITHUB_TOKEN") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/

Check warning on line 30 in Dockerfile

View workflow job for this annotation

GitHub Actions / docker-build-push (linux/arm64, arm64, ubuntu-24.04-arm)

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "GITHUB_TOKEN") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG GITHUB_PR
ENV GITHUB_PR=${GITHUB_PR}

Expand All @@ -48,7 +48,7 @@
echo "trusted-users = root $USER" > /etc/nix/nix.conf && \
echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf && \
echo "filter-syscalls = false" >> /etc/nix/nix.conf && \
echo "sandbox = false" >> /etc/nix/nix.conf && \
echo "sandbox = true" >> /etc/nix/nix.conf && \
if [ -n "$GITHUB_TOKEN" ]; then \
echo "access-tokens = github.com=$GITHUB_TOKEN" >> /etc/nix/nix.conf ; \
fi
Expand Down
1 change: 1 addition & 0 deletions config/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ in
./k3s
./karabiner
./llm
./mempalace
./obsidian
./omp
./openclaw
Expand Down
3 changes: 3 additions & 0 deletions config/mempalace/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"palace": "/home/ubuntu/ghq/github.com/shunkakinoki/wiki"
}
7 changes: 7 additions & 0 deletions config/mempalace/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{ ... }:
{
home.file.".mempalace/config.json" = {
source = ./config.json;
force = true;
};
}
Comment on lines +1 to +7

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 configuration for mempalace currently relies on a static JSON file with a hardcoded home directory path. To improve portability across different users and environments, it is better to generate the JSON content dynamically using Nix and the config.home.homeDirectory option.

{ config, ... }:
{
  home.file.".mempalace/config.json" = {
    text = builtins.toJSON {
      palace = "${config.home.homeDirectory}/ghq/github.com/shunkakinoki/wiki";
    };
    force = true;
  };
}

2 changes: 1 addition & 1 deletion config/paperclip/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ let
database_mode = if host.isKyber then "postgres" else "embedded-postgres";
database_connection_string = "";
deployment_mode = if host.isKyber then "authenticated" else "local_trusted";
host = if host.isKyber then "0.0.0.0" else "127.0.0.1";
host = "127.0.0.1";
allowed_hostname = if host.isKyber then "paperclip.shunkakinoki.com" else "";
is_kyber = if host.isKyber then "true" else "false";
};
Expand Down
2 changes: 1 addition & 1 deletion dotagents
Submodule dotagents updated 2 files
+4 −0 .gitignore
+19 −15 .ruler/mcp.json
1 change: 1 addition & 0 deletions home-manager/modules/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
./local-binaries
./local-scripts
./npm-globals
./secure-dotenv
./tailscale
./uv-globals
./xremap
Expand Down
8 changes: 8 additions & 0 deletions home-manager/modules/local-scripts/clipboard-copy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,13 @@ if command -v xsel >/dev/null 2>&1; then
exec xsel --clipboard --input
fi

# OSC 52 fallback: works over SSH if the terminal supports it
# (ghostty, iTerm2, kitty, alacritty, tmux, etc.)
if [[ -t 1 ]] || [[ -n ${TMUX:-} ]] || [[ -n ${SSH_TTY:-} ]]; then
data=$(base64 | tr -d '\n')
printf '\033]52;c;%s\a' "$data"
exit 0
fi

printf 'No clipboard backend available\n' >&2
exit 1
4 changes: 3 additions & 1 deletion home-manager/modules/local-scripts/clipboard-paste.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ if command -v xsel >/dev/null 2>&1; then
exec xsel --clipboard --output
fi

printf 'No clipboard backend available\n' >&2
# OSC 52 paste query is not reliably supported across terminals,
# so no fallback here - print an actionable hint instead.
printf 'No clipboard backend available (paste not supported over SSH)\n' >&2
exit 1
158 changes: 117 additions & 41 deletions home-manager/modules/local-scripts/decafinate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ set -euo pipefail

UNIT_NAME="decafinate"
UNIT_FILE="${UNIT_NAME}.service"
PID_FILE="${XDG_STATE_HOME:-$HOME/.local/state}/decafinate.pid"

OS="$(uname -s)"

notify_local() {
local message="$1"
Expand All @@ -28,28 +31,60 @@ EOF
}

ac_online() {
local ac_path
shopt -s nullglob

for ac_path in /sys/class/power_supply/AC*/online; do
if grep -q 1 "$ac_path"; then
return 0
fi
done
case "$OS" in
Darwin)
pmset -g ps | grep -q "AC Power"
;;
Linux)
local ac_path
shopt -s nullglob

for ac_path in /sys/class/power_supply/AC*/online; do
if grep -q 1 "$ac_path"; then
return 0
fi
done

return 1
return 1
;;
*)
echo "Unsupported OS: $OS" >&2
return 1
;;
esac
}

require_ac_path() {
if ! compgen -G "/sys/class/power_supply/AC*/online" >/dev/null; then
echo "No AC power status path found under /sys/class/power_supply/AC*/online" >&2
notify_local "No AC power status path found."
exit 1
fi
require_ac() {
case "$OS" in
Darwin)
if ! command -v pmset >/dev/null; then
echo "pmset not found" >&2
notify_local "pmset not found."
exit 1
fi
;;
Linux)
if ! compgen -G "/sys/class/power_supply/AC*/online" >/dev/null; then
echo "No AC power status path found under /sys/class/power_supply/AC*/online" >&2
notify_local "No AC power status path found."
exit 1
fi
;;
esac
}

service_active() {
systemctl --user is-active --quiet "$UNIT_FILE"
case "$OS" in
Darwin)
if [[ -f $PID_FILE ]] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then

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

Checking for file existence with [[ -f $PID_FILE ]] is insufficient if the file is empty, as kill -0 will then be called with an empty argument, leading to a shell error. Using [[ -s $PID_FILE ]] ensures the file exists and contains data before attempting to read the PID.

Suggested change
if [[ -f $PID_FILE ]] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
if [[ -s $PID_FILE ]] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then

return 0
fi
return 1
;;
Linux)
systemctl --user is-active --quiet "$UNIT_FILE"
;;
esac
}

print_status() {
Expand All @@ -63,7 +98,7 @@ print_status() {
}

start_service() {
require_ac_path
require_ac

if service_active; then
echo "decafinate is already active"
Expand All @@ -76,33 +111,60 @@ start_service() {
return 1
fi

local systemd_inhibit
local bash_bin
echo "Starting decafinate. The laptop will stay awake while AC is connected."
notify_local "Keeping the laptop awake while AC is connected."

systemd_inhibit="$(command -v systemd-inhibit)"
bash_bin="$(command -v bash)"
case "$OS" in
Darwin)
mkdir -p "$(dirname "$PID_FILE")"

if [[ -z $systemd_inhibit || -z $bash_bin ]]; then
echo "Required commands not found: systemd-inhibit and bash must be available." >&2
return 1
fi
(
caffeinate -di &
CAFF_PID=$!

echo "Starting decafinate. The laptop will stay awake while AC is connected."
notify_local "Keeping the laptop awake while AC is connected."
while ac_online; do
if ! kill -0 "$CAFF_PID" 2>/dev/null; then
break
fi
sleep 15
done

kill "$CAFF_PID" 2>/dev/null || true
rm -f "$PID_FILE"

echo "AC power disconnected; ending decafinate session."
if [[ -x "$HOME/.local/scripts/notify-local" ]]; then
"$HOME/.local/scripts/notify-local" "Decafinate" "AC power disconnected. Ending keep-awake session." >/dev/null 2>&1 || true
fi
) &
echo $! >"$PID_FILE"
disown
;;
Linux)
local systemd_inhibit
local bash_bin

systemd_inhibit="$(command -v systemd-inhibit)"
bash_bin="$(command -v bash)"

if [[ -z $systemd_inhibit || -z $bash_bin ]]; then
echo "Required commands not found: systemd-inhibit and bash must be available." >&2
return 1
fi

systemctl --user reset-failed "$UNIT_FILE" >/dev/null 2>&1 || true

# shellcheck disable=SC2016
systemd-run --user \
--unit="$UNIT_NAME" \
--collect \
--property=Restart=no \
--property=Type=simple \
"$systemd_inhibit" \
--what=idle:sleep:handle-lid-switch \
--who="decafinate" \
--why="Manual AC-only keep-awake session" \
"$bash_bin" -lc '
systemctl --user reset-failed "$UNIT_FILE" >/dev/null 2>&1 || true

# shellcheck disable=SC2016
systemd-run --user \
--unit="$UNIT_NAME" \
--collect \
--property=Restart=no \
--property=Type=simple \
"$systemd_inhibit" \
--what=idle:sleep:handle-lid-switch \
--who="decafinate" \
--why="Manual AC-only keep-awake session" \
"$bash_bin" -lc '
set -euo pipefail

ac_online() {
Expand All @@ -127,6 +189,8 @@ start_service() {
"$HOME/.local/scripts/notify-local" "Decafinate" "AC power disconnected. Ending keep-awake session." >/dev/null 2>&1 || true
fi
' >/dev/null
;;
esac
}

stop_service() {
Expand All @@ -135,7 +199,19 @@ stop_service() {
return 0
fi

systemctl --user stop "$UNIT_FILE"
case "$OS" in
Darwin)
local pid
pid="$(cat "$PID_FILE")"
# Kill the wrapper process group (includes caffeinate)
kill -- -"$pid" 2>/dev/null || kill "$pid" 2>/dev/null || true
rm -f "$PID_FILE"
;;
Linux)
systemctl --user stop "$UNIT_FILE"
;;
esac

echo "Stopped decafinate"
notify_local "Stopped the keep-awake session."
}
Expand Down
29 changes: 29 additions & 0 deletions home-manager/modules/secure-dotenv/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
config,
lib,
pkgs,
...
}:
let
homeDir = config.home.homeDirectory;
script = pkgs.writeShellScript "secure-dotenv" ''
set -euo pipefail
# Enforce 600 on all .env files under home directory
${pkgs.findutils}/bin/find "${homeDir}" \
-maxdepth 4 \
-name '.env' -o -name '.env.*' -o -name '*.env' \
2>/dev/null | while IFS= read -r f; do
Comment on lines +12 to +15

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

Parsing find output with a standard while read loop can fail if filenames contain spaces or newlines. Using -print0 and read -d '' is a more robust approach for handling arbitrary filenames, as recommended in the general rules for shell scripts in this repository.

    ${pkgs.findutils}/bin/find "${homeDir}" \
      -maxdepth 4 \
      \( -name '.env' -o -name '.env.*' -o -name '*.env' \) \
      -print0 2>/dev/null | while IFS= read -r -d "" f; do
References
  1. To robustly parse command output in shell scripts, use a unique delimiter (e.g., tab) in the format string and read with a matching IFS. This is safer than splitting by spaces with cut, especially when data fields might contain spaces.

if [ -f "$f" ] && [ ! -L "$f" ]; then
current=$(${pkgs.coreutils}/bin/stat -c '%a' "$f")
if [ "$current" != "600" ]; then
chmod 600 "$f"
fi
fi
done
'';
in
{
home.activation.secureDotenv = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
$DRY_RUN_CMD ${script}
'';
}
23 changes: 20 additions & 3 deletions home-manager/modules/uv-globals/install-uv-globals.sh
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,22 @@ echo "$DEPS" | while read -r pkg; do
uv tool install "$pkg" --python "$PYTHON_VERSION" --force $extra_flags 2>/dev/null || echo "Failed to install $pkg, skipping..."
fi

# Symlink each tool's python3 for per-tool access: `python3-<tool> -m <tool>`
# Create a wrapper so `python3-<tool> -m <tool>` uses the tool's venv python.
# A symlink won't work because Python resolves the real binary path and loses
# the venv's pyvenv.cfg, so site-packages aren't found.
tool_python="${HOME}/.local/share/uv/tools/${name}/bin/python3"
if [ -f "$tool_python" ]; then
ln -sf "$tool_python" "${HOME}/.local/bin/python3-${name}"
rm -f "${HOME}/.local/bin/python3-${name}"
cat >"${HOME}/.local/bin/python3-${name}" <<WRAPPER
#!/usr/bin/env bash
exec "${HOME}/.local/share/uv/tools/${name}/bin/python3" "\$@"
WRAPPER
chmod +x "${HOME}/.local/bin/python3-${name}"
fi
done

# Write a dispatcher so `python3 -m <tool>` uses that tool's isolated Python
rm -f "${HOME}/.local/bin/python3"
cat >"${HOME}/.local/bin/python3" <<'EOF'
#!/usr/bin/env bash
prev=""
Expand All @@ -95,7 +103,16 @@ for arg in "$@"; do
fi
prev="$arg"
done
exec /etc/profiles/per-user/"${USER}"/bin/python3 "$@"
self="$(realpath "${BASH_SOURCE[0]}")"
IFS=: read -ra dirs <<< "$PATH"
for d in "${dirs[@]}"; do
candidate="$d/python3"
if [ -x "$candidate" ] && [ "$(realpath "$candidate")" != "$self" ]; then
exec "$candidate" "$@"
fi
done
echo "python3: no system python3 found in PATH" >&2
exit 127
EOF
chmod +x "${HOME}/.local/bin/python3"

Expand Down
2 changes: 1 addition & 1 deletion home-manager/programs/fish/functions/_clrc_function.fish
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ function _clrc_function --description "Run Claude Code remote-control with a sta
# Usage: clrc [<claude remote-control args...>]

set -l claude_real (realpath (which claude))
$claude_real remote-control --permission-mode bypassPermissions $argv
$claude_real remote-control --permission-mode auto $argv
end
2 changes: 1 addition & 1 deletion home-manager/programs/fish/functions/_clwrc_function.fish
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ function _clwrc_function --description "Run Claude Code remote-control with a st
# Usage: clwrc [<claude remote-control args...>]

set -l claude_real (realpath (which claude))
$claude_real remote-control --spawn worktree --permission-mode bypassPermissions $argv
$claude_real remote-control --spawn worktree --permission-mode auto $argv
end
4 changes: 2 additions & 2 deletions home-manager/services/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ let
darkman = import ./darkman { inherit pkgs; };
dolt = ./dolt;
docker = import ./docker { inherit lib pkgs; };
dockerPostgres = import ./docker-postgres { inherit pkgs; };
dockerPostgres = ./docker-postgres;
dotfilesUpdater = import ./dotfiles-updater { inherit pkgs; };
gasTown = import ./gas-town { inherit pkgs; };
makeUpdater = import ./make-updater { inherit pkgs; };
neversslKeepalive = import ./neverssl-keepalive { inherit pkgs; };
obsidian = import ./obsidian { inherit config pkgs inputs; };
ollama = import ./ollama { inherit pkgs inputs; };
ollama = ./ollama;
qmd = ./qmd;
openclaw = ./openclaw;
paperclip = ./paperclip;
Expand Down
Loading
Loading