Skip to content

Session Management Restructure: Multi-session .agents/ with deterministic cleanup #6

@hev

Description

@hev

Goal

Replace the single .agent/ folder with a multi-session .agents/<session>/ structure to support deterministic cleanup, multiple local deployments via worktrees, and avoid port conflicts between concurrent sessions.

Motivation

  • Enable testing multiple things across multiple local deployments using worktrees
  • Make cleanup deterministic and command-driven (not part of the scratchpad prompt)
  • Avoid port conflicts when running multiple sessions concurrently

Key Design Decisions

Decision Choice
Session location .agents/ in project root
Session identity Tied to prompt.md file (hash of absolute path)
Port allocation Dynamic - scan existing sessions, find next available offset
Cleanup criteria Manual only via new CLI commands

Session Naming

.agents/<sanitized-prompt-basename>-<8-char-hash>/

Example: prompt.md at /Users/hev/workspace/ralph/prompt.md becomes .agents/prompt-a1b2c3d4/

Session Folder Structure

.agents/
  <session-name>/
    session.json          # Metadata (creation time, prompt path, session number, ports)
    TODO.md               # Task tracking
    docker-compose.yml    # Generated with offset ports
    worktree/             # Git worktree (if enabled)
    items/                # Per-todo-item artifacts

Port Allocation (Dynamic)

When creating a new session:

  1. Scan all existing sessions in .agents/*/docker-compose.yml
  2. Parse port mappings to find used offsets
  3. Find the next available offset (gap-filling: if 1, 3 exist, use 2)
  4. Apply offset to base ports:
    • Grafana: 3000 + N
    • OTEL gRPC: 4317 + N
    • OTEL HTTP: 4318 + N
    • Prometheus: 9090 + N

New CLI Commands

  • ralph sessions - List all sessions in current project (table with name, status, ports, age, prompt)
  • ralph clean <session-name> - Delete a specific session folder
  • ralph clean --all - Delete all session folders
  • ralph cd <session-name> - Print worktree path (for use with cd $(ralph cd name))

Implementation Steps

Step 1: Create session package

Create internal/session/ with:

  • metadata.go - Session JSON structure and load/save
  • session.go - Manager with Create(), List(), Get(), Clean(), CleanAll()
  • docker.go - Docker-compose generation with dynamic port detection:
    • ScanUsedOffsets(agentsDir) - Parse existing docker-compose files for port usage
    • NextAvailableOffset(usedOffsets) - Find lowest unused offset (gap-filling)
    • GenerateDockerCompose(sessionDir, offset) - Template with calculated ports
  • Tests for each file

Step 2: Add CLI commands

Create new command files in cmd/ralph/:

  • sessions.go - ralph sessions command
  • clean.go - ralph clean <name> and ralph clean --all
  • cd.go - ralph cd <name>

Register commands in main.go init().

Step 3: Integrate with runner

Modify internal/runner/runner.go lines 105-115:

  • Replace direct os.MkdirAll(cfg.AgentDir) with session manager
  • Create/get session based on prompt file path
  • Update cfg.AgentDir to point to session directory

Step 4: Update worktree handling

Modify internal/worktree/worktree.go:

  • Add CreateAt(branch, path) method for session-local worktrees
  • Update runner to use session's worktree path instead of /tmp/ralph-worktrees

Step 5: Update scratchpad prompt

Modify internal/config/config.go lines 277-283:

  • Remove "Artifact Management" section (cleanup instructions)
  • Remove "When done cleaning up after a todo item, commit your changes"
  • Keep artifact creation but remove cleanup responsibility

Files to Create

File Purpose
internal/session/metadata.go Session JSON struct and persistence
internal/session/session.go Manager: create, list, get, clean
internal/session/docker.go Docker-compose template generation
internal/session/session_test.go Tests
cmd/ralph/sessions.go ralph sessions command
cmd/ralph/clean.go ralph clean command
cmd/ralph/cd.go ralph cd command

Files to Modify

File Changes
cmd/ralph/main.go Register new subcommands
internal/config/config.go:277-283 Remove cleanup from scratchpad prompt
internal/runner/runner.go:105-115 Use session manager
internal/worktree/worktree.go Add CreateAt() for session-local worktrees

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions