Skip to content

feat: Add detached mode for long-running agent sessions#15

Merged
khaliqgant merged 92 commits into
claude/analyze-mcp-agent-mail-IXbNFfrom
claude/continue-pr-8-7tWzb
Dec 25, 2025
Merged

feat: Add detached mode for long-running agent sessions#15
khaliqgant merged 92 commits into
claude/analyze-mcp-agent-mail-IXbNFfrom
claude/continue-pr-8-7tWzb

Conversation

@khaliqgant

Copy link
Copy Markdown
Member

Add -d/--detach flag to start agents in background, allowing SSH users
to disconnect without losing agent sessions. Includes attach/kill commands
for session management.

claude and others added 30 commits December 20, 2025 12:20
Design document for storing task conversations and agent reasoning
as first-class artifacts. Covers storage architecture, capture
mechanisms, retrospectives, and how trajectories help with code
review, bug diagnosis, and institutional memory.
- Add TaskReference abstraction (works with Beads, Linear, Jira, GitHub, or standalone)
- Define universal .trajectory file format (JSON primary, Markdown generated)
- Add TaskSourceAdapter interface for pluggable task systems
- Show multiple reading experiences: Notion-style pages, Linear-style timelines, Git integration, CLI
- Update storage to support file system, SQLite, PostgreSQL, S3
- Revise migration path to prioritize format and adapters
Link to tweet and Pragmatic Engineer article on agent trajectories.
Include related observations on why trajectory capture matters:
more code faster, parallel agent work, bug diagnosis needs.
Add comprehensive "Notion for Agents" section:
- Knowledge workspace concept (decisions, patterns, knowledge base)
- Data model for AgentWorkspace, DecisionLog, PatternLibrary
- Population strategies (automatic, agent contribution, human curation)
- Query interface with contextual suggestions
- Flywheel effect for continuous improvement

Add claude-mem integration section:
- Comparison table (observation layer vs task layer)
- Agent Memory Stack diagram showing complementary roles
- Integration strategies (shared storage, cross-query, hooks)
- Export/import between formats
Add "Architecture: Separate Providers in a Stack" section showing:
- Each layer is an independent project (agent-relay, claude-mem,
  agent-trajectories, agent-workspace)
- Projects can be used alone or composed together
- Integration points between layers
- Why separate projects (independent adoption, different maintainers,
  cleaner dependencies)
- agent-relay as the communication substrate
- Remove agent-workspace as separate Layer 4
- Show workspace as nested feature within agent-trajectories
- Add project structure showing workspace/ as opt-in module
- Explain why combined: flywheel effect, simpler UX, derived data

Stack is now 3 separate providers:
1. agent-relay (messaging)
2. claude-mem (observations)
3. agent-trajectories (narratives + workspace)
Export StoredMessage, MessageQuery, StorageAdapter, and StorageConfig
types so agent-trajectories can import messages from agent-relay.

Example usage:
  import { StoredMessage, MessageQuery } from 'agent-relay';
Comprehensive guide covering:
- Phase 0: Current state (agent-relay, claude-mem)
- Phase 1: Installing claude-mem
- Phase 2: Creating agent-trajectories project structure
- Phase 3: agent-relay integration (import messages)
- Phase 4: claude-mem integration (import observations)
- Phase 5: Hook integration (combined hooks config)
- Phase 6: Complete setup and workflow

Includes code examples, data flow diagrams, and setup checklist.
- Add isInputClear() to detect empty input buffer via prompt pattern matching
- Add getCursorX() to get cursor position for stability detection
- Add waitForClearInput() loop-wait mechanism that polls until input is clear
- Integrate input detection into injectNextMessage() - waits for clear input
  before injecting, falls back to forceful clear only on timeout
- Add configurable inputWaitTimeoutMs and inputWaitPollMs options
- Add dev:local, dev:unlink, dev:rebuild npm scripts for local development
…mmary tracking

- Move SQLite storage from /tmp to ~/.agent-relay (fixes data loss on reboot)
- Support XDG_DATA_HOME and AGENT_RELAY_DATA_DIR env overrides
- Add sessions table to track agent connection history
- Add agent_summaries table for running agent context
- Record session start/end in daemon on connect/disconnect
- Add [[SUMMARY]] block parsing in wrapper for agent summaries
- Update dashboard API to include sessions and summaries data
- Dashboard now shows recent sessions and agent summaries

