feat: matrix-style subagent connection lines + smart window layout

Subagent windows now visually connect to their parent session tabs with
glowing matrix-green lines that pulse with life. Windows automatically
arrange in a non-overlapping grid, and each shows its origin with a
clickable "from [session]" header.

Watch your AI agents spawn and dance across the screen, tethered to
their creators by neon threads of digital consciousness.

Changes:
- Matrix green (#00ff41) connection lines with glow effect
- Smart grid positioning prevents window overlap
- Smaller default window size (420x350) for better density
- Auto-sizing activity columns for cleaner logs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-25 23:55:53 +01:00
co-authored by Claude Opus 4.5
parent 23022b533d
commit c4b737bc15
4 changed files with 25 additions and 14 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ When user says "COM": 1) Increment version in BOTH `package.json` AND `CLAUDE.md
Claudeman is a Claude Code session manager with a web interface and autonomous Ralph Loop. It spawns Claude CLI processes via PTY, streams output in real-time via SSE, and supports scheduled/timed runs.
**Version**: 0.1370 (must match `package.json`)
**Version**: 0.1371 (must match `package.json`)
**Tech Stack**: TypeScript (ES2022/NodeNext, strict mode), Node.js, Fastify, Server-Sent Events, node-pty
+3 -2
View File
@@ -1,6 +1,6 @@
{
"name": "claudeman",
"version": "0.1370",
"version": "0.1371",
"description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence",
"type": "module",
"main": "dist/index.js",
@@ -55,8 +55,9 @@
"@types/uuid": "^10.0.0",
"@vitest/coverage-v8": "^4.0.17",
"agent-browser": "^0.6.0",
"playwright": "^1.58.0",
"tsx": "^4.15.0",
"typescript": "^5.5.0",
"typescript": "^5.9.3",
"vitest": "^4.0.17"
},
"engines": {
+11 -3
View File
@@ -5098,10 +5098,18 @@ class ClaudemanApp {
const agent = this.subagents.get(agentId);
if (!agent) return;
// Calculate final position (cascade from top-left)
// Calculate final position - grid layout to avoid overlaps
const windowCount = this.subagentWindows.size;
const finalX = 50 + (windowCount % 5) * 30;
const finalY = 100 + (windowCount % 5) * 30;
const windowWidth = 420;
const windowHeight = 350;
const gap = 20;
const startX = 50;
const startY = 120;
const maxCols = Math.floor((window.innerWidth - startX - 50) / (windowWidth + gap)) || 1;
const col = windowCount % maxCols;
const row = Math.floor(windowCount / maxCols);
const finalX = startX + col * (windowWidth + gap);
const finalY = startY + row * (windowHeight + gap);
// Get parent tab position for spawn animation
const parentTab = agent.parentSessionId
+10 -8
View File
@@ -3819,10 +3819,10 @@ kbd {
.subagent-window {
position: fixed;
width: 500px;
height: 400px;
min-width: 300px;
min-height: 200px;
width: 420px;
height: 350px;
min-width: 280px;
min-height: 180px;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 8px;
@@ -3980,17 +3980,19 @@ kbd {
}
.connection-line {
stroke: var(--accent);
stroke: #00ff41;
stroke-width: 2;
stroke-dasharray: 5 3;
fill: none;
opacity: 0.5;
transition: opacity 0.2s, stroke-width 0.2s;
opacity: 0.6;
filter: drop-shadow(0 0 3px #00ff41);
transition: opacity 0.2s, stroke-width 0.2s, filter 0.2s;
}
.connection-line:hover {
opacity: 0.8;
opacity: 1;
stroke-width: 3;
filter: drop-shadow(0 0 6px #00ff41);
}
.connection-line.spawning-line {