claude-dojo 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +153 -37
- package/bin/claude-dojo.js +89 -0
- package/package.json +1 -1
- package/server/dist/claudeService.d.ts +2 -0
- package/server/dist/claudeService.js +32 -7
package/README.md
CHANGED
|
@@ -1,82 +1,198 @@
|
|
|
1
1
|
# Claude Dojo
|
|
2
2
|
|
|
3
|
-
A visual dashboard for Claude AI - watch agents work in
|
|
3
|
+
A visual agent dashboard for Claude AI - watch agents work in an interactive 3D hex-grid interface.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
- Anthropic API key
|
|
9
|
+
## Features
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
- **3D Hex Grid Visualization** - Watch multiple Claude sessions as interactive hexagonal tiles with real-time status updates
|
|
12
|
+
- **Subagent System** - Visualize spawned subagents (Explore, Plan, Bash, Read, Write, Glob) orbiting their parent session
|
|
13
|
+
- **Real Tool Execution** - Claude can read/write files and execute shell commands on your system
|
|
14
|
+
- **Permission System** - Approve or deny file writes and command execution (like Claude Code CLI)
|
|
15
|
+
- **Real-time Streaming** - Watch responses stream in as Claude generates them
|
|
16
|
+
- **Token Tracking** - Visual context bar showing token usage with color-coded thresholds
|
|
17
|
+
- **Session Persistence** - Sessions survive server restarts
|
|
18
|
+
- **Slash Commands** - 14 built-in commands with autocomplete
|
|
19
|
+
- **Markdown Rendering** - Rich formatting with syntax-highlighted code blocks
|
|
20
|
+
- **Resizable Panels** - Drag to adjust the canvas/chat split
|
|
11
21
|
|
|
12
|
-
|
|
22
|
+
## Quick Start
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
export ANTHROPIC_API_KEY="your-api-key-here"
|
|
16
|
-
```
|
|
24
|
+
### Requirements
|
|
17
25
|
|
|
18
|
-
|
|
26
|
+
- Node.js >= 18.0.0
|
|
27
|
+
- Anthropic API key (or AWS credentials for Bedrock)
|
|
28
|
+
|
|
29
|
+
### Installation
|
|
19
30
|
|
|
20
31
|
```bash
|
|
32
|
+
# Set your API key
|
|
33
|
+
export ANTHROPIC_API_KEY="your-api-key-here"
|
|
34
|
+
|
|
35
|
+
# Run with npx (no install needed)
|
|
21
36
|
npx claude-dojo
|
|
22
37
|
```
|
|
23
38
|
|
|
24
|
-
This starts the server and opens the dashboard in your browser
|
|
25
|
-
|
|
26
|
-
## Upgrading
|
|
39
|
+
This starts the server and opens the dashboard in your browser at `http://localhost:3001`.
|
|
27
40
|
|
|
28
|
-
|
|
41
|
+
### Upgrading
|
|
29
42
|
|
|
30
43
|
```bash
|
|
31
44
|
npx claude-dojo@latest
|
|
32
45
|
```
|
|
33
46
|
|
|
34
|
-
|
|
47
|
+
## Configuration
|
|
48
|
+
|
|
49
|
+
### Environment Variables
|
|
50
|
+
|
|
51
|
+
| Variable | Description | Default |
|
|
52
|
+
|----------|-------------|---------|
|
|
53
|
+
| `ANTHROPIC_API_KEY` | Your Anthropic API key | Required (unless using Bedrock) |
|
|
54
|
+
| `PORT` | Server port | `3001` |
|
|
55
|
+
| `ANTHROPIC_MODEL` | Claude model to use | `claude-sonnet-4-20250514` |
|
|
56
|
+
| `CLAUDE_CODE_USE_BEDROCK` | Use AWS Bedrock instead of Anthropic API | `false` |
|
|
57
|
+
| `AWS_REGION` | AWS region for Bedrock | `us-east-1` |
|
|
58
|
+
| `CLAUDE_DOJO_NO_BROWSER` | Don't auto-open browser on start | `false` |
|
|
59
|
+
|
|
60
|
+
### AWS Bedrock Support
|
|
61
|
+
|
|
62
|
+
To use Claude via AWS Bedrock instead of the Anthropic API:
|
|
35
63
|
|
|
36
64
|
```bash
|
|
37
|
-
|
|
38
|
-
|
|
65
|
+
# Set environment variables
|
|
66
|
+
export CLAUDE_CODE_USE_BEDROCK=1
|
|
67
|
+
export AWS_REGION=us-east-1
|
|
68
|
+
export ANTHROPIC_MODEL=anthropic.claude-sonnet-4-20250514-v1:0
|
|
39
69
|
|
|
40
|
-
|
|
70
|
+
# Ensure AWS credentials are configured
|
|
71
|
+
aws configure
|
|
41
72
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
- **Session Persistence** - Sessions survive server restarts
|
|
48
|
-
- **Resizable Panels** - Drag to resize the canvas/chat split
|
|
49
|
-
- **Markdown Rendering** - Rich formatting in chat messages
|
|
73
|
+
# Run Claude Dojo
|
|
74
|
+
npx claude-dojo
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The Bedrock SDK is included - no additional installation needed.
|
|
50
78
|
|
|
51
79
|
## Slash Commands
|
|
52
80
|
|
|
81
|
+
Type `/` in the input to see available commands with autocomplete.
|
|
82
|
+
|
|
53
83
|
| Command | Description |
|
|
54
84
|
|---------|-------------|
|
|
55
|
-
| `/help` | Show available commands |
|
|
56
|
-
| `/status` | Display session status
|
|
85
|
+
| `/help` | Show available commands and usage |
|
|
86
|
+
| `/status` | Display session status, token usage, and system info |
|
|
57
87
|
| `/clear` | Clear conversation history |
|
|
58
|
-
| `/compact` | Compress context by summarizing messages |
|
|
59
|
-
| `/todos` |
|
|
88
|
+
| `/compact` | Compress context by summarizing older messages |
|
|
89
|
+
| `/todos` | View and manage the task list |
|
|
60
90
|
| `/resume` | List and resume previous sessions |
|
|
61
|
-
| `/rewind` | Undo recent messages |
|
|
62
|
-
| `/export` | Export conversation to
|
|
63
|
-
| `/model` |
|
|
64
|
-
| `/
|
|
91
|
+
| `/rewind` | Undo recent messages or restore snapshots |
|
|
92
|
+
| `/export` | Export conversation to JSON or Markdown |
|
|
93
|
+
| `/model` | View or change the Claude model |
|
|
94
|
+
| `/system` | View or modify the system prompt |
|
|
95
|
+
| `/settings` | View and modify session settings |
|
|
96
|
+
| `/file` | Read a file into the conversation |
|
|
97
|
+
| `/search` | Search for patterns in files |
|
|
98
|
+
| `/run` | Execute a shell command |
|
|
65
99
|
|
|
66
100
|
## Keyboard Shortcuts
|
|
67
101
|
|
|
68
102
|
| Key | Action |
|
|
69
103
|
|-----|--------|
|
|
70
|
-
| `1-9` | Select session by index |
|
|
104
|
+
| `1-9` | Select session by index (when not typing) |
|
|
71
105
|
| `Esc` | Deselect current session |
|
|
72
|
-
| `/` |
|
|
106
|
+
| `/` | Start typing a command |
|
|
73
107
|
| `Enter` | Send message |
|
|
74
108
|
| `Shift+Enter` | New line in message |
|
|
109
|
+
| `Tab` | Accept autocomplete suggestion |
|
|
110
|
+
| `↑/↓` | Navigate autocomplete options |
|
|
111
|
+
|
|
112
|
+
## Permission System
|
|
113
|
+
|
|
114
|
+
When Claude tries to write files or execute commands, a permission dialog appears:
|
|
115
|
+
|
|
116
|
+
- **Allow Once** - Permit this specific operation
|
|
117
|
+
- **Allow Always** - Remember permission for similar operations this session
|
|
118
|
+
- **Deny** - Block the operation
|
|
119
|
+
|
|
120
|
+
Dangerous commands (like `rm -rf`, `sudo`) show enhanced warnings.
|
|
121
|
+
|
|
122
|
+
## Tool Capabilities
|
|
123
|
+
|
|
124
|
+
Claude has access to real tools that execute on your system:
|
|
125
|
+
|
|
126
|
+
| Tool | Description |
|
|
127
|
+
|------|-------------|
|
|
128
|
+
| `read_file` | Read file contents |
|
|
129
|
+
| `write_file` | Write content to files (requires permission) |
|
|
130
|
+
| `bash` | Execute shell commands (requires permission) |
|
|
131
|
+
| `glob` | Find files matching patterns |
|
|
132
|
+
| `task` | Spawn specialized subagents |
|
|
75
133
|
|
|
76
134
|
## Data Storage
|
|
77
135
|
|
|
78
|
-
Sessions
|
|
136
|
+
- **Sessions**: Persisted to `.claude-dojo/sessions/` in your working directory
|
|
137
|
+
- **Panel width**: Stored in browser localStorage
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Clone the repository
|
|
143
|
+
git clone https://github.com/anthropics/claude-dojo.git
|
|
144
|
+
cd claude-dojo
|
|
145
|
+
|
|
146
|
+
# Install dependencies
|
|
147
|
+
npm install
|
|
148
|
+
|
|
149
|
+
# Run in development mode (hot reload)
|
|
150
|
+
npm run dev
|
|
151
|
+
|
|
152
|
+
# Build for production
|
|
153
|
+
npm run build
|
|
154
|
+
|
|
155
|
+
# Start production server
|
|
156
|
+
npm start
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Architecture
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
claude-dojo/
|
|
163
|
+
├── client/ # React frontend with Three.js 3D visualization
|
|
164
|
+
│ ├── src/
|
|
165
|
+
│ │ ├── components/ # UI components (HexGrid, SessionPanel, etc.)
|
|
166
|
+
│ │ ├── hooks/ # Custom React hooks
|
|
167
|
+
│ │ ├── stores/ # Zustand state management
|
|
168
|
+
│ │ └── types/ # TypeScript types
|
|
169
|
+
│ └── dist/ # Production build
|
|
170
|
+
├── server/ # Express backend
|
|
171
|
+
│ ├── src/
|
|
172
|
+
│ │ ├── commands/ # Slash command handlers
|
|
173
|
+
│ │ ├── claudeService.ts # Claude API integration
|
|
174
|
+
│ │ └── sessionManager.ts # Session persistence
|
|
175
|
+
│ └── dist/ # Compiled server
|
|
176
|
+
└── bin/ # CLI entry point
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Troubleshooting
|
|
180
|
+
|
|
181
|
+
### Port already in use
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# Use a different port
|
|
185
|
+
PORT=3002 npx claude-dojo
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Sessions not persisting
|
|
189
|
+
|
|
190
|
+
Ensure you have write permissions to the `.claude-dojo/` directory in your working directory.
|
|
79
191
|
|
|
80
192
|
## License
|
|
81
193
|
|
|
82
194
|
MIT
|
|
195
|
+
|
|
196
|
+
## Credits
|
|
197
|
+
|
|
198
|
+
Built with [Claude Code](https://claude.ai/claude-code) (claude-opus-4-5-20250514)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
import { existsSync } from 'fs';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
|
|
11
|
+
const PORT = process.env.PORT || 3001;
|
|
12
|
+
const OPEN_BROWSER = process.env.CLAUDE_DOJO_NO_BROWSER !== '1';
|
|
13
|
+
|
|
14
|
+
// Find the server entry point
|
|
15
|
+
const serverPath = join(__dirname, '..', 'server', 'dist', 'index.js');
|
|
16
|
+
|
|
17
|
+
if (!existsSync(serverPath)) {
|
|
18
|
+
console.error('Error: Server not built. Run "npm run build" first.');
|
|
19
|
+
console.error(`Expected server at: ${serverPath}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Check for client build
|
|
24
|
+
const clientPath = join(__dirname, '..', 'client', 'dist', 'index.html');
|
|
25
|
+
if (!existsSync(clientPath)) {
|
|
26
|
+
console.error('Error: Client not built. Run "npm run build" first.');
|
|
27
|
+
console.error(`Expected client at: ${clientPath}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log(`
|
|
32
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
33
|
+
║ ║
|
|
34
|
+
║ ██████╗██╗ █████╗ ██╗ ██╗██████╗ ███████╗ ║
|
|
35
|
+
║ ██╔════╝██║ ██╔══██╗██║ ██║██╔══██╗██╔════╝ ║
|
|
36
|
+
║ ██║ ██║ ███████║██║ ██║██║ ██║█████╗ ║
|
|
37
|
+
║ ██║ ██║ ██╔══██║██║ ██║██║ ██║██╔══╝ ║
|
|
38
|
+
║ ╚██████╗███████╗██║ ██║╚██████╔╝██████╔╝███████╗ ║
|
|
39
|
+
║ ╚═════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝ ║
|
|
40
|
+
║ ║
|
|
41
|
+
║ ██████╗ ██████╗ ██╗ ██████╗ ║
|
|
42
|
+
║ ██╔══██╗██╔═══██╗ ██║██╔═══██╗ ║
|
|
43
|
+
║ ██║ ██║██║ ██║ ██║██║ ██║ ║
|
|
44
|
+
║ ██║ ██║██║ ██║██ ██║██║ ██║ ║
|
|
45
|
+
║ ██████╔╝╚██████╔╝╚█████╔╝╚██████╔╝ ║
|
|
46
|
+
║ ╚═════╝ ╚═════╝ ╚════╝ ╚═════╝ ║
|
|
47
|
+
║ ║
|
|
48
|
+
║ Visual Agent Dashboard for Claude ║
|
|
49
|
+
║ ║
|
|
50
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
51
|
+
`);
|
|
52
|
+
|
|
53
|
+
console.log(`Starting server on http://localhost:${PORT}...`);
|
|
54
|
+
|
|
55
|
+
// Start the server
|
|
56
|
+
const server = spawn('node', [serverPath], {
|
|
57
|
+
stdio: 'inherit',
|
|
58
|
+
env: { ...process.env, PORT: String(PORT) },
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
server.on('error', (err) => {
|
|
62
|
+
console.error('Failed to start server:', err.message);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Open browser after a short delay to let server start
|
|
67
|
+
if (OPEN_BROWSER) {
|
|
68
|
+
setTimeout(async () => {
|
|
69
|
+
try {
|
|
70
|
+
const open = (await import('open')).default;
|
|
71
|
+
await open(`http://localhost:${PORT}`);
|
|
72
|
+
console.log(`\nOpened browser at http://localhost:${PORT}`);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.log(`\nOpen http://localhost:${PORT} in your browser`);
|
|
75
|
+
}
|
|
76
|
+
}, 1500);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Handle shutdown
|
|
80
|
+
process.on('SIGINT', () => {
|
|
81
|
+
console.log('\nShutting down...');
|
|
82
|
+
server.kill('SIGINT');
|
|
83
|
+
process.exit(0);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
process.on('SIGTERM', () => {
|
|
87
|
+
server.kill('SIGTERM');
|
|
88
|
+
process.exit(0);
|
|
89
|
+
});
|
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import type { Message, ToolCall, Session, PermissionRequest, PermissionResponse
|
|
|
2
2
|
type BroadcastCallback = (sessionId: string, session: Session) => void;
|
|
3
3
|
declare class ClaudeService {
|
|
4
4
|
private client;
|
|
5
|
+
private clientInitPromise;
|
|
5
6
|
private conversationHistory;
|
|
6
7
|
private onSubagentCreated;
|
|
7
8
|
private onSubagentUpdated;
|
|
@@ -10,6 +11,7 @@ declare class ClaudeService {
|
|
|
10
11
|
private grantedPermissions;
|
|
11
12
|
private useBedrock;
|
|
12
13
|
constructor();
|
|
14
|
+
private getClient;
|
|
13
15
|
private getModel;
|
|
14
16
|
setOnSubagentCreated(callback: BroadcastCallback): void;
|
|
15
17
|
setOnSubagentUpdated(callback: (sessionId: string, updates: Partial<Session>) => void): void;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
-
import AnthropicBedrock from '@anthropic-ai/bedrock-sdk';
|
|
3
2
|
import { sessionManager } from './sessionManager.js';
|
|
4
3
|
import { v4 as uuidv4 } from 'uuid';
|
|
5
4
|
import * as fs from 'fs/promises';
|
|
@@ -8,11 +7,25 @@ import { exec } from 'child_process';
|
|
|
8
7
|
import { promisify } from 'util';
|
|
9
8
|
import { glob } from 'glob';
|
|
10
9
|
const execAsync = promisify(exec);
|
|
11
|
-
// Check if we should use Bedrock
|
|
10
|
+
// Check if we should use Bedrock (only if explicitly set)
|
|
12
11
|
const USE_BEDROCK = process.env.CLAUDE_CODE_USE_BEDROCK === '1' || process.env.CLAUDE_CODE_USE_BEDROCK === 'true';
|
|
13
12
|
// Model mapping for Bedrock
|
|
14
13
|
const BEDROCK_MODEL = process.env.ANTHROPIC_MODEL || 'anthropic.claude-sonnet-4-20250514-v1:0';
|
|
15
14
|
const ANTHROPIC_MODEL = process.env.ANTHROPIC_MODEL || 'claude-sonnet-4-20250514';
|
|
15
|
+
// Dynamic import for Bedrock SDK (only loaded if needed)
|
|
16
|
+
async function createBedrockClient() {
|
|
17
|
+
try {
|
|
18
|
+
const { default: AnthropicBedrock } = await import('@anthropic-ai/bedrock-sdk');
|
|
19
|
+
return new AnthropicBedrock({
|
|
20
|
+
awsRegion: process.env.AWS_REGION || 'us-east-1',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.error('Failed to load @anthropic-ai/bedrock-sdk. Install it with: npm install @anthropic-ai/bedrock-sdk');
|
|
25
|
+
console.error('Falling back to Anthropic API directly.');
|
|
26
|
+
return new Anthropic();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
16
29
|
// Tool definitions for Claude
|
|
17
30
|
const TOOLS = [
|
|
18
31
|
{
|
|
@@ -79,7 +92,8 @@ const TOOLS = [
|
|
|
79
92
|
},
|
|
80
93
|
];
|
|
81
94
|
class ClaudeService {
|
|
82
|
-
client;
|
|
95
|
+
client = null;
|
|
96
|
+
clientInitPromise = null;
|
|
83
97
|
conversationHistory = new Map();
|
|
84
98
|
onSubagentCreated = null;
|
|
85
99
|
onSubagentUpdated = null;
|
|
@@ -91,15 +105,25 @@ class ClaudeService {
|
|
|
91
105
|
this.useBedrock = USE_BEDROCK;
|
|
92
106
|
if (this.useBedrock) {
|
|
93
107
|
console.log('Using AWS Bedrock for Claude API');
|
|
94
|
-
this.client = new AnthropicBedrock({
|
|
95
|
-
awsRegion: process.env.AWS_REGION || 'us-east-1',
|
|
96
|
-
});
|
|
97
108
|
}
|
|
98
109
|
else {
|
|
99
110
|
console.log('Using Anthropic API directly');
|
|
100
111
|
this.client = new Anthropic();
|
|
101
112
|
}
|
|
102
113
|
}
|
|
114
|
+
// Lazy initialization of client (needed for async Bedrock import)
|
|
115
|
+
async getClient() {
|
|
116
|
+
if (this.client) {
|
|
117
|
+
return this.client;
|
|
118
|
+
}
|
|
119
|
+
if (!this.clientInitPromise) {
|
|
120
|
+
this.clientInitPromise = createBedrockClient().then(client => {
|
|
121
|
+
this.client = client;
|
|
122
|
+
return client;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return this.clientInitPromise;
|
|
126
|
+
}
|
|
103
127
|
getModel() {
|
|
104
128
|
return this.useBedrock ? BEDROCK_MODEL : ANTHROPIC_MODEL;
|
|
105
129
|
}
|
|
@@ -421,7 +445,8 @@ class ClaudeService {
|
|
|
421
445
|
if (abortSignal?.aborted) {
|
|
422
446
|
throw new Error('Request aborted');
|
|
423
447
|
}
|
|
424
|
-
const
|
|
448
|
+
const client = await this.getClient();
|
|
449
|
+
const response = await client.messages.create({
|
|
425
450
|
model: this.getModel(),
|
|
426
451
|
max_tokens: 4096,
|
|
427
452
|
system: `You are a helpful coding assistant working in directory: ${session.cwd}. Help the user with their software engineering tasks. Be concise and direct.
|