Closes: agent-relay-kzw (SQLite in /tmp cleared on reboot)
- Add [[SESSION_END]]...[[/SESSION_END]] parsing in parser.ts
- Add closedBy field to StoredSession ('agent' | 'disconnect' | 'error')
- Update endSession() to accept closedBy option
- Add parseSessionEndAndClose() to tmux-wrapper
- Update daemon to pass closedBy on disconnect/error
- Include SESSION_END in startup instructions for agents
- Move StoredSession, SessionQuery, AgentSummary types to base adapter.ts
- Add optional session/summary methods to StorageAdapter interface
- This enables future MySQL/Postgres implementations
- Add 12 tests for session management (start, end, query, closedBy)
- Add 4 tests for agent summaries (save, get, getAll, update)
- Add 3 tests for getMessageById
- Add 11 tests for parseSummaryFromOutput and parseSessionEndFromOutput
- Coverage: sqlite-adapter 43%→86%, parser 90%→97%
- Add currentSessionId getter to RelayClient (sessionId was private)
- Update TmuxWrapper to use client.currentSessionId
- Remove unused ParsedSummary import
- Fix storage initialization race condition: add storageReady promise
  that methods await before using storage
- Add resetSessionState() method for wrapper reuse across sessions
- Don't set sessionEndProcessed flag if sessionId unavailable (allows retry)
- Add documentation for COALESCE pattern in endSession() explaining
  that null summary preserves existing value
- Clarify isActive field documentation: determined by endedAt only,
  independent of closedBy field
- Add closedBy field to SessionInfo interface and API response
Introduces the "bridge" command for cross-project agent coordination:
- Architect/Principal role as orchestrator connecting multiple projects
- Leads with spawn capability to dynamically create worker agents
- Standup protocol for daily work coordination
- Multi-project dashboard visibility
- bridge: just project paths as args
- lead: just your name
- System handles all complexity underneath
- Add bridge module with MultiProjectClient for multi-socket connections
- Add AgentSpawner for lead agents to spawn/release workers
- Add 'bridge' command: agent-relay bridge ~/project1 ~/project2
- Add 'lead' command: agent-relay lead Alice claude
- Support config file for project defaults (~/.agent-relay/bridge.json)
- Support --cli override for all projects
Add Multi-Project Orchestration section with:
- Bridge command usage
- Lead command usage
- Cross-project messaging syntax
- Spawn/release worker patterns
- Link to full design doc
- agent-relay-spawn-handler: Wire up spawn/release in lead mode
- agent-relay-cross-project-parser: Add project:agent syntax
- agent-relay-multi-project-dashboard: Bridge view for dashboard
- config.test.ts: Tests for path resolution, lead naming, project resolution
- utils.test.ts: Tests for target parsing, shell escaping

26 tests passing
Tests actual socket connections with real daemons for:
- Connection management across multiple projects
- Message routing to specific project agents
- Lead alias resolution
- Broadcast to all leads
claude and others added 12 commits December 23, 2025 08:29
- .env.example: Environment variables reference
- cli-usage.sh: CLI command examples
- programmatic-usage.ts: Library usage in TypeScript
- docker-compose.yml: Docker deployment example
- agent-relay.service: Systemd service file
- README.md: Examples documentation
…:khaliqgant/agent-relay into claude/review-pr-9-6HyEY
Add beads task for threaded conversations feature
- computeNeedsAttention: derive agents needing attention from message history
- findAgentConfig: auto-detect agent role from .claude/agents/ or .openagents/
- Includes full test coverage for both utilities
- Enables agent-relay-9w0 (auto-detect role) implementation
- Tests passing: 452/453 ✓
Major Changes:
- Cross-project message support (@project:agent syntax)
- Bridge interface for project-based messaging
- Dashboard display with project badges
- Agent auto-detection from .claude/agents config
- Needs-attention indicators for pending messages

Features:
- computeNeedsAttention: Heuristic for pending message detection
- Agent config detection from frontmatter
- Project namespace support in relay messages
- Enhanced bridge header and navigation

