This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Important: Always read the README.md file in full before starting any task. It contains essential user-facing information about requirements, setup, and usage that may be critical for helping users effectively.
ccremote is a CLI tool that provides remote control for Claude Code sessions with Discord integration. It monitors Claude Code sessions, automatically continues them when usage limits reset, and provides Discord notifications for session events and approval requests.
bun run dev- Run in development modebun run build- Build for production using tsdownbun run test- Run tests with vitestbun run lint- Lint code with ESLintbun run typecheck- Type check with TypeScript compilerbun run check- All checks (lint + typecheck + test + build)bun run release- Full release process (all checks + version bump)
bun run build- Build distribution files with tsdownbun run check- Full validation (lint + typecheck + test + build)bun run release- Complete release workflow (check + version bump with bumpp)npm publish- Publish to npm registry (triggers prepack build + publint validation)
- Tests are located alongside source files using vitest's in-source testing
- Use
import.meta.vitestblocks for tests within source files - Test config: vitest with globals enabled, node environment
- Run single test file:
vitest run src/core/monitor.ts
Command System (src/commands/)
- CLI interface using command pattern
- Commands:
init,start,stop,list,status - Entry point:
src/index.ts→src/commands/index.ts
Core Services (src/core/)
config.ts: Configuration management with env file precedencesession.ts: Session state management with JSON persistencetmux.ts: Tmux session integration and command sendingmonitor.ts: Pattern detection and event monitoring systemdiscord.ts: Discord bot integration for notifications
Configuration Priority (highest to lowest):
- Environment variables (CCREMOTE_* prefix)
- ./ccremote.env
- ./.env
- ~/.ccremote.env
Session Management
- Sessions: Global user directory
~/.ccremote/sessions.json(shared across all projects) - Auto-generated IDs:
ccremote-1,ccremote-2, etc. - Status tracking:
active,waiting,waiting_approval,ended - Logs: Global user directory
~/.ccremote/logs/with project-specific naming:{projectName}-{sessionId}.log
Pattern Detection
- Usage limit detection:
/(?:5-hour limit reached.*resets|usage limit.*resets)/i - Approval dialog detection: Requires question + numbered options + selection arrow
- Command continuation: Automated after 5-hour reset
Discord Integration
- Notification types:
limit,continued,approval,error - Per-user bots recommended for privacy
- Approval workflow: detect → notify → wait for user response
- Resilience Features:
- Automatic retry logic with exponential backoff for connection failures
- Increased WebSocket timeout values (handshake: 60s, hello: 2min, ready: 30s)
- Graceful degradation - monitoring continues even if Discord fails
- Smart error detection - distinguishes retryable vs permanent errors
- Permissions Policy: Bot requires these Discord permissions (as implemented in src/core/discord.ts):
- Administrator (recommended): Full channel management without role hierarchy issues - ensures bot can always access and manage channels
- OR minimal permissions:
- Manage Channels: Create/rename session channels (falls back to DMs if missing)
- Manage Roles: Edit channel permission overwrites to hide archived channels from server list
- Send Messages: Send notifications to channels/DMs
- Read Message History: Read user approval responses
- Message Content Intent: Required gateway intent for approval commands
CCREMOTE_DISCORD_BOT_TOKEN=your_discord_bot_token
CCREMOTE_DISCORD_OWNER_ID=your_discord_user_idCCREMOTE_DISCORD_AUTHORIZED_USERS=user1,user2 # Additional users
CCREMOTE_MONITORING_INTERVAL=2000 # Poll interval (ms)
CCREMOTE_MAX_RETRIES=3 # Error retry limit
CCREMOTE_AUTO_RESTART=true # Auto-restart on failure- Uses @ryoppippi/eslint-config with TypeScript support
- Strict TypeScript configuration with ESNext modules
- Console logging: only warn, error, info allowed (no plain console.log)
- Top-level await enabled
- Vitest for testing with in-source test blocks
- tsdown: Modern TypeScript bundler (replaces tsc)
- Output: ESM format with declaration files
- Entry:
src/index.ts - Distribution:
dist/directory - Binary: Executable CLI via
dist/index.js
- Make changes to source files in
src/ - Run
bun run checkto verify types, run tests, lint etc - Use
bun run devfor local testing of CLI commands - Build with
bun run buildbefore publishing
To install ccremote globally for development and testing:
# Build the project
bun run build
# Create and install package globally (recommended approach)
bun run release:test # Runs all checks, builds, packages, and installs globally
# Test global installation
ccremote --help
# After making changes, simply run:
bun run release:test # Rebuilds, repackages, and reinstalls globallyNote: Avoid using bun link or manual symlinks as they can cause module resolution issues with PM2's internal dependencies when the daemon processes are started.
- PM2 is bundled with the distribution (included in
filesarray) - PM2 binary is resolved at runtime from multiple possible locations
- No external dependencies need to be installed when using ccremote in other projects
- Use GitHub PRs: Never merge to
mainlocally - always use GitHub pull requests - Test before merging: Bump version and test releases (
npm pack+ local install) on feature branches - Publish from main: Only publish to npm from
mainbranch after PR merge - Tag releases: Create git tags for published versions
# Full release process (main branch only)
bun run release
# Test package without releasing
bun run release:test- Merge features: All features merged to main via GitHub PRs
- Release: On main branch, run
bun run release- Validates you're on main branch
- Runs all checks (lint, typecheck, tests, build)
- Creates and tests package locally
- Interactive version bump
- Publishes to npm and creates git tag
- Bug fixes: If issues found, fix on main and re-run
bun run release