Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
123 changes: 111 additions & 12 deletions bun.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions home-manager/services/cliproxyapi/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ in
"${pkgs.bash}/bin/bash"
"${backupScripts}/backup-and-recover.sh"
];
StartInterval = 300; # Run every 5 minutes
StartInterval = 180; # Run every 3 minutes

Copilot AI Dec 26, 2025

Copy link

Choose a reason for hiding this comment

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

The backup interval was reduced from 5 minutes (300 seconds) to 3 minutes (180 seconds). This 40% increase in frequency may put additional load on the R2 storage service with more frequent sync operations. Consider whether this increased frequency is necessary, especially since the cliproxyapi service appears to use KeepAlive=true (continuously running), so auth files should rarely be missing. A less aggressive interval might be sufficient.

Copilot uses AI. Check for mistakes.
RunAtLoad = true;
StandardOutPath = "/tmp/cliproxyapi-backup.log";
StandardErrorPath = "/tmp/cliproxyapi-backup.error.log";
Expand All @@ -88,7 +88,7 @@ in
};
Timer = {
OnBootSec = "1min";
OnUnitActiveSec = "5min";
OnUnitActiveSec = "3min";
Unit = "cliproxyapi-backup.service";
};
Install = {
Expand Down
24 changes: 22 additions & 2 deletions home-manager/services/cliproxyapi/scripts/backup-auth.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,36 @@ set -euo pipefail

CONFIG_DIR="$HOME/.cli-proxy-api"
BACKUP_DIR="s3://cliproxyapi/backup/auths/"
MAIN_DIR="s3://cliproxyapi/auths/"
AUTH_DIR="$CONFIG_DIR/objectstore/auths"
DOTFILES_AUTH_DIR="$HOME/dotfiles/objectstore/auths"

# First, sync from dotfiles repo to local cache (picks up new auth files from ccs auth)
if [ -d "$DOTFILES_AUTH_DIR" ] && [ -n "$(ls -A "$DOTFILES_AUTH_DIR" 2>/dev/null)" ]; then
mkdir -p "$AUTH_DIR"
rsync -a "$DOTFILES_AUTH_DIR/" "$AUTH_DIR/"
Comment on lines +14 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add rsync to service PATH or avoid it

This new rsync call will fail under the Linux systemd unit because the service PATH is explicitly set to only bash/awscli2/coreutils (see home-manager/services/cliproxyapi/default.nix lines 106–112), so rsync is not available and set -e will terminate the backup/recovery cycle as soon as $HOME/dotfiles/objectstore/auths exists. That leaves auths unsynced and recovery skipped on systems where the dotfiles repo is present; either add pkgs.rsync to the PATH or gate this block on command -v rsync.

Useful? React with 👍 / 👎.

Copilot AI Dec 26, 2025

Copy link

Choose a reason for hiding this comment

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

Using rsync -a without error handling could silently fail. If rsync fails (e.g., due to permissions or I/O errors), the script will continue with potentially incomplete or corrupted auth files being synced to R2. Consider adding error handling similar to the aws s3 sync commands, or use set -e behavior by checking the rsync exit code.

Copilot uses AI. Check for mistakes.
echo "✅ Synced from dotfiles repo to local cache" >&2
fi

# Check if auth directory has files
if [ -d "$AUTH_DIR" ] && [ -n "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
echo "Backing up auth files to R2 backup directory..." >&2
echo "Syncing auth files to R2..." >&2

# Sync to main auths/ location (what cliproxyapi reads from)
AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$AUTH_DIR/" \
"$MAIN_DIR" 2>/dev/null && echo "✅ Synced to auths/" >&2 || echo "⚠️ Sync to auths/ failed" >&2
Comment on lines +25 to +31

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

Using && ... || ... for control flow can be brittle, especially with set -e enabled. If the aws command fails, the script will exit, and the || part will not be executed. A standard if/else block is safer and more readable. Also, redirecting stderr to /dev/null hides potentially useful error messages. Since the service logs stderr, it's better to let aws errors be captured for easier debugging.

Suggested change
AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$AUTH_DIR/" \
"$MAIN_DIR" 2>/dev/null && echo "✅ Synced to auths/" >&2 || echo "⚠️ Sync to auths/ failed" >&2
if AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$AUTH_DIR/" \
"$MAIN_DIR"; then
echo "✅ Synced to auths/" >&2
else
echo "⚠️ Sync to auths/ failed" >&2
fi


# Also sync to backup location for redundancy
AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$AUTH_DIR/" \
"$BACKUP_DIR" 2>/dev/null || echo "⚠️ Backup failed (continuing anyway)" >&2
"$BACKUP_DIR" 2>/dev/null && echo "✅ Synced to backup/auths/" >&2 || echo "⚠️ Backup sync failed" >&2
Comment on lines 34 to +40

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

This block has the same issues as the previous one: the && ... || ... construct is not robust with set -e, and redirecting stderr to /dev/null suppresses important error information. Refactoring to an if/else block is recommended for improved reliability and debuggability.

Suggested change
AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$AUTH_DIR/" \
"$BACKUP_DIR" 2>/dev/null || echo "⚠️ Backup failed (continuing anyway)" >&2
"$BACKUP_DIR" 2>/dev/null && echo "✅ Synced to backup/auths/" >&2 || echo "⚠️ Backup sync failed" >&2
if AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$AUTH_DIR/" \
"$BACKUP_DIR"; then
echo "✅ Synced to backup/auths/" >&2
else
echo "⚠️ Backup sync failed" >&2
fi

Comment on lines +25 to +40

Copilot AI Dec 26, 2025

Copy link

Choose a reason for hiding this comment

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

The error handling pattern with || echo at the end of each aws s3 sync command prevents the script from failing (via set -e) even when sync operations fail. If both the main and backup sync operations fail, the script will exit successfully despite no files being uploaded. Consider tracking failures and exiting with a non-zero status code if critical operations fail, especially for the main sync to auths/.

Copilot uses AI. Check for mistakes.
fi
25 changes: 20 additions & 5 deletions home-manager/services/cliproxyapi/scripts/recover-auth.sh
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
#!/usr/bin/env bash
# Recover auth files from backup if missing
# Recover auth files from R2 if missing locally
# Handles race condition where files get deleted during config reload

set -euo pipefail

CONFIG_DIR="$HOME/.cli-proxy-api"
MAIN_DIR="s3://cliproxyapi/auths/"
BACKUP_DIR="s3://cliproxyapi/backup/auths/"
AUTH_DIR="$CONFIG_DIR/objectstore/auths"

# Check if auth directory is missing or empty
if [ ! -d "$AUTH_DIR" ] || [ -z "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
echo "Auth files missing, attempting recovery from R2 backup..." >&2
echo "Auth files missing locally, attempting recovery from R2..." >&2
mkdir -p "$AUTH_DIR"
AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \

# Try main auths/ location first
if AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$BACKUP_DIR" \
"$AUTH_DIR/" 2>/dev/null && echo "✅ Recovered auth files from backup" >&2 || echo "⚠️ Recovery failed (no backup available?)" >&2
"$MAIN_DIR" \
"$AUTH_DIR/" 2>/dev/null; then

@cubic-dev-ai cubic-dev-ai Bot Dec 26, 2025

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.

P1: aws s3 sync returns success (exit code 0) even when the source is empty and nothing is synced. This means the backup fallback will be skipped even if no files were recovered from the main location. Consider also checking if files actually exist after sync:

if AWS_ACCESS_KEY_ID=... aws s3 sync ... && [ -n "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At home-manager/services/cliproxyapi/scripts/recover-auth.sh, line 24:

<comment>`aws s3 sync` returns success (exit code 0) even when the source is empty and nothing is synced. This means the backup fallback will be skipped even if no files were recovered from the main location. Consider also checking if files actually exist after sync:

```bash
if AWS_ACCESS_KEY_ID=... aws s3 sync ... &amp;&amp; [ -n &quot;$(ls -A &quot;$AUTH_DIR&quot; 2&gt;/dev/null)&quot; ]; then
```</comment>

<file context>
@@ -1,22 +1,37 @@
-    &quot;$BACKUP_DIR&quot; \
-    &quot;$AUTH_DIR/&quot; 2&gt;/dev/null &amp;&amp; echo &quot;✅ Recovered auth files from backup&quot; &gt;&amp;2 || echo &quot;⚠️  Recovery failed (no backup available?)&quot; &gt;&amp;2
+    &quot;$MAIN_DIR&quot; \
+    &quot;$AUTH_DIR/&quot; 2&gt;/dev/null; then
+    echo &quot;✅ Recovered auth files from auths/&quot; &gt;&amp;2
+  else
</file context>
Suggested change
"$AUTH_DIR/" 2>/dev/null; then
"$AUTH_DIR/" 2>/dev/null && [ -n "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
Fix with Cubic

Comment on lines +18 to +24

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

Redirecting stderr to /dev/null hides potentially useful error messages from aws s3 sync. Since this script's stderr is captured by the service configuration, it's better to allow these errors to be logged for easier debugging.

Suggested change
if AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$BACKUP_DIR" \
"$AUTH_DIR/" 2>/dev/null && echo "✅ Recovered auth files from backup" >&2 || echo "⚠️ Recovery failed (no backup available?)" >&2
"$MAIN_DIR" \
"$AUTH_DIR/" 2>/dev/null; then
if AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$MAIN_DIR" \
"$AUTH_DIR/"; then

echo "✅ Recovered auth files from auths/" >&2
else
# Fall back to backup location
echo "Main location empty, trying backup..." >&2
AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$BACKUP_DIR" \
"$AUTH_DIR/" 2>/dev/null && echo "✅ Recovered from backup/auths/" >&2 || echo "⚠️ Recovery failed" >&2
Comment on lines +29 to +35

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

This block has the same issues as seen in backup-auth.sh: the && ... || ... construct is not robust with set -e, and redirecting stderr to /dev/null suppresses important error information. Refactoring to an if/else block is recommended for improved reliability and debuggability.

Suggested change
AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$BACKUP_DIR" \
"$AUTH_DIR/" 2>/dev/null && echo "✅ Recovered from backup/auths/" >&2 || echo "⚠️ Recovery failed" >&2
if AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY}" \
aws s3 sync \
--endpoint-url="${OBJECTSTORE_ENDPOINT}" \
--no-progress \
"$BACKUP_DIR" \
"$AUTH_DIR/"; then
echo "✅ Recovered from backup/auths/" >&2
else
echo "⚠️ Recovery failed" >&2
fi

Comment on lines +18 to +35

Copilot AI Dec 26, 2025

Copy link

Choose a reason for hiding this comment

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

The recovery script suppresses all stderr output from aws s3 sync with 2>/dev/null, making it difficult to diagnose failures. When the main location sync fails, it's unclear whether it failed because the location is empty, network issues occurred, or authentication failed. Consider capturing and logging the error output to help with troubleshooting, or at least distinguishing between "no files found" and "sync operation failed".

Copilot uses AI. Check for mistakes.
fi

Copilot AI Dec 26, 2025

Copy link

Choose a reason for hiding this comment

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

After recovery attempts, there's no verification that files were actually recovered. The script could complete successfully even if both sync operations fail or return no files. Consider adding a check after the recovery attempts to verify that $AUTH_DIR is not empty, and exit with an error if recovery failed to restore any files.

Suggested change
fi
fi
# Verify that recovery actually restored at least one auth file
if [ -z "$(ls -A "$AUTH_DIR" 2>/dev/null)" ]; then
echo "❌ Recovery failed: no auth files present in $AUTH_DIR after recovery attempts" >&2
exit 1
fi

Copilot uses AI. Check for mistakes.
fi
9 changes: 2 additions & 7 deletions home-manager/services/dotfiles-updater/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,7 @@ in
]
}:/opt/homebrew/bin:/usr/local/bin";
};
StartCalendarInterval = [
{
Hour = 0;
Minute = 0;
}
];
StartInterval = 10800;
StandardOutPath = "/tmp/dotfiles-updater.log";
StandardErrorPath = "/tmp/dotfiles-updater.error.log";
};
Expand Down Expand Up @@ -62,7 +57,7 @@ in
Description = "Timer for dotfiles auto-updater";
};
Timer = {
OnCalendar = "*-*-* 00:00:00";
OnCalendar = "*-*-* 00/3:00:00";

Copilot AI Dec 26, 2025

Copy link

Choose a reason for hiding this comment

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

The OnCalendar value "--* 00/3:00:00" is incorrectly formatted for systemd timers. The "/3" notation in the hour field means "every 3 hours starting from hour 00", but the minute and second fields should not both be "00:00".

For a timer that runs every 3 hours, the correct format should be:

  • "--* *:00:00" with OnUnitActiveSec = "3h" (preferred for recurring tasks)
  • OR "--* 00/3:00:00" but this is non-standard syntax

To match the macOS StartInterval of 10800 seconds (3 hours), consider using OnUnitActiveSec instead of OnCalendar for consistency.

Suggested change
OnCalendar = "*-*-* 00/3:00:00";
OnUnitActiveSec = "3h";

Copilot uses AI. Check for mistakes.
Persistent = true;
};
Install = {
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@pulumi/pulumi": "^3.212.0",
"@sourcegraph/amp": "^0.0.1764893126-gb1ffc3",
"@typescript/native-preview": "^7.0.0-dev.20251127.1",
"@vibe-kit/grok-cli": "^0.0.34",
"ccusage": "^17.2.0",
"cline": "^1.0.5",
"open-composer": "^0.8.23",
Expand All @@ -41,6 +42,7 @@
"@pulumi/pulumi",
"@sourcegraph/amp",
"@typescript/native-preview",
"@vibe-kit/grok-cli",
"ccusage",
"cline",
"open-composer",
Expand Down
Loading