Tests:
- 452/453 tests passing ✓
- Full coverage for new utilities
- Integration tests complete

Issues Created:
- agent-relay-9uq: Project chat targeting
- agent-relay-1t7: Project name display
- agent-relay-vxc: Navigation consistency
- agent-relay-290: Interface parity

[bd-agent-relay] Dashboard + Bridge improvements complete
Bridge Features Completed:
- Project connection status (Online/Reconnecting/Offline with pulsing)
- Project chat targeting (message composer with project/agent dropdowns)
- Project name display in bridge header (with back link + highlighting)
- Navigation consistency (Dashboard ↔ Bridge seamless transitions)
- Interface parity audit (bridge vs dashboard features locked)
- Multi-project client reconnection (exponential backoff, configurable)

Dashboard Features:
- needsAttention indicators (pulsing badge, real-time updates)
- Project-based communication (selective targeting)
- Cross-project messaging (@project:agent syntax)
- Agent auto-detection from .claude/agents config

All tests passing (457+). Bridge UI production-ready.
Add -d/--detach flag to start agents in background, allowing SSH users
to disconnect without losing agent sessions. Includes attach/kill commands
for session management.
@khaliqgant khaliqgant changed the base branch from main to claude/analyze-mcp-agent-mail-IXbNF December 24, 2025 11:13
claude and others added 12 commits December 24, 2025 11:14
…ts test

The test was checking if dataDir exists, but listProjects() requires
the .project marker file to be present.
- POST /api/spawn - Create new agent with name, cli, task
- GET /api/workers - List active spawned workers
- DELETE /api/workers/:name - Release a worker

Enable with: agent-relay up --spawn
- Remove --spawn flag requirement, API always enabled
- Rename /api/workers to /api/spawned for consistency
- Update response field from 'workers' to 'agents'
…ets-RCkNs

