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
6 changes: 5 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ ALLOWED_USER_ID=your_discord_user_id

# Base folder path where Claude Code will operate
# Channel names will be appended to this path
BASE_FOLDER=/Users/your-user-name/repos
BASE_FOLDER=/Users/your-user-name/repos

# MCP Server Port (optional, defaults to 3001)
# Change this if port 3001 is already in use
MCP_SERVER_PORT=3001
Comment on lines +12 to +14
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a blank line at the end of the file.

The dotenv-linter correctly identifies that the file should end with a blank line, which is a common convention for text files.

Apply this diff:

 # MCP Server Port (optional, defaults to 3001)
 # Change this if port 3001 is already in use
 MCP_SERVER_PORT=3001
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# MCP Server Port (optional, defaults to 3001)
# Change this if port 3001 is already in use
MCP_SERVER_PORT=3001
# MCP Server Port (optional, defaults to 3001)
# Change this if port 3001 is already in use
MCP_SERVER_PORT=3001
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 14-14: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)

🤖 Prompt for AI Agents
In .env.example around lines 12 to 14, the file is missing a trailing blank line
at EOF; update the file by adding a single newline (blank line) at the end so
the file ends with an empty line.

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ coverage
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
log.txt
bot.log

# dotenv environment variable files
.env
Expand Down
176 changes: 165 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ A Discord bot that runs Claude Code sessions on different projects based on Disc

## Quickstart

