Skip to content
Open
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
23 changes: 18 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Claude Code operates on a 5-hour subscription model that renews from your first

**Solution:** CC AutoRenew prevents both gaps AND session burning:
- 🚫 **Prevents Gaps** - Automatically starts new sessions when blocks expire
- ⏰ **Prevents Session Burning** - Schedule when monitoring begins (`--at "09:00"`)
- ⏰ **Prevents Session Burning** - Schedule when monitoring begins (`--at "09:00"`)
- 🎯 **Perfect Timing** - Start your 5-hour block exactly when you need it

## ✨ Features
Expand All @@ -27,6 +27,7 @@ Claude Code operates on a 5-hour subscription model that renews from your first
- 📝 **Detailed Logging** - Track all renewal activities with WAITING/ACTIVE/STOPPED states
- 📊 **Live Dashboard** - Real-time monitoring with progress bars and renewal schedules
- 💬 **Custom Messages** - Use `--message` to send contextual renewal messages instead of generic greetings
- 💸 **Economical Defaults** - Uses a low-effort Claude session and a configurable model via `CLAUDE_MODEL`
- 🛡️ **Failsafe Design** - Multiple fallback mechanisms and prevents renewals near stop time
- 🖥️ **Cross-platform** - Works on macOS and Linux
- ⚡ **Clock-only Mode** - Use `--disableccusage` flag to bypass ccusage entirely
Expand Down Expand Up @@ -159,7 +160,7 @@ The new live dashboard provides real-time monitoring of your Claude renewal stat

**Progress Bar Colors:**
- 🟢 **Green** - More than 1 hour remaining
- 🟡 **Yellow** - 30-60 minutes remaining
- 🟡 **Yellow** - 30-60 minutes remaining
- 🔴 **Red** - Less than 30 minutes remaining

**Usage:**
Expand Down Expand Up @@ -202,6 +203,18 @@ Example dashboard output:
6. **Automatically restarts** the next day at start time
7. **Logs** all activities for transparency

### Economical Mode

By default, the daemon uses a low-effort Claude session and a model set through `CLAUDE_MODEL`. The scripts default that variable to `haiku`, but you can override both at startup through command flags:

Comment on lines +208 to +209
```bash
./claude-daemon-manager.sh start --model haiku --effort low
```

The selected values persist across restarts until you change them again.

If your Claude CLI/account exposes a cheaper model alias, pass it with `--model` and it will be used for every renewal.

### Custom Renewal Messages 💬

**Default Behavior (without --message):** The daemon automatically sends random greetings ("hi", "hello", "hey there", "good day", "greetings", "howdy", "what's up", "salutations") when renewing sessions. This is the original behavior and requires no configuration.
Expand Down Expand Up @@ -285,7 +298,7 @@ This mode is useful when:

The daemon adjusts its checking frequency based on time remaining:
- **Normal**: Every 10 minutes
- **< 30 minutes**: Every 2 minutes
- **< 30 minutes**: Every 2 minutes
- **< 5 minutes**: Every 30 seconds
- **After renewal**: 5-minute cooldown

Expand Down Expand Up @@ -347,7 +360,7 @@ The daemon uses smart defaults, but you can modify behavior by editing `claude-a
```bash
# Adjust check intervals (in seconds)
- Normal: 600 (10 minutes)
- Approaching: 120 (2 minutes)
- Approaching: 120 (2 minutes)
- Imminent: 30 (30 seconds)
```

Expand Down Expand Up @@ -434,7 +447,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
- Can be added to system startup for automatic launch

---
## Buy me a coffee if you like my work:
## Buy me a coffee if you like my work:

<a href="https://www.buymeacoffee.com/aniketkarne" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
--
Expand Down
59 changes: 32 additions & 27 deletions claude-auto-renew-advanced.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

LOG_FILE="$HOME/.claude-auto-renew.log"
LAST_ACTIVITY_FILE="$HOME/.claude-last-activity"
CLAUDE_MODEL="${CLAUDE_MODEL:-haiku}"
CLAUDE_EFFORT="${CLAUDE_EFFORT:-low}"

# Function to log messages
log_message() {
Expand All @@ -31,19 +33,19 @@ parse_time_remaining() {
log_message "ERROR: ccusage not available"
return 1
fi

# Try to get blocks info and extract time remaining
local output=$($ccusage_cmd blocks 2>/dev/null | grep -i "time remaining" | head -1)

if [ -z "$output" ]; then
# Try live mode for more accurate info
output=$($ccusage_cmd blocks --live 2>/dev/null | grep -i "remaining" | head -1)
fi

# Extract hours and minutes from various formats
local hours=0
local minutes=0

if [[ "$output" =~ ([0-9]+)h[[:space:]]*([0-9]+)m ]]; then
hours=${BASH_REMATCH[1]}
minutes=${BASH_REMATCH[2]}
Expand All @@ -53,7 +55,7 @@ parse_time_remaining() {
elif [[ "$output" =~ ([0-9]+)m ]]; then
minutes=${BASH_REMATCH[1]}
fi

# Convert to total minutes
local total_minutes=$((hours * 60 + minutes))
echo "$total_minutes"
Expand All @@ -63,10 +65,10 @@ parse_time_remaining() {
should_start_session() {
# First try to get accurate time from ccusage
local minutes_remaining=$(parse_time_remaining)

if [ -n "$minutes_remaining" ] && [ "$minutes_remaining" -gt 0 ]; then
log_message "Time remaining in current block: $minutes_remaining minutes"

# Start session if less than 5 minutes remaining
if [ "$minutes_remaining" -lt 5 ]; then
log_message "Reset window approaching, preparing to start session"
Expand All @@ -75,21 +77,21 @@ should_start_session() {
return 1
fi
fi

# Fallback: Check last activity time
if [ -f "$LAST_ACTIVITY_FILE" ]; then
local last_activity=$(cat "$LAST_ACTIVITY_FILE")
local current_time=$(date +%s)
local time_diff=$((current_time - last_activity))

# If more than 5 hours (18000 seconds) have passed
if [ $time_diff -gt 18000 ]; then
log_message "More than 5 hours since last activity, starting session"
return 0
else
local remaining=$((18000 - time_diff))
log_message "Fallback check: $((remaining / 60)) minutes until 5-hour mark"

# Start if within 5 minutes of the 5-hour mark
if [ $remaining -lt 300 ]; then
return 0
Expand All @@ -100,25 +102,28 @@ should_start_session() {
log_message "No previous activity found, starting session"
return 0
fi

return 1
}

# Function to start Claude session
start_claude_session() {
log_message "Attempting to start Claude session"

# Check if claude command exists
if ! command -v claude &> /dev/null; then
log_message "ERROR: claude command not found"
return 1
fi


local claude_cmd=(claude --model "$CLAUDE_MODEL" --effort "$CLAUDE_EFFORT")
log_message "Using Claude model: $CLAUDE_MODEL (effort: $CLAUDE_EFFORT)"

# Create a temporary expect script for better automation
cat > /tmp/claude_auto_start.exp << 'EOF'
cat > /tmp/claude_auto_start.exp << EOF
#!/usr/bin/expect -f
set timeout 10
spawn claude
spawn ${claude_cmd[*]}
expect {
Comment on lines 122 to 127
">" {
send "hi\r"
Expand All @@ -132,25 +137,25 @@ expect {
}
expect eof
EOF

chmod +x /tmp/claude_auto_start.exp

# Try using expect if available
if command -v expect &> /dev/null; then
/tmp/claude_auto_start.exp >> "$LOG_FILE" 2>&1
local result=$?
else
# Fallback to simple echo with macOS-compatible timeout
(echo "hi" | claude >> "$LOG_FILE" 2>&1) &
(echo "hi" | "${claude_cmd[@]}" >> "$LOG_FILE" 2>&1) &
local pid=$!

# Wait up to 10 seconds
local count=0
while kill -0 $pid 2>/dev/null && [ $count -lt 10 ]; do
sleep 1
((count++))
done

# Kill if still running
if kill -0 $pid 2>/dev/null; then
kill $pid 2>/dev/null
Expand All @@ -161,10 +166,10 @@ EOF
local result=$?
fi
fi

# Clean up
rm -f /tmp/claude_auto_start.exp

if [ $result -eq 0 ]; then
log_message "Successfully started Claude session"
date +%s > "$LAST_ACTIVITY_FILE"
Expand All @@ -178,19 +183,19 @@ EOF
# Main execution
main() {
log_message "=== Starting Claude auto-renewal check ==="

# Check ccusage availability
if ! get_ccusage_cmd &> /dev/null; then
log_message "WARNING: ccusage not found. Install with: npm install -g ccusage"
log_message "Falling back to time-based checking"
fi

# Check if we should start a session
if should_start_session; then
# Wait a moment to ensure we're in the renewal window
log_message "Waiting 60 seconds to ensure renewal window..."
sleep 60

# Try to start session up to 3 times
local attempts=0
while [ $attempts -lt 3 ]; do
Expand All @@ -203,14 +208,14 @@ main() {
sleep 30
fi
done

if [ $attempts -eq 3 ]; then
log_message "ERROR: Failed to start session after 3 attempts"
fi
else
log_message "Not time for renewal yet"
fi

log_message "=== Check complete ==="
}

Expand Down
Loading