Commit Graph
185 Commits
Author SHA1 Message Date
arkonandClaude Opus 4.6 97ca13916a refactor: consolidate ~70 scattered constants into 6 new config files (phase 6)
Create 6 domain-focused config files in src/config/ to centralize operational
tuning knobs that were scattered across 15+ source files:

- server-timing.ts: SSE batching, state debounce, scheduled runs, error recovery
- auth-config.ts: session TTL, rate limits, hook timeout
- tunnel-config.ts: QR token rotation, tunnel process lifecycle
- terminal-limits.ts: input length, terminal cols/rows, session name
- ai-defaults.ts: AI model string, idle/plan context limits
- team-config.ts: poll interval, cache sizes

Eliminates all cross-file duplicates:
- AI model string: 5 occurrences → 1 (config only)
- STATS_COLLECTION_INTERVAL_MS: 2 → 1
- timeout: 10000 in hooks-config: 6 → 0 (now HOOK_TIMEOUT_MS)
- MAX_TRACKED_AGENTS shadow: removed, imports from map-limits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:19:16 +01:00
arkonandClaude Opus 4.6 746004c461 feat: implement QR code authentication for tunnel access
Adds ephemeral single-use QR tokens for passwordless tunnel login.
Scanning the QR auto-authenticates; bare tunnel URL requires Basic Auth.

Backend:
- TunnelManager: 60s token rotation, 90s grace, rejection-sampled 6-char
  base62 short codes, Map-based O(1) lookup, SVG caching, global rate limit
- Auth middleware: /q/ bypass, separate qrAuthFailures counter, enhanced
  AuthSessionRecord with device context (ip, ua, createdAt, method)
- Routes: GET /q/:code (consume + cookie + redirect), POST /api/tunnel/qr/
  regenerate, POST /api/auth/revoke, updated GET /api/tunnel/qr with cache
- SSE: tunnel:qrRotated, tunnel:qrRegenerated, tunnel:qrAuthUsed events
- Audit: qr_auth lifecycle log entries

Frontend:
- Auto-refresh QR via inline SVG in SSE (fallback fetch if absent)
- 60s countdown indicator on QR badge
- Regenerate QR button
- QRLjacking detection toast with [Revoke All] action button (10s duration)
- showToast enhanced with optional duration and action button support

Fixes:
- /api/logout now invalidates server-side session token (was only clearing
  browser cookie, leaving token valid for replay)

Tests: 20 new tests in test/qr-auth.test.ts covering token lifecycle,
bias check, rate limiting, SVG caching, and full server integration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 06:05:26 +01:00
arkonandClaude Opus 4.6 a27be18a5a fix: address review findings from route extraction refactor
- Add addSession() to SessionPort, replacing unsafe ReadonlyMap casts
- Restore getLightSessionsState() 1s TTL cache for GET /api/sessions
- Deduplicate AUTH_COOKIE_NAME, CASES_DIR, SETTINGS_PATH constants
- Fix eslint no-require-imports error in system-routes.ts
- Remove unused imports (homedir) from cleaned-up route modules

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:26:08 +01:00
arkonandClaude Opus 4.6 e05d507254 refactor: extract server.ts routes into domain modules (phase 3)
Split 6,710-line server.ts into focused route modules using port
interfaces for dependency injection. 107/109 routes extracted into
12 domain files with auth middleware, 5 port interfaces, and shared
helpers. Server.ts retains orchestration (SSE, lifecycle, state).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:12:45 +01:00
arkonandClaude Opus 4.6 e0a2774d37 perf: implement phase 1-3 performance optimizations
Add implementation plans and code structure analysis for a 3-phase
performance optimization effort. Refactor core modules to reduce
timer overhead, consolidate regex usage, extract exec timeout config,
add debouncer utility, and streamline server/schema validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:39:44 +01:00
arkonandClaude Opus 4.6 db550a0e28 fix: format server.ts to pass CI prettier check
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 14:50:59 +01:00
arkonandClaude Opus 4.6 db8ee8458c chore: version packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 14:45:39 +01:00
arkonandClaude Opus 4.6 9d9f4d323c chore: version packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 01:35:37 +01:00
arkonandClaude Opus 4.6 1ab1dd100a style: fix prettier formatting in server.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 01:00:36 +01:00
arkonandClaude Opus 4.6 ec7244fa5b chore: version packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:55:16 +01:00
arkonandClaude Opus 4.6 6053593813 chore: version packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 17:54:59 +01:00
arkonandClaude Opus 4.6 1b0a540919 fix: tunnel button stuck on "Connecting..." when already running
Re-broadcast tunnel:started SSE event when tunnel is already active
and user toggles the setting, so the client receives the URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 16:31:31 +01:00
480584de63 chore: project setup and tooling cleanup (#26)
* add project setup

* add tools to eslint

* remove contributing.md

* update claude md

* chore: simplify CI to single Node.js version (22)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* use node 20

* adjust formatting

* fix linting

* format

* fix layout

* fix: align CI node version to .nvmrc (22), remove redundant gotcha

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: arkon <arkon.85@hotmail.com>
2026-02-27 13:16:23 +01:00
arkon b99821cd10 fix: tunnel stop respawning + fix pre-existing TS errors 2026-02-27 08:54:00 +01:00
arkon 8038145d40 chore: bump version to 0.1658 2026-02-27 08:53:30 +01:00
arkonandClaude Opus 4.6 c668f9bae1 chore: bump version to 0.1656
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 08:28:30 +01:00
arkonandClaude Opus 4.6 8fc0dc8c2e chore: bump version to 0.1655
Security hardening: timing-safe auth comparison, localhost-only hook bypass,
SSE client limit, TLS key permissions, strict settings schema, logout endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 01:13:58 +01:00
arkonandClaude Opus 4.6 f699002cbf chore: bump version to 0.1654
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 01:07:03 +01:00
arkon 5f1f66bf60 chore: bump version to 0.1652 2026-02-27 00:34:38 +01:00
arkonandClaude Opus 4.6 3795c45cc1 chore: rename Claudeman to Codeman
Full product rename across 109 files (~834 occurrences):
- Env vars: CLAUDEMAN_* → CODEMAN_*
- Data dirs: ~/.claudeman/ → ~/.codeman/, ~/claudeman-cases/ → ~/codeman-cases/
- tmux prefix: claudeman- → codeman-
- localStorage: claudeman-* → codeman-*
- Package/CLI: claudeman → codeman
- GitHub repo: Ark0N/Claudeman → Ark0N/Codeman
- systemd service: claudeman-web → codeman-web
- Class: ClaudemanApp → CodemanApp

Migration infrastructure for seamless transition:
- state-store.ts: auto-migrates data directories on startup
- tmux-manager.ts: dual-prefix detection (legacy claudeman- sessions)
- app.js: localStorage key migration (preserves old keys)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 16:44:34 +01:00
arkonandClaude Opus 4.6 a899a8b67a fix: address code review findings for OpenCode integration
- Add _isStopped guard to OpenCode 3s readiness timeout (session.ts)
- Block respawn for opencode sessions on interactive-respawn and
  respawn/enable routes (server.ts)
- Fail fast in direct PTY fallback for OpenCode mode (session.ts)
- Validate configContent as JSON at schema level (schemas.ts)
- Update JSDoc example for createSession options API (tmux-manager.ts)
- Un-hide Context tab for OpenCode sessions (index.html)
- Add OpenCode UI tests (opencode-resize.test.ts)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:58:26 +01:00
arkonandClaude Opus 4.6 33f39c91ba fix: update mobile CSS for OpenCode run button group
Replace dead .btn-claude selectors in mobile.css with proper styling
for the new split run button (.btn-run + .btn-run-gear). Add mobile
touch-friendly dropdown menu options (10px padding, 35px height).
Include mode-specific colors for both Claude (blue) and OpenCode
(green) on mobile. Also guard Claude-specific features (Ralph,
Respawn) from running on OpenCode sessions in server.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:06:36 +01:00
arkonandClaude Opus 4.6 2e3a08fad2 fix: emit needsRefresh after OpenCode TUI stabilizes
After the 3s TUI stabilization timeout, emit needsRefresh so the
client fetches the full terminal buffer. Without this, the terminal
appears empty until the user manually refreshes or switches tabs.

Wire needsRefresh as a proper session listener in server.ts with
cleanup in both removal paths to prevent memory leaks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-26 13:03:28 +01:00
arkonandClaude Opus 4.6 02f3bea3c1 feat: OpenCode integration Phase 5 — API routes, frontend UI
API changes:
- GET /api/opencode/status — check if OpenCode CLI is available
- POST /api/sessions — support mode: 'opencode' with openCodeConfig
- POST /api/quick-start — support mode: 'opencode', guard writeHooksConfig
- Fix hardcoded mode: 'claude' in lifecycle logs (use session.mode)

Schema changes:
- Add 'opencode' to mode enums in CreateSessionSchema, QuickStartSchema
- Add OpenCodeConfigSchema (model, autoAllowTools, continueSession, etc.)
- Add 'OPENCODE_' to ALLOWED_ENV_PREFIXES
- Block OPENCODE_SERVER_PASSWORD in BLOCKED_ENV_KEYS (atomic with prefix addition)

Frontend UI:
- "Run OC" button in toolbar + "Run OpenCode" on welcome screen
- Green "oc" tab badge for OpenCode sessions (matching green brand)
- runOpenCode() method — checks availability, quick-starts with autoAllowTools
- Feature gating: hide Respawn/Context/Ralph tabs for OpenCode sessions
- Session options defaults to Summary tab for OpenCode
- CSS: OpenCode button styles, tab badge styles

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-26 10:16:20 +01:00
arkonandClaude Opus 4.6 fd0b75c9a5 chore: bump version to 0.1640
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:40:55 +01:00
arkonandClaude Opus 4.6 5170c188c3 fix: respect Claude CLI startup mode setting (#12)
The "Startup Mode" setting (normal/bypass/allowedTools) was saved to
settings but never read when spawning sessions. All code paths had
--dangerously-skip-permissions hardcoded. Now reads claudeMode from
~/.claudeman/settings.json and passes it through Session → TmuxManager.

Closes #12

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 15:52:55 +01:00
arkon 37af7ead20 chore: bump version to 0.1614 2026-02-24 13:36:42 +01:00
arkonandClaude Opus 4.6 819b1771c3 chore: bump version to 0.1580
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:04:45 +01:00
arkon 3f9632c8c7 chore: bump version to 0.1579 2026-02-20 14:33:06 +01:00
arkonandClaude Opus 4.6 868d4f1196 perf: fix memory leaks — strip task outputs from SSE broadcasts, use light state everywhere
- TaskTracker.getTaskTreeLight(): strips large `output` strings from tasks
  in SSE broadcasts (was serializing 5-10MB every 500ms with many subagents)
- session:created broadcasts now use toLightDetailedState() (consistent with
  session:updated which already did)
- GET /api/sessions/:id returns light state (no 2-3MB terminal+text buffers)
- Ralph wizard polls /terminal?tail=2048 instead of full session endpoint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 06:50:59 +01:00
arkon 5b882c448e chore: bump version to 0.1570 2026-02-20 06:09:28 +01:00
arkon 99ad44e907 perf: speed up session creation by ~500ms — remove redundant sleep, reduce tmux wait, fire-and-forget config 2026-02-20 04:30:02 +01:00
arkon 1b21e1b8d8 fix: server shutdown no longer kills tmux sessions — detach instead of cleanup
Previously, server.stop() called cleanupSession(killMux=false) for all sessions,
which still tore down session state, removed listeners, killed PTY processes via
node-pty SIGHUP, and broadcast session:deleted. This caused Claude sessions
running inside tmux to be disrupted during COM deploys.

Now server shutdown just persists state, removes listeners, and lets the Node.js
process exit naturally. The tmux sessions survive independently, and
restoreMuxSessions() finds them alive on restart.

Also adds defense-in-depth in session.stop(): when killMux=false, skip PTY kill
entirely (just null the reference). And adds 'detached' lifecycle event type for
accurate audit logging.
2026-02-19 22:15:36 +01:00
arkonandClaude Opus 4.6 383ed5e5a0 feat: session lifecycle audit log — append-only JSONL at ~/.claudeman/session-lifecycle.jsonl
Records every session create, start, exit, delete, recover, stale-clean,
mux-died, and server start/stop with timestamps, names, reasons, and exit
codes. Survives server restarts (unlike in-memory RunSummary).

- New SessionLifecycleLog singleton (src/session-lifecycle-log.ts)
- LifecycleEventType + LifecycleEntry types in types.ts
- GET /api/session-lifecycle endpoint with sessionId/event/since/limit filters
- cleanupSession() now takes reason parameter for audit trail
- state-store cleanupStaleSessions returns cleaned session IDs+names
- UI: lifecycle log modal accessible from header clipboard icon
- Auto-trims to 8k entries when exceeding 10k on server start

chore: bump version to 0.1556

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:30:14 +01:00
arkonandClaude Opus 4.6 fe1f665531 fix: ralph tracker — 3 bugs: first-occurrence completion, double-counting, TodoWrite pattern
Bug 1 (CRITICAL): canonicalCount >= 1 always fired on first <promise> tag
(prompt echo). Changed to >= 2 so only 2nd+ occurrence triggers completion.

Bug 2: checkMultiLinePatterns() re-detected complete tags already handled
by processLine(), double-counting. Now only tries completion when partial
buffer is non-empty (cross-chunk scenario).

Bug 3: TodoWrite ✔ patterns required "Task #N" but real Claude Code output
is plain "✔ content". Added TODO_PLAIN_CHECKMARK_PATTERN fallback.

Includes 71 new deep tests + real-life verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 14:00:10 +01:00
arkon 926e77b1c2 chore: bump version to 0.1550 2026-02-19 08:49:36 +01:00
arkon 1833a9ac2d chore: bump version to 0.1549 2026-02-18 23:14:39 +01:00
arkonandClaude Opus 4.6 d7ad617d7f chore: bump version to 0.1545
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:53:34 +01:00
arkon 88422cab57 chore: bump version to 0.1538 2026-02-18 12:51:35 +01:00
arkonandClaude Opus 4.6 c548c2d6ee fix: mobile keyboard handlers killed on SSE reconnect — re-init after cleanup
handleInit() called KeyboardHandler.cleanup() and MobileDetection.cleanup()
on every SSE connect but never re-initialized them, breaking keyboard
scroll-into-view and the /init /clear accessory bar on mobile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:59:42 +01:00
arkon 62ddfdea36 chore: bump version to 0.1531 2026-02-18 10:23:10 +01:00
arkon 50b17184ee chore: bump version to 0.1529 2026-02-18 07:28:15 +01:00
arkonandClaude Opus 4.6 31d3e7bc70 chore: bump version to 0.1528
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 07:06:34 +01:00
arkon 9d67a571ba chore: bump version to 0.1527 2026-02-18 05:36:20 +01:00
arkon 4fd8174680 chore: bump version to 0.1524 2026-02-17 16:47:54 +01:00
arkon ea3e534607 chore: bump version to 0.1520 2026-02-16 21:19:16 +01:00
arkonandClaude Opus 4.6 da74ac248b fix: mobile keyboard layout — scroll-to-bottom on show, robust dismiss detection
Three bugs fixed in KeyboardHandler:
1. onKeyboardShow() used sessionData.terminal (always undefined) instead of app.terminal
2. Keyboard dismiss threshold (50px) too tight for iOS address bar drift — widened to 100px
3. No terminal refit on keyboard hide — caused black gap below terminal

Also added: dynamic baseline update for initialViewportHeight, safety check in
updateLayoutForKeyboard() that forces dismiss when keyboardOffset <= 0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 12:10:44 +01:00
arkonandClaude Opus 4.6 9ab62adfa8 fix: medium severity audit fixes — races, leaks, perf, warnings
- Clear teams/teamTasks maps in handleInit() on SSE reconnect
- Fix saveNowAsync() race condition with in-flight promise guard
- Add setMaxListeners() on Session, WebServer, SubagentWatcher,
  ImageWatcher, TmuxManager to prevent MaxListenersExceeded warnings
- Debounce persistSessionState() per-session (100ms) to reduce
  redundant toState() serialization across 25+ call sites
- Cache getLightSessionsState() with 1s TTL to avoid re-serializing
  all sessions on every SSE connect and /api/sessions request

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 05:33:34 +01:00
arkonandClaude Opus 4.6 f223501164 fix: async I/O, map iteration bug, unified cleanup, Zod validation, error handling
- Convert sync readFileSync/statSync to async in subagent-watcher.ts to
  unblock event loop on hot paths (transcript reads, liveness checks)
- Fix Map mutation during iteration in closeSessionLogViewerWindows and
  closeSessionImagePopups (collect IDs first, then iterate to close)
- Unify session cleanup into shared _cleanupSessionData() method called
  from both closeSession() and session:deleted handler to prevent leaks
- Add Zod validation schemas for 20+ API routes that used raw type casts
- Add consecutive error tracking (5 errors/60s triggers exit for systemd
  restart) and SIGHUP handler for SSH disconnect safety

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 05:26:29 +01:00
arkon 641fd28211 chore: bump version to 0.1504 2026-02-13 21:21:33 +01:00