claude-oauth-refresher
SafeAI & LLMs
Keep your Claude access token fresh 24/7.
SKILL.md
# claude-oauth-refresher
**Automatic OAuth token refresh for Claude Code CLI on macOS**
Keep your Claude account logged in 24/7 by automatically refreshing OAuth tokens before they expire.
---
## ā ļø Requirements
This skill is **macOS-only** and requires:
1. **macOS** (uses Keychain for secure credential storage)
2. **Claude Code CLI** already installed (`claude` command available)
3. **Already logged into your Claude account** (run `claude` then `login` - stores tokens in Keychain)
4. **Clawdbot** installed and running
**Not sure if you're set up?** Run the verification script:
```bash
./verify-setup.sh
```
---
## What It Does
- **Monitors** your Claude CLI token expiration
- **Refreshes** tokens automatically before they expire (default: 30 min buffer)
- **Notifies** you with three notification types:
- š Start: "Refreshing Claude token..."
- ā
Success: "Claude token refreshed!"
- ā Failure: Detailed error with troubleshooting steps
- **Logs** all refresh attempts for debugging
---
## Installation
### Quick Setup (Recommended)
```bash
cd ~/clawd/skills/claude-oauth-refresher
./install.sh
```
**This installer runs ONCE** and sets up automatic token refresh that runs every 2 hours.
The installer will:
1. Verify your system meets requirements
2. **Interactively configure** notification preferences
3. Auto-detect your notification target (Telegram, Slack, etc.)
4. Set up launchd for automatic refresh
5. Test the refresh immediately
**After installation:**
- Config changes apply automatically (refresh script reads config each run)
- Edit `claude-oauth-refresh-config.json` to change settings
- Ask Clawdbot to modify settings for you
- **Only re-run installer** if you need to reinstall or fix the job
### Interactive Notification Setup
During installation, you'll be prompted:
```
Configure Notifications:
š” Recommendation: Keep all enabled for the first run to verify it works.
You can disable them later by:
1. Editing ~/clawd/claude-oauth-refresh-config.json
2. Asking Clawdbot: "disable Claude refresh notifications"
Enable "š Refreshing token..." notification? [Y/n]:
Enable "ā
Token refreshed!" notification? [Y/n]:
Enable "ā Refresh failed" notification? [Y/n]:
```
**Recommendation:** Keep all enabled initially to verify everything works, then disable start/success notifications once you're confident.
---
## Managing Notifications with Clawdbot
**You can ask Clawdbot to change notification settings for you!** No need to edit JSON manually.
### Examples
**Disable specific notification types:**
```
"disable Claude refresh start notifications"
"disable Claude refresh success notifications"
"turn off Claude token refresh start messages"
```
**Enable notification types:**
```
"enable Claude refresh start notifications"
"enable all Claude refresh notifications"
"turn on Claude token refresh success messages"
```
**Check current settings:**
```
"show Claude refresh notification settings"
"what are my Claude token refresh notification settings?"
```
**Disable all notifications:**
```
"disable all Claude refresh notifications"
"turn off all Claude token notifications"
```
**Reset to defaults:**
```
"reset Claude refresh notifications to defaults"
```
### How It Works
Clawdbot will:
1. Read your `~/clawd/claude-oauth-refresh-config.json`
2. Update the appropriate notification flags
3. Save the file
4. Confirm the changes
**Changes apply immediately** on the next refresh (no need to restart anything).
---
## Auto-Detection (Smart Defaults)
**The install script automatically detects your notification settings!**
It reads `~/.clawdbot/clawdbot.json` to find:
- Which messaging channels you have enabled
- Your chat ID, phone number, or user ID
- Automatically populates `claude-oauth-refresh-config.json` with these values
**Example:** If you have Telegram enabled with chat ID `123456789`, the installer creates:
```json
{
"notification_channel": "telegram",
"notification_target": "123456789"
}
```
**To override:** Simply edit `claude-oauth-refresh-config.json` after installation to use a different channel or target.
**If auto-detection fails:** The installer will prompt you to configure manually (see "Finding Your Target ID" below).
**Test detection before installing:**
```bash
./test-detection.sh
# Shows what would be auto-detected without modifying anything
```
---
## Finding Your Target ID
To receive notifications, you need to configure your `notification_target` in `claude-oauth-refresh-config.json`. Here's how to find it for each channel:
### Telegram
**Format:** Numeric chat ID (e.g., `123456789`)
**How to find:**
```bash
# Option 1: Use Clawdbot CLI
clawdbot message telegram account list
# Option 2: Message @userinfobot on Telegram
# Send any message, it will reply with your ID
# Option 3: Check recent messages
clawdbot message telegram message search --limit 1 --from-me true
```
**Example config:**
```json
{
"notification_channel": "telegram",
"notification_target": "123456789"
}
```
### Slack
**Format:**
- Direct messages: `user:U01234ABCD`
- Channels: `channel:C01234ABCD`
**How to find:**
```bash
# List channels
clawdbot message slack channel list
# Find user ID
clawdbot message slack user list | grep "your.email@company.com"
# Or click on your profile in Slack ā More ā Copy member ID
```
**Example config:**
```json
{
"notification_channel": "slack",
"notification_target": "user:U01234ABCD"
}
```
### Discord
**Format:**
- Direct messages: `user:123456789012345678`
- Channels: `channel:123456789012345678`
**How to find:**
```bash
# Enable Developer Mode in Discord (Settings ā Advanced ā Developer Mode)
# Then right-click your username ā Copy ID
# Or list channels
clawdbot message discord channel list
```
**Example config:**
```json
{
"notification_channel": "discord",
"notification_target": "user:123456789012345678"
}
```
### WhatsApp
**Format:** E.164 phone number (e.g., `+15551234567`)
**How to find:**
- Use your full phone number with country code
- Format: `+[country code][number]` (no spaces, dashes, or parentheses)
**Examples:**
- US: `+15551234567`
- UK: `+447911123456`
- Australia: `+61412345678`
**Example config:**
```json
{
"notification_channel": "whatsapp",
"notification_target": "+15551234567"
}
```
### iMessage
**Format (preferred):** `chat_id:123`
**How to find:**
```bash
# List recent chats to find your chat_id
clawdbot message imessage thread list --limit 10
# Find the chat with yourself or your preferred device
```
**Alternative formats:**
- Phone: `+15551234567` (E.164 format)
- Email: `your.email@icloud.com`
**Example config:**
```json
{
"notification_channel": "imessage",
"notification_target": "chat_id:123"
}
```
### Signal
**Format:** E.164 phone number (e.g., `+15551234567`)
**How to find:**
- Use your Signal-registered phone number
- Format: `+[country code][number]` (no spaces, dashes, or parentheses)
**Example config:**
```json
{
"notification_channel": "signal",
"notification_target": "+15551234567"
}
```
---
## Configuration
**File:** `claude-oauth-refresh-config.json`
```json
{
"refresh_buffer_minutes": 30,
"log_file": "~/clawd/logs/claude-oauth-refresh.log",
"notifications": {
"on_start": true,
"on_success": true,
"on_failure": true
},
"notification_channel": "telegram",
"notification_target": "YOUR_CHAT_ID"
}
```
### Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `refresh_buffer_minutes` | number | `30` | Refresh tokens this many minutes before expiry |
| `log_file` | string | `~/clawd/logs/claude-oauth-refresh.log` | Where to write logs |
| `notifications.on_start` | boolean | `true` | Send "š Refreshing token..." notification |
| `notifications.on_success` | boolean | `true` | Send "ā
Token refreshed!" notification |
| `notifications.on_failure` | boolean | `true` | Send "ā Refresh failed" notification with details |
| `notification_channel` | string | `telegram` | Channel to use (see above for options) |
| `notification_target` | string | `YOUR_CHAT_ID` | Target ID (see "Finding Your Target ID") |
### Notification Types Explained
**š Start (`on_start`)**
- Sent when refresh process begins
- Useful for debugging or knowing when refresh runs
- **Recommendation:** Disable once you verify it works (can be noisy)
**ā
Success (`on_success`)**
- Sent when token successfully refreshed
- Includes validity duration (e.g., "valid for 24h")
- **Recommendation:** Disable once you trust the setup (can be noisy)
**ā Failure (`on_failure`)**
- Sent when refresh fails with detailed error info
- Includes troubleshooting steps based on error type
- **Recommendation:** Keep enabled! You want to know about failures.
### Example Configurations
**Minimal (failures only):**
```json
{
"notifications": {
"on_start": false,
"on_success": false,
"on_failure": true
}
}
```
**Verbose (all notifications):**
```json
{
"notifications": {
"on_start": true,
"on_success": true,
"on_failure": true
}
}
```
**Silent (no notifications):**
```json
{
"notifications": {
"on_start": false,
"on_success": false,
"on_failure": false
}
}
```
---
## Detailed Failure Messages
When a refresh fails, you'll receive a detailed notification with:
1. **Error message** - What went wrong
2. **Details** - Additional context (HTTP codes, error responses, etc.)
3. **Troubleshooting** - Specific steps based on the error type
4. **Help** - Where to find logs and get support
### Example Failure Notification
```
ā Claude token refresh failed
Error: Network timeout connecting to auth.anthropic.com
Details: Connection timed out after 30s
Troubleshooting:
- Check your internet connection
- Verify you can reach auth.anthropic.com
- Try running manually: ~/clawd/skills/claude-oauth-refresher/refresh-token.sh
Need help? Message Clawdbot or check logs:
~/clawd/logs/claude-oauth-refresh.log
```
### Common Errors and Solutions
**Network/Timeout Errors**
```
Troubleshooting:
- Check your internet connection
- Verify you can reach auth.anthropic.com
- Try running manually: ./refresh-token.sh
```
**Invalid Refresh Token**
```
Troubleshooting:
- Your refresh token may have expired
- Re-authenticate: claude auth logout && claude auth
- Verify Keychain access: security find-generic-password -s 'claude-cli-auth' -a 'default'
```
**Keychain Access Denied**
```
Troubleshooting:
- Check Keychain permissions
- Re-run authentication: claude auth
- Verify setup: ./verify-setup.sh
```
**Missing Auth Profile**
```
Troubleshooting:
- Run: claude auth
- Verify file exists: ~/.config/claude/auth-profiles.json
- Check file permissions: chmod 600 ~/.config/claude/auth-profiles.json
```
---
## Usage
### Check Status
```bash
# View recent logs
tail -f ~/clawd/logs/claude-oauth-refresh.log
# Check launchd status
launchctl list | grep claude-oauth-refresher
# Manual refresh (for testing)
cd ~/clawd/skills/claude-oauth-refresher
./refresh-token.sh
```
### Modify Settings
**Option 1: Ask Clawdbot (easiest)**
```
"disable Claude refresh start notifications"
"show Claude refresh notification settings"
```
**Option 2: Edit config file**
```bash
nano ~/clawd/skills/claude-oauth-refresher/claude-oauth-refresh-config.json
```
Changes apply automatically on next refresh (every 2 hours, or when you run manually).
**No need to restart anything!** The refresh script reads the config file each time it runs.
---
## Troubleshooting
### Problem: `verify-setup.sh` says Claude CLI not found
**Solution:**
```bash
# Install Claude CLI
brew install claude
# Or download from https://github.com/anthropics/claude-cli
```
---
### Problem: `verify-setup.sh` says no refresh token found
**Solution:**
```bash
# Authenticate with Claude
claude auth
# Follow the prompts to log in
```
---
### Problem: Notifications not arriving
**Solution:**
1. Check your `notification_target` format matches the examples above
2. Test manually:
```bash
clawdbot message [channel] send --target "[your_target]" --message "Test"
```
3. Check Clawdbot is running: `clawdbot gateway status`
4. Verify notification settings:
```bash
cat ~/clawd/skills/claude-oauth-refresher/claude-oauth-refresh-config.json | jq .notifications
```
---
### Problem: Token refresh fails with "invalid_grant"
**Solution:**
```bash
# Re-authenticate from scratch
claude auth logout
claude auth
# Test refresh again
cd ~/clawd/skills/claude-oauth-refresher
./refresh-token.sh
```
---
### Problem: "Config file not found" after upgrade
**Solution:**
The config file was renamed from `config.json` to `claude-oauth-refresh-config.json`.
```bash
# If you have an old config.json, run the installer to migrate:
cd ~/clawd/skills/claude-oauth-refresher
./install.sh
# Choose to keep existing config when prompted
```
---
### Problem: Want to reinstall or fix the job
**Solution:**
```bash
# Re-run the installer (safe to run multiple times)
cd ~/clawd/skills/claude-oauth-refresher
./install.sh
```
The installer will:
- Detect existing config and ask if you want to keep it
- Update the launchd job
- Test the refresh
---
## Uninstall
```bash
cd ~/clawd/skills/claude-oauth-refresher
./uninstall.sh
```
This will:
- Stop and unload the launchd service
- Remove the plist file
- Optionally delete logs and config
---
## How It Works
1. **Installer (`install.sh`)** - Run ONCE to set up:
- Auto-detects notification target
- Interactively configures notification types
- Creates launchd job
- Tests refresh immediately
2. **Launchd** - Runs `refresh-token.sh` every 2 hours automatically
3. **Refresh Script (`refresh-token.sh`)** - Each run:
- Reads config file (changes apply automatically!)
- Checks token expiration from `~/.config/claude/auth-profiles.json`
- If token expires within buffer window (default 30 min):
- Sends start notification (if enabled)
- Retrieves refresh token from Keychain
- Calls OAuth endpoint to get new tokens
- Updates auth profile and Keychain
- Sends success notification (if enabled)
- If refresh fails:
- Sends detailed failure notification with troubleshooting
- All activity logged to `~/clawd/logs/claude-oauth-refresh.log`
4. **Config Changes** - Applied automatically:
- Edit `claude-oauth-refresh-config.json` anytime
- Ask Clawdbot to edit for you
- Changes take effect on next refresh
- No restart needed!
---
## Security
- **Tokens are never written to logs or config files**
- Refresh tokens stored securely in macOS Keychain
- Access tokens cached in `~/.config/claude/auth-profiles.json` (permissions: 600)
- All HTTP requests use Claude's official OAuth endpoints
- Config file is world-readable (contains no secrets)
---
## Support
**Logs:** `~/clawd/logs/claude-oauth-refresh.log`
**Issues:**
1. Run `./verify-setup.sh` to diagnose
2. Check logs for detailed error messages
3. Test manual refresh: `./refresh-token.sh`
4. Check notification settings: `cat claude-oauth-refresh-config.json | jq .notifications`
**Need help?** Open an issue with:
- Output of `./verify-setup.sh`
- Last 20 lines of logs: `tail -20 ~/clawd/logs/claude-oauth-refresh.log`
- macOS version: `sw_vers`
- Config (redacted): `cat claude-oauth-refresh-config.json | jq 'del(.notification_target)'`
More in AI & LLMs
antigravity-quota
SafeCheck Antigravity account quotas for Claude and Gemini models.
ask-questions-if-underspecified
SafeClarify requirements before implementing. Do not use automatically, only when invoked explicitly.
council
SafeCouncil Chamber orchestration with Memory Bridge.
de-ai-ify
SafeRemove AI-generated jargon and restore human voice to text.