Add Bridge & Staffing design for multi-project orchestration
…iqgant/agent-relay into claude/continue-pr-8-7tWzb
@khaliqgant khaliqgant merged commit bbcb4e9 into claude/analyze-mcp-agent-mail-IXbNF Dec 25, 2025
@khaliqgant khaliqgant deleted the claude/continue-pr-8-7tWzb branch December 25, 2025 13:53
khaliqgant added a commit that referenced this pull request Apr 1, 2026
template-resolver.ts: shell-escape interpolated variables (CRITICAL #1)
broker_tests.rs: uncomment and wire up 5 real tests (CRITICAL #2)
worker_tests.rs: uncomment and wire up 5 real tests (CRITICAL #3)
worker.rs: log bypass-flag injection, add .. path traversal rejection (CRITICAL #4, #7)
verification.ts: export stripInjectedTaskEcho, add path traversal guard (CRITICAL #5)
runner.ts: remove duplicate stripInjectedTaskEcho, add ENV_ALLOWLIST filtering (HIGH #17)
channel-messenger.ts: add secret scrubbing, hoist regex constants (MEDIUM #27, #28)
process-spawner.ts: add settled guard for race condition (MEDIUM #23)
step-executor.ts: add sideEffects to callback type, deprecate alias (HIGH #15, #16)
index.ts: export StepExecutor directly (MEDIUM #29)
workflows/refactor/*.ts: replace hardcoded paths, remove --no-verify (HIGH #8-11)
broker.rs: move is_pid_alive to canonical location (HIGH #14)
cost/tracker.ts: add restrictive file permissions (MEDIUM #30)
cost/pricing.ts: add last-verified date (MEDIUM #31)
verification.test.ts: 9 new tests for exported helpers (MEDIUM #32)

Co-Authored-By: My Senior Dev <dev@myseniordev.com>
khaliqgant added a commit that referenced this pull request Apr 6, 2026
…#675)

* refactor: TDD decomposition of runner.ts + main.rs with extracted modules

Extracted 5 modules from runner.ts (6,878 lines):
- verification.ts (143 lines)
- template-resolver.ts (87 lines)
- channel-messenger.ts (151 lines)
- step-executor.ts (571 lines)
- process-spawner.ts (96 lines)

Added characterization tests for all extracted modules.
Extracted broker.rs and worker.rs from main.rs.

Bug fixes:
- Restore stripInjectedTaskEcho in verification.ts
- Guard agent.release() against broker 400 race condition
- Fix run-summary-table test for new table format
- Export normalizeModel for correct pricing resolution
- Fix --wave argument parsing in run-refactor.ts
- ESM imports in all workflow files

* fix: address 10 review finding(s)

tracker.ts: resolveModel now uses normalizeModel for alias resolution (pre-existing fix verified)
run-refactor.ts: --wave parsing with proper validation (pre-existing fix verified)
step-executor.ts: signal-killed processes now correctly treated as failures
channel-messenger.ts: replaced ReDoS-vulnerable regex with iterative indexOf stripping
runner.ts: eliminated shell injection by using direct git spawn with argument arrays
process-spawner.ts: fixed SIGKILL fallback timer leak by storing and clearing reference

Co-Authored-By: My Senior Dev <dev@myseniordev.com>

* Revert "chore: gitignore .trajectories/ (automated run artifacts) (#676)" (#677)

This reverts commit 07a8dc0.

* refactor: TDD decomposition of runner.ts + main.rs with extracted modules

Extracted 5 modules from runner.ts (6,878 lines):
- verification.ts (143 lines)
- template-resolver.ts (87 lines)
- channel-messenger.ts (151 lines)
- step-executor.ts (571 lines)
- process-spawner.ts (96 lines)

Added characterization tests for all extracted modules.
Extracted broker.rs and worker.rs from main.rs.

Bug fixes:
- Restore stripInjectedTaskEcho in verification.ts
- Guard agent.release() against broker 400 race condition
- Fix run-summary-table test for new table format
- Export normalizeModel for correct pricing resolution
- Fix --wave argument parsing in run-refactor.ts
- ESM imports in all workflow files

* trajectories correction again

* pre commit is executable

* remove tracked workflows

* fix: address 36 review findings across Rust and TypeScript modules

template-resolver.ts: shell-escape interpolated variables (CRITICAL #1)
broker_tests.rs: uncomment and wire up 5 real tests (CRITICAL #2)
worker_tests.rs: uncomment and wire up 5 real tests (CRITICAL #3)
worker.rs: log bypass-flag injection, add .. path traversal rejection (CRITICAL #4, #7)
verification.ts: export stripInjectedTaskEcho, add path traversal guard (CRITICAL #5)
runner.ts: remove duplicate stripInjectedTaskEcho, add ENV_ALLOWLIST filtering (HIGH #17)
channel-messenger.ts: add secret scrubbing, hoist regex constants (MEDIUM #27, #28)
process-spawner.ts: add settled guard for race condition (MEDIUM #23)
step-executor.ts: add sideEffects to callback type, deprecate alias (HIGH #15, #16)
index.ts: export StepExecutor directly (MEDIUM #29)
workflows/refactor/*.ts: replace hardcoded paths, remove --no-verify (HIGH #8-11)
broker.rs: move is_pid_alive to canonical location (HIGH #14)
cost/tracker.ts: add restrictive file permissions (MEDIUM #30)
cost/pricing.ts: add last-verified date (MEDIUM #31)
verification.test.ts: 9 new tests for exported helpers (MEDIUM #32)

Co-Authored-By: My Senior Dev <dev@myseniordev.com>

* style: auto-format Rust code with cargo fmt

* minor clean

* fix: reinstate deleted workflow files into workflows/ci/

Moved fix-mcp-spawn.yaml, add-swift-sdk.ts, and cli-observability.ts
into workflows/ci/ to clearly distinguish them as CI test suite
workflows. Updated .gitignore to allow workflows/ci/ and workflows/refactor/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address remaining Devin review findings and fix failing test

- Fix tracker test: expect mode: 0o700 in mkdirSync assertion
- Use Object.hasOwn() instead of `in` operator to avoid prototype chain false positives
- Use Promise.allSettled to preserve partial output on process timeout
- Apply path containment check for absolute paths in checkFileExists

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address new Devin review findings — StepExecutor name collision and cwd trailing slash

- Rename StepExecutor interface in runner.ts to RunnerStepExecutor to avoid
  shadowing the StepExecutor class export in the barrel index
- Normalize cwd with path.resolve() in checkFileExists to handle trailing slashes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants