agileflow 3.4.2 → 3.4.3
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/CHANGELOG.md +5 -0
- package/README.md +2 -2
- package/lib/drivers/claude-driver.ts +1 -1
- package/lib/lazy-require.js +1 -1
- package/package.json +1 -1
- package/scripts/agent-loop.js +290 -230
- package/scripts/check-sessions.js +116 -0
- package/scripts/lib/quality-gates.js +35 -8
- package/scripts/lib/signal-detectors.js +0 -13
- package/scripts/lib/team-events.js +1 -1
- package/scripts/lib/tmux-audit-monitor.js +2 -1
- package/src/core/commands/ads/audit.md +19 -3
- package/src/core/commands/code/accessibility.md +22 -6
- package/src/core/commands/code/api.md +22 -6
- package/src/core/commands/code/architecture.md +22 -6
- package/src/core/commands/code/completeness.md +22 -6
- package/src/core/commands/code/legal.md +22 -6
- package/src/core/commands/code/logic.md +22 -6
- package/src/core/commands/code/performance.md +22 -6
- package/src/core/commands/code/security.md +22 -6
- package/src/core/commands/code/test.md +22 -6
- package/src/core/commands/ideate/features.md +5 -4
- package/src/core/commands/ideate/new.md +8 -7
- package/src/core/commands/seo/audit.md +21 -5
- package/lib/claude-cli-bridge.js +0 -215
- package/lib/dashboard-automations.js +0 -130
- package/lib/dashboard-git.js +0 -254
- package/lib/dashboard-inbox.js +0 -64
- package/lib/dashboard-protocol.js +0 -605
- package/lib/dashboard-server.js +0 -1296
- package/lib/dashboard-session.js +0 -136
- package/lib/dashboard-status.js +0 -72
- package/lib/dashboard-terminal.js +0 -354
- package/lib/dashboard-websocket.js +0 -88
- package/scripts/dashboard-serve.js +0 -336
- package/src/core/commands/serve.md +0 -127
- package/tools/cli/commands/serve.js +0 -492
|
@@ -1,336 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* dashboard-serve.js - AgileFlow Dashboard WebSocket Server CLI
|
|
5
|
-
*
|
|
6
|
-
* Starts a WebSocket server that the AgileFlow Dashboard can connect to
|
|
7
|
-
* for real-time communication with Claude Code.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* agileflow serve [options]
|
|
11
|
-
* node scripts/dashboard-serve.js [options]
|
|
12
|
-
*
|
|
13
|
-
* Options:
|
|
14
|
-
* --port, -p Port to listen on (default: 8765)
|
|
15
|
-
* --host, -h Host to bind to (default: 0.0.0.0)
|
|
16
|
-
* --api-key, -k API key for authentication
|
|
17
|
-
* --require-auth Require API key for connections
|
|
18
|
-
* --tunnel, -t Start ngrok tunnel (if installed)
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
'use strict';
|
|
22
|
-
|
|
23
|
-
const path = require('path');
|
|
24
|
-
const {
|
|
25
|
-
createDashboardServer,
|
|
26
|
-
startDashboardServer,
|
|
27
|
-
stopDashboardServer,
|
|
28
|
-
} = require('../lib/dashboard-server');
|
|
29
|
-
const {
|
|
30
|
-
createNotification,
|
|
31
|
-
createTextDelta,
|
|
32
|
-
createToolStart,
|
|
33
|
-
createToolResult,
|
|
34
|
-
createAskUserQuestion,
|
|
35
|
-
} = require('../lib/dashboard-protocol');
|
|
36
|
-
const { createClaudeBridge } = require('../lib/claude-cli-bridge');
|
|
37
|
-
|
|
38
|
-
// Parse command line arguments
|
|
39
|
-
function parseArgs() {
|
|
40
|
-
const args = process.argv.slice(2);
|
|
41
|
-
const options = {
|
|
42
|
-
port: 8765,
|
|
43
|
-
host: '0.0.0.0',
|
|
44
|
-
apiKey: null,
|
|
45
|
-
requireAuth: false,
|
|
46
|
-
tunnel: false,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
for (let i = 0; i < args.length; i++) {
|
|
50
|
-
const arg = args[i];
|
|
51
|
-
const next = args[i + 1];
|
|
52
|
-
|
|
53
|
-
switch (arg) {
|
|
54
|
-
case '--port':
|
|
55
|
-
case '-p':
|
|
56
|
-
options.port = parseInt(next, 10);
|
|
57
|
-
i++;
|
|
58
|
-
break;
|
|
59
|
-
case '--host':
|
|
60
|
-
case '-h':
|
|
61
|
-
options.host = next;
|
|
62
|
-
i++;
|
|
63
|
-
break;
|
|
64
|
-
case '--api-key':
|
|
65
|
-
case '-k':
|
|
66
|
-
options.apiKey = next;
|
|
67
|
-
options.requireAuth = true;
|
|
68
|
-
i++;
|
|
69
|
-
break;
|
|
70
|
-
case '--require-auth':
|
|
71
|
-
options.requireAuth = true;
|
|
72
|
-
break;
|
|
73
|
-
case '--tunnel':
|
|
74
|
-
case '-t':
|
|
75
|
-
options.tunnel = true;
|
|
76
|
-
break;
|
|
77
|
-
case '--help':
|
|
78
|
-
printHelp();
|
|
79
|
-
process.exit(0);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return options;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function printHelp() {
|
|
87
|
-
console.log(`
|
|
88
|
-
AgileFlow Dashboard Server
|
|
89
|
-
|
|
90
|
-
Starts a WebSocket server for the AgileFlow Dashboard to connect to.
|
|
91
|
-
|
|
92
|
-
Usage:
|
|
93
|
-
agileflow serve [options]
|
|
94
|
-
node scripts/dashboard-serve.js [options]
|
|
95
|
-
|
|
96
|
-
Options:
|
|
97
|
-
--port, -p <port> Port to listen on (default: 8765)
|
|
98
|
-
--host, -h <host> Host to bind to (default: 0.0.0.0)
|
|
99
|
-
--api-key, -k <key> API key for authentication
|
|
100
|
-
--require-auth Require API key for connections
|
|
101
|
-
--tunnel, -t Start ngrok tunnel (requires ngrok)
|
|
102
|
-
--help Show this help message
|
|
103
|
-
|
|
104
|
-
Examples:
|
|
105
|
-
# Start with default settings
|
|
106
|
-
agileflow serve
|
|
107
|
-
|
|
108
|
-
# Start on custom port with API key
|
|
109
|
-
agileflow serve --port 9000 --api-key agf_secret123
|
|
110
|
-
|
|
111
|
-
# Start with ngrok tunnel
|
|
112
|
-
agileflow serve --tunnel
|
|
113
|
-
|
|
114
|
-
Dashboard Connection:
|
|
115
|
-
The dashboard should connect to ws://localhost:<port>
|
|
116
|
-
Or use the tunnel URL if --tunnel is enabled.
|
|
117
|
-
`);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function printBanner() {
|
|
121
|
-
console.log(`
|
|
122
|
-
╔═══════════════════════════════════════════════════════════╗
|
|
123
|
-
║ ║
|
|
124
|
-
║ █████╗ ██████╗ ██╗██╗ ███████╗███████╗██╗ ║
|
|
125
|
-
║ ██╔══██╗██╔════╝ ██║██║ ██╔════╝██╔════╝██║ ║
|
|
126
|
-
║ ███████║██║ ███╗██║██║ █████╗ █████╗ ██║ ║
|
|
127
|
-
║ ██╔══██║██║ ██║██║██║ ██╔══╝ ██╔══╝ ██║ ║
|
|
128
|
-
║ ██║ ██║╚██████╔╝██║███████╗███████╗██║ ███████╗ ║
|
|
129
|
-
║ ╚═╝ ╚═╝ ╚═════╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚══════╝ ║
|
|
130
|
-
║ ║
|
|
131
|
-
║ Dashboard WebSocket Server ║
|
|
132
|
-
║ ║
|
|
133
|
-
╚═══════════════════════════════════════════════════════════╝
|
|
134
|
-
`);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function startTunnel(port) {
|
|
138
|
-
try {
|
|
139
|
-
const { exec } = require('child_process');
|
|
140
|
-
|
|
141
|
-
return new Promise((resolve, reject) => {
|
|
142
|
-
// Check if ngrok is installed
|
|
143
|
-
exec('which ngrok', error => {
|
|
144
|
-
if (error) {
|
|
145
|
-
console.log(' Tunnel: ngrok not found. Install with: npm install -g ngrok');
|
|
146
|
-
resolve(null);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Start ngrok tunnel
|
|
151
|
-
const ngrok = exec(`ngrok http ${port} --log stdout`, { encoding: 'utf8' });
|
|
152
|
-
|
|
153
|
-
ngrok.stdout.on('data', data => {
|
|
154
|
-
// Parse ngrok output for public URL
|
|
155
|
-
const urlMatch = data.match(/url=(https?:\/\/[^\s]+)/);
|
|
156
|
-
if (urlMatch) {
|
|
157
|
-
const tunnelUrl = urlMatch[1].replace('https://', 'wss://').replace('http://', 'ws://');
|
|
158
|
-
console.log(` Tunnel: ${tunnelUrl}`);
|
|
159
|
-
resolve(tunnelUrl);
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
ngrok.stderr.on('data', data => {
|
|
164
|
-
console.error(' Tunnel error:', data);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// Give ngrok a moment to start
|
|
168
|
-
setTimeout(() => {
|
|
169
|
-
if (!ngrok.killed) {
|
|
170
|
-
console.log(' Tunnel: Starting... check ngrok dashboard');
|
|
171
|
-
resolve(null);
|
|
172
|
-
}
|
|
173
|
-
}, 5000);
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
} catch (error) {
|
|
177
|
-
console.log(' Tunnel: Failed to start -', error.message);
|
|
178
|
-
return null;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
async function main() {
|
|
183
|
-
const options = parseArgs();
|
|
184
|
-
|
|
185
|
-
printBanner();
|
|
186
|
-
|
|
187
|
-
console.log('Starting server...\n');
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
// Create server
|
|
191
|
-
const server = createDashboardServer({
|
|
192
|
-
port: options.port,
|
|
193
|
-
host: options.host,
|
|
194
|
-
apiKey: options.apiKey,
|
|
195
|
-
requireAuth: options.requireAuth,
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
// Set up event handlers
|
|
199
|
-
setupEventHandlers(server);
|
|
200
|
-
|
|
201
|
-
// Start server
|
|
202
|
-
const { wsUrl } = await startDashboardServer(server);
|
|
203
|
-
|
|
204
|
-
// Start tunnel if requested
|
|
205
|
-
if (options.tunnel) {
|
|
206
|
-
await startTunnel(options.port);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
console.log('─────────────────────────────────────────────────────────────');
|
|
210
|
-
console.log('');
|
|
211
|
-
console.log(' Ready! Connect your dashboard to:');
|
|
212
|
-
console.log(` ${wsUrl}`);
|
|
213
|
-
console.log('');
|
|
214
|
-
if (options.apiKey) {
|
|
215
|
-
console.log(` API Key: ${options.apiKey.slice(0, 8)}...`);
|
|
216
|
-
console.log('');
|
|
217
|
-
}
|
|
218
|
-
console.log(' Press Ctrl+C to stop.');
|
|
219
|
-
console.log('');
|
|
220
|
-
console.log('─────────────────────────────────────────────────────────────');
|
|
221
|
-
console.log('');
|
|
222
|
-
|
|
223
|
-
// Handle shutdown
|
|
224
|
-
const shutdown = async () => {
|
|
225
|
-
console.log('\nShutting down...');
|
|
226
|
-
await stopDashboardServer(server);
|
|
227
|
-
process.exit(0);
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
process.on('SIGINT', shutdown);
|
|
231
|
-
process.on('SIGTERM', shutdown);
|
|
232
|
-
} catch (error) {
|
|
233
|
-
console.error('Failed to start server:', error.message);
|
|
234
|
-
process.exit(1);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Set up event handlers for the dashboard server
|
|
240
|
-
*/
|
|
241
|
-
function setupEventHandlers(server) {
|
|
242
|
-
// Session events
|
|
243
|
-
server.on('session:connected', (sessionId, session) => {
|
|
244
|
-
console.log(`[${new Date().toISOString()}] Session connected: ${sessionId}`);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
server.on('session:disconnected', sessionId => {
|
|
248
|
-
console.log(`[${new Date().toISOString()}] Session disconnected: ${sessionId}`);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// User message handler - use Claude CLI bridge
|
|
252
|
-
server.on('user:message', async (session, content) => {
|
|
253
|
-
console.log(
|
|
254
|
-
`[${new Date().toISOString()}] Message from ${session.id}: ${content.slice(0, 50)}...`
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
try {
|
|
258
|
-
await handleClaudeMessage(session, content, server.projectRoot);
|
|
259
|
-
} catch (error) {
|
|
260
|
-
console.error(`[${new Date().toISOString()}] Claude error:`, error.message);
|
|
261
|
-
session.send(createNotification('error', 'Error', error.message));
|
|
262
|
-
session.setState('error');
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
// Cancel handler
|
|
267
|
-
server.on('user:cancel', session => {
|
|
268
|
-
console.log(`[${new Date().toISOString()}] Cancel from ${session.id}`);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
// Refresh handlers
|
|
272
|
-
server.on('refresh:tasks', session => {
|
|
273
|
-
// Send task list update
|
|
274
|
-
console.log(`[${new Date().toISOString()}] Task refresh for ${session.id}`);
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
server.on('refresh:status', session => {
|
|
278
|
-
// Send status update
|
|
279
|
-
console.log(`[${new Date().toISOString()}] Status refresh for ${session.id}`);
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Handle message by calling Claude CLI
|
|
285
|
-
*/
|
|
286
|
-
async function handleClaudeMessage(session, content, projectRoot) {
|
|
287
|
-
let fullResponse = '';
|
|
288
|
-
|
|
289
|
-
const bridge = createClaudeBridge({
|
|
290
|
-
cwd: projectRoot,
|
|
291
|
-
onInit: info => {
|
|
292
|
-
console.log(
|
|
293
|
-
`[${new Date().toISOString()}] Claude session: ${info.sessionId}, model: ${info.model}`
|
|
294
|
-
);
|
|
295
|
-
},
|
|
296
|
-
onText: (text, done) => {
|
|
297
|
-
if (text) {
|
|
298
|
-
fullResponse += text;
|
|
299
|
-
session.send(createTextDelta(text, done));
|
|
300
|
-
}
|
|
301
|
-
if (done) {
|
|
302
|
-
session.addMessage('assistant', fullResponse);
|
|
303
|
-
session.setState('idle');
|
|
304
|
-
console.log(`[${new Date().toISOString()}] Response complete`);
|
|
305
|
-
}
|
|
306
|
-
},
|
|
307
|
-
onToolStart: (id, name, input) => {
|
|
308
|
-
// Special handling for AskUserQuestion - send to dashboard for UI
|
|
309
|
-
if (name === 'AskUserQuestion' && input?.questions) {
|
|
310
|
-
session.send(createAskUserQuestion(id, input.questions));
|
|
311
|
-
}
|
|
312
|
-
session.send(createToolStart(id, name, input));
|
|
313
|
-
},
|
|
314
|
-
onToolResult: (id, output, isError, toolName) => {
|
|
315
|
-
session.send(createToolResult(id, { content: output, error: isError }, toolName));
|
|
316
|
-
},
|
|
317
|
-
onError: error => {
|
|
318
|
-
console.error(`[${new Date().toISOString()}] Claude error:`, error);
|
|
319
|
-
session.send(createNotification('error', 'Claude Error', error));
|
|
320
|
-
},
|
|
321
|
-
onComplete: response => {
|
|
322
|
-
// Already handled in onText with done=true
|
|
323
|
-
},
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
try {
|
|
327
|
-
await bridge.sendMessage(content);
|
|
328
|
-
} catch (error) {
|
|
329
|
-
session.send(createNotification('error', 'Error', error.message));
|
|
330
|
-
session.setState('error');
|
|
331
|
-
throw error;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Run main
|
|
336
|
-
main().catch(console.error);
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Start Dashboard WebSocket server for real-time UI communication
|
|
3
|
-
argument-hint: "[OPTIONS: --port 8765 --api-key KEY --tunnel]"
|
|
4
|
-
compact_context:
|
|
5
|
-
priority: medium
|
|
6
|
-
preserve_rules:
|
|
7
|
-
- "ACTIVE COMMAND: /agileflow:serve - Dashboard WebSocket server"
|
|
8
|
-
- "Server provides real-time communication for Cloud Dashboard"
|
|
9
|
-
- "Default port: 8765, binds to 0.0.0.0"
|
|
10
|
-
state_fields:
|
|
11
|
-
- server_running
|
|
12
|
-
- server_port
|
|
13
|
-
- tunnel_url
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
# serve
|
|
17
|
-
|
|
18
|
-
Start the AgileFlow Dashboard WebSocket server for real-time communication with the Cloud Dashboard UI.
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Overview
|
|
23
|
-
|
|
24
|
-
The serve command starts a WebSocket server that the AgileFlow Dashboard connects to for real-time features: chat streaming, git operations, terminal access, and automation management.
|
|
25
|
-
|
|
26
|
-
**Key Features**:
|
|
27
|
-
- **WebSocket protocol**: Real-time bidirectional communication with dashboard
|
|
28
|
-
- **Claude CLI bridge**: Streaming text deltas and tool call forwarding
|
|
29
|
-
- **Git integration**: Status, diff, commit, branch operations via WebSocket
|
|
30
|
-
- **Terminal channels**: Remote terminal sessions scoped to project directory
|
|
31
|
-
- **Automation runner**: Trigger and monitor automations from the dashboard
|
|
32
|
-
- **Auth support**: Optional API key authentication for secure connections
|
|
33
|
-
- **Tunnel support**: ngrok integration for remote access
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## Usage
|
|
38
|
-
|
|
39
|
-
### Start with Default Settings
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
/agileflow:serve
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Starts the WebSocket server on port 8765, binding to 0.0.0.0.
|
|
46
|
-
|
|
47
|
-
### Start with Custom Port and Auth
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
/agileflow:serve --port 9000 --api-key agf_secret123
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Start with Tunnel for Remote Access
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
/agileflow:serve --tunnel
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Starts ngrok tunnel for remote dashboard connections (requires ngrok installed).
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## Options
|
|
64
|
-
|
|
65
|
-
| Option | Short | Default | Description |
|
|
66
|
-
|--------|-------|---------|-------------|
|
|
67
|
-
| `--port` | `-p` | `8765` | Port to listen on |
|
|
68
|
-
| `--host` | `-h` | `0.0.0.0` | Host to bind to |
|
|
69
|
-
| `--api-key` | `-k` | none | API key for authentication |
|
|
70
|
-
| `--require-auth` | | `false` | Require API key for connections |
|
|
71
|
-
| `--tunnel` | `-t` | `false` | Start ngrok tunnel |
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## Prompt
|
|
76
|
-
|
|
77
|
-
ROLE: Dashboard Server Manager
|
|
78
|
-
|
|
79
|
-
Run the dashboard WebSocket server using the installed script:
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
node .agileflow/scripts/dashboard-serve.js [OPTIONS]
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
**Pass through any user-provided options** (--port, --api-key, --tunnel, etc.) directly to the script.
|
|
86
|
-
|
|
87
|
-
WORKFLOW:
|
|
88
|
-
|
|
89
|
-
1. **Start the server**:
|
|
90
|
-
```bash
|
|
91
|
-
node .agileflow/scripts/dashboard-serve.js --port 8765
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
2. **Report the connection URL** to the user:
|
|
95
|
-
- Local: `ws://localhost:<port>`
|
|
96
|
-
- If tunnel enabled: the ngrok URL
|
|
97
|
-
|
|
98
|
-
3. **Keep the server running** - it runs in the foreground. The user can stop it with Ctrl+C.
|
|
99
|
-
|
|
100
|
-
4. If the user specifies `--api-key`, pass it through:
|
|
101
|
-
```bash
|
|
102
|
-
node .agileflow/scripts/dashboard-serve.js --port 8765 --api-key agf_secret123
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
5. If the user specifies `--tunnel`, pass it through:
|
|
106
|
-
```bash
|
|
107
|
-
node .agileflow/scripts/dashboard-serve.js --tunnel
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## Dashboard Connection
|
|
113
|
-
|
|
114
|
-
Once the server is running, the Cloud Dashboard connects via WebSocket:
|
|
115
|
-
|
|
116
|
-
1. Open the AgileFlow Dashboard
|
|
117
|
-
2. Enter the connection URL: `ws://localhost:8765` (or tunnel URL)
|
|
118
|
-
3. If auth is enabled, provide the API key
|
|
119
|
-
4. Dashboard receives real-time updates for chat, git, terminal, and automations
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## Related Commands
|
|
124
|
-
|
|
125
|
-
- `/agileflow:api` - REST API server (read-only state exposure)
|
|
126
|
-
- `/agileflow:session:status` - View current session state
|
|
127
|
-
- `/agileflow:board` - Visual kanban board
|