1. Install [Bun](https://bun.sh/) and [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code)
1. Install [Bun](https://bun.sh/), [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code), and [Beads](https://github.com/steveyegge/beads) (optional)
2. Create a Discord bot at [Discord Developer Portal](https://discord.com/developers/applications)
3. Clone and setup:
```bash
Expand All @@ -26,8 +26,10 @@ A Discord bot that runs Claude Code sessions on different projects based on Disc

- **Channel-based project mapping**: Each Discord channel corresponds to a folder (e.g., `#my-project` → `/path/to/repos/my-project`)
- **Persistent sessions**: Sessions are maintained per channel and automatically resume
- **Real-time streaming**: See Claude Code's tool usage and responses as they happen
- **Activity logging**: Shows up to 20 lines of activity including tool calls with parameters
- **Live progress updates**: Single message that updates in real-time showing current status, latest response, and recent tools
- **Automatic screenshots**: Detects localhost URLs and automatically captures/posts screenshots of web apps
- **Beads task tracking**: Deep integration with Beads issue tracker for managing complex tasks and dependencies
- **MCP tool permissions**: Interactive approval for MCP tools with 5-minute timeout
- **Slash commands**: Use `/clear` to reset a session

## Setup Instructions
Expand Down Expand Up @@ -125,10 +127,13 @@ In your Discord server, create channels for each repository:

```bash
# Start the bot
bun run src/index.ts

# Or use the npm script
bun start

# Start in background (recommended for production)
nohup bun run src/index.ts > bot.log 2>&1 &

# Restart the bot (safely stops and restarts)
bun run restart
```

**Important**: Do not use hot reload (`bun --hot`) as it can cause issues with process management and spawn multiple Claude processes.
Expand All @@ -139,32 +144,181 @@ Bot is ready! Logged in as Claude Code Bot#1234
Successfully registered application commands.
```

### Managing the Bot

**Restarting the bot:**
```bash
bun run restart
```
This script safely stops any running bot instance and immediately starts a new one. Logs are written to `bot.log`.

**Viewing logs:**
```bash
tail -f bot.log
```

**Stopping the bot:**
```bash
# Find the bot process
ps aux | grep "bun run src/index.ts"

# Kill it
kill <PID>
```

## Usage

Type any message in a channel that corresponds to a repository folder. The bot will run Claude Code with your message as the prompt and stream the results.
Type any message in a channel that corresponds to a repository folder. The bot will run Claude Code with your message as the prompt and show live progress updates.

**Progress Updates**: The bot creates a single message that updates in real-time showing:
- 🚀 Working directory, model, and available tools
- 💬 Latest assistant response (most recent 200 characters)
- 🔧 Recent tool calls with status indicators (⏳ running, ✅ completed, ❌ failed)
- Final status: ✅ Session Complete, ❌ Session Failed, or ⏰ Timeout

**Notifications**: The bot will @mention you when:
- ✅ A session completes successfully
- ❌ A session fails or encounters an error
- ⏰ A session times out (after 30 minutes)

**MCP Permissions**: When Claude Code requests permission to use an MCP tool, the bot will:
- Post a permission request message with tool details
- Wait up to 5 minutes for you to react with ✅ (approve) or ❌ (deny)
- Auto-deny if no response within the timeout period
- Delete the permission message after you respond to keep chat clean

**Automatic Screenshots**: When Claude mentions a localhost URL, the bot will:
- Automatically detect URLs like `localhost:3000`, `http://localhost:8080/path`, `127.0.0.1:5000`
- Wait 3 seconds for the server to be ready
- Launch a headless browser and capture a screenshot
- Post the screenshot to Discord with the URL
- Supported formats: `localhost:PORT`, `127.0.0.1:PORT`, `0.0.0.0:PORT`, `http://localhost:PORT/path`

**Beads Task Tracking**: Claude Code can use Beads tools to manage complex tasks:
- `beads_init` - Initialize Beads in project directory
- `beads_create` - Create issues with priorities and types
- `beads_list` - List and filter issues
- `beads_update` - Update issue status, priority, or description
- `beads_ready` - Show issues ready to work on (no blockers)
- `beads_blocked` - Show blocked issues
- `beads_dep_add` - Create dependencies (blocks, related, parent, discovered)
- `beads_stats` - View project statistics
- All Beads data is git-versioned in `.beads/` directory

### Commands

- **Any message**: Runs Claude Code with your message as the prompt
- **stop**: Stops the currently running Claude Code process in the channel
- **/clear**: Resets the current channel's session (starts fresh next time)

### Example

```
You: hello
Bot: 🔧 LS (path: .)
🔧 Read (file_path: ./package.json)

Bot: 🚀 Claude Code

Working Directory: /path/to/repos/my-project
Model: claude-sonnet-4-5-20250929
Tools: 15 available

Latest Response:
Hello! I can see this is a Node.js project. What would you like to work on?
✅ Completed (3 turns)

Recent Tools:
✅ Glob (pattern=**/*.ts)
✅ Read (file_path=./package.json)

[Message updates in real-time as Claude works, then final status:]

Bot: ✅ Session Complete

Working Directory: /path/to/repos/my-project
Model: claude-sonnet-4-5-20250929
Tools: 15 available

Latest Response:
Task completed

Completed in 3 turns

Recent Tools:
✅ Glob (pattern=**/*.ts)
✅ Read (file_path=./package.json)

@YourUsername
```

## How It Works

- Each Discord channel maps to a folder: `#my-project` → `/path/to/repos/my-project`
- Sessions persist per channel and automatically resume
- Shows real-time tool usage and responses
- Single progress message updates in real-time (no spam!)
- Shows latest response, recent tools, and current status
- @mentions you only when input needed or task completes
- Only responds to the configured `ALLOWED_USER_ID`

## Development

### Running Tests

```bash
# Run all tests
bun run test:run

# Run tests in watch mode
bun test

# Run tests with coverage report
bun run test:coverage
```

### Test Coverage

Current test coverage (excluding MCP integration modules):

- **Overall**: 50.69%
- **database.ts**: 100% ✅
- **config.ts**: 100% ✅
- **shell.ts**: 93.58% ✅
- **commands.ts**: 76.19%
- **manager.ts**: 36.79%
- **client.ts**: 28.46%

Coverage focuses on unit-testable modules. MCP modules are excluded as they require full integration testing with Claude Code CLI and Discord bot running.

### Process Exit Code Handling

The bot properly handles Claude Code process exit codes:
- **Exit code 0**: Normal successful completion
- **Exit code 143**: SIGTERM shutdown (also treated as normal)
- **Other codes**: Displayed as errors in Discord

The bot no longer manually terminates Claude Code processes. It lets them exit naturally when tasks complete.

## Troubleshooting

### Claude Code Hooks

If you have Claude Code hooks configured (e.g., audio notifications in `~/.claude/settings.json`), they may interfere with the Discord bot. The bot automatically sets `CLAUDE_DISABLE_HOOKS=1` when spawning Claude processes.

To make your hooks respect this, add a check at the beginning of your hook scripts:

```bash
#!/bin/bash
# Example: ~/.claude/claude-sound-notification.sh

# Skip hook if running from Discord bot
if [ "$CLAUDE_DISABLE_HOOKS" = "1" ]; then
exit 0
fi

# Your existing hook code (e.g., play sound)
mplayer -really-quiet /path/to/sound.mp3
```

This ensures hooks run normally in your terminal but are skipped when using the Discord bot.

For detailed setup instructions, troubleshooting, and development information, see [CONTRIBUTING.md](CONTRIBUTING.md).

## License
Expand Down
87 changes: 87 additions & 0 deletions SESSION_DISCOVERY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Session Discovery Feature

This feature automatically detects running Claude Code sessions and creates corresponding Discord channels for them.

## How It Works

When the Discord bot starts up, it:

1. **Scans for Running Claude Processes**
- Uses `ps aux` to find Claude Code processes
- Uses `pwdx` to get the working directory of each process
- Filters out the bot's own directory

2. **Creates Discord Channels**
- Converts working directory paths to Discord-friendly channel names
- Creates a "claude-code" category if it doesn't exist
- Creates channels under that category for each discovered session
- If a channel already exists, sends a notification instead

3. **Channel Name Conversion**
- `/home/user/projects/my-app` → `#my-app`
- `/home/user/Soffi/Main Project` → `#main-project`
- Sanitizes to lowercase, alphanumeric + dashes/underscores

## Example

If you have Claude Code running in these directories:
- `/home/user/projects/soffi-main`
- `/home/user/projects/discord-bot`

The bot will create:
```
📁 claude-code (category)
└─ #soffi-main
└─ #discord-bot
```

Each channel will show:
- 🔍 Session Discovered
- Working Directory: `/home/user/projects/soffi-main`
- Process ID: 1234
- Message: "You can now interact with this session by sending messages here!"

## Files Modified

- **`src/services/session-discovery.ts`** - New service for discovering sessions
- **`src/bot/client.ts`** - Integrated session discovery on startup
- **`src/index.ts`** - Pass baseFolder to DiscordBot
- **`test/services/session-discovery.test.ts`** - Comprehensive test suite
- **`test/bot/client.test.ts`** - Updated tests for new constructor parameter

## Benefits

1. **Seamless Integration** - Existing sessions are automatically discoverable
2. **No Manual Setup** - Channels are created automatically
3. **Clear Organization** - All Claude Code channels grouped under one category
4. **Process Tracking** - See which PID corresponds to each session
5. **No Duplicates** - Handles existing channels gracefully

## Running the Bot

To test the feature:

```bash
# Make sure you have Claude Code sessions running in various directories
bun run src/index.ts
```

The bot will:
1. Start the MCP Permission Server
2. Discover existing Claude Code sessions
3. Create Discord channels for each
4. Log the results to console

## Environment Requirements

Make sure these environment variables are set:
- `DISCORD_TOKEN` - Your Discord bot token
- `ALLOWED_USER_ID` - Discord user ID who can use the bot
- `BASE_FOLDER` - Base path where Claude Code operates

## Notes

- The bot excludes its own directory from discovery
- Channel names are sanitized to be Discord-compatible
- Existing channels receive a "Session Detected" notification
- The feature runs once on bot startup (not continuously)
Loading