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
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The root command dynamically selects behavior:
codes
├── init [--yes]
├── update / version
├── doctor # Run system diagnostics
├── start (alias: s) # Launch Claude in directory or project alias
├── profile (alias: pf) # add / select / test / list / remove
├── project (alias: p) # add [name] [path] / list / remove
Expand Down
3 changes: 3 additions & 0 deletions cmd/codes/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func init() {
rootCmd.AddCommand(commands.InitCmd)
rootCmd.AddCommand(commands.UpdateCmd)
rootCmd.AddCommand(commands.VersionCmd)
rootCmd.AddCommand(commands.DoctorCmd)
rootCmd.AddCommand(commands.StartCmd)
rootCmd.AddCommand(commands.ProfileCmd)
rootCmd.AddCommand(commands.ProjectCmd)
Expand All @@ -37,6 +38,8 @@ func init() {
rootCmd.AddCommand(commands.AgentCmd)
rootCmd.AddCommand(commands.TaskSimpleCmd)
rootCmd.AddCommand(commands.WorkflowCmd)
rootCmd.AddCommand(commands.NotifyCmd)
rootCmd.AddCommand(commands.NotifyCmd)

// 设置默认运行时行为
rootCmd.Run = func(cmd *cobra.Command, args []string) {
Expand Down
134 changes: 134 additions & 0 deletions docs/doctor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# codes doctor - System Diagnostics

The `codes doctor` command runs comprehensive system diagnostics to verify your Claude Code environment is properly configured and healthy.

## Usage

```bash
codes doctor
```

## What It Checks

### 1. Claude CLI Installation
- ✓ Verifies Claude CLI is in PATH
- ✓ Displays Claude CLI version
- ✗ Suggests installation command if missing

### 2. Configuration File
- ✓ Confirms config file exists and is valid
- ✓ Shows number of configured API profiles
- ✓ Displays default profile name
- ! Warns if no profiles configured
- ✗ Fails if config is corrupted

### 3. API Connectivity
- ✓ Tests connection to default API profile
- ! Skips test if no profiles configured
- ✗ Fails if API is unreachable

### 4. File Permissions
- ✓ Checks config directory (`~/.codes/`) is writable
- ✓ Checks session directory (`~/.claude/`) is writable
- ✗ Fails if critical directories aren't writable

### 5. Agent Daemons
- ✓ Lists all teams and agents
- ✓ Shows running/stopped status for each agent
- ℹ Provides command to start stopped agents
- ! Warns if unable to check team status

### 6. Disk Space
- ℹ Shows Claude session data size
- ℹ Shows codes data size
- ℹ Displays disk usage percentage
- ✓ Confirms sufficient space available
- ! Warns if disk usage > 90% or < 1GB free
- ✗ Fails if disk is critically full

## Exit Codes

- `0` - All checks passed (may have warnings)
- `1` - One or more critical checks failed

## Example Output

```
────────────────────────────
Running System Diagnostics
────────────────────────────

1. Checking Claude CLI...
✓ Claude CLI found: /usr/local/bin/claude
ℹ Version: 2.1.39 (Claude Code)

2. Checking configuration file...
✓ Config loaded: /Users/user/.codes/config.json
✓ 3 profile(s) configured
✓ Default profile: anthropic

3. Checking API connectivity...
ℹ Testing profile: anthropic
✓ API connection successful

4. Checking file permissions...
✓ Config directory writable: /Users/user/.codes
✓ Session directory writable: /Users/user/.claude

5. Checking agent daemons...
✓ 3/3 agents running across 1 team(s)

6. Checking disk space...
ℹ Claude session data: /Users/user/.claude (1.7 GB)
ℹ Codes data: /Users/user/.codes (56.9 KB)
ℹ Disk usage: 14.4% (792.7 GB / 926.4 GB available)
✓ Sufficient disk space available

────────────────────
Diagnostic Summary
────────────────────
✓ Passed: 8

✓ All checks passed!
```

## When to Use

Run `codes doctor` when:
- Setting up codes for the first time
- Troubleshooting connection issues
- Before opening a support ticket
- After system updates
- When agent daemons aren't responding
- If session data seems corrupted

## Troubleshooting

### Claude CLI Not Found
```bash
npm install -g @anthropic-ai/claude
```

### No API Profiles
```bash
codes profile add
```

### Disk Space Low
Clean up old Claude sessions:
```bash
# Review session data
ls -lh ~/.claude/

# Remove old sessions if needed
rm -rf ~/.claude/sessions/old-session-id
```

### Agents Not Running
```bash
# Start all agents in a team
codes agent start-all <team-name>

# Or start specific agent
codes agent start <team-name> <agent-name>
```
45 changes: 45 additions & 0 deletions internal/agent/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,9 @@ func (d *Daemon) writeNotification(task *Task, status, detail string) {
}); err != nil {
d.logger.Printf("notification: desktop notify error: %v", err)
}

// Send webhook notifications (if configured)
d.sendWebhookNotifications(status, task)
}

// truncate shortens a string to maxLen, adding "..." if truncated.
Expand All @@ -483,3 +486,45 @@ func truncate(s string, maxLen int) string {
}
return s[:maxLen-3] + "..."
}

// sendWebhookNotifications sends notifications to all configured webhooks.
func (d *Daemon) sendWebhookNotifications(status string, task *Task) {
webhooks, err := config.ListWebhooks()
if err != nil || len(webhooks) == 0 {
return
}

// Determine event type
eventType := "task_completed"
if status == "failed" {
eventType = "task_failed"
}

notification := notify.Notification{
Title: fmt.Sprintf("codes: Task %s", status),
Message: fmt.Sprintf("[%s] #%d %s", d.TeamName, task.ID, task.Subject),
Sound: false, // webhooks don't use sound
}

for _, webhook := range webhooks {
// Check event filter
if len(webhook.Events) > 0 {
allowed := false
for _, event := range webhook.Events {
if event == eventType {
allowed = true
break
}
}
if !allowed {
continue
}
}

// Send notification
notifier := notify.NewWebhookNotifier(webhook.URL, webhook.Format)
if err := notifier.Send(notification); err != nil {
d.logger.Printf("webhook notification error (%s): %v", webhook.URL, err)
}
}
}
Loading
Loading