Files
claude-code/docs/plans/2024-12-29-pa-agent-mode-implementation.md
OpenCode Test 008ceaf3b4 Add PA Agent Mode implementation plan
9-task plan covering:
- Directory structure and JSON state files
- pa-mode launch script with tmux management
- pa-summarize hook script
- Hyprland keybind update
- PA agent memory loading instructions
- End-to-end testing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 02:04:47 -08:00

12 KiB

PA Agent Mode Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Create a persistent Claude Code environment with tmux, full autonomy, and long-term memory.

Architecture: Shell scripts manage tmux session lifecycle. Memory stored as JSON files. Hyprland keybind launches via existing omarchy-launch-tui pattern. PA agent instructions updated to load memory on startup.

Tech Stack: Bash, tmux, JSON, Hyprland config


Task 1: Create Directory Structure

Files:

  • Create: ~/.claude/state/personal-assistant/history/
  • Create: ~/.claude/state/personal-assistant/memory/

Step 1: Create directories

mkdir -p ~/.claude/state/personal-assistant/history
mkdir -p ~/.claude/state/personal-assistant/memory

Run: mkdir -p ~/.claude/state/personal-assistant/history ~/.claude/state/personal-assistant/memory

Step 2: Verify directories exist

Run: ls -la ~/.claude/state/personal-assistant/ Expected: history and memory directories listed

Step 3: Commit

# No git commit - these are runtime directories, not tracked

Task 2: Create History Index File

Files:

  • Create: ~/.claude/state/personal-assistant/history/index.json

Step 1: Create index.json with empty sessions array

{
  "version": "1.0",
  "sessions": []
}

Write to: ~/.claude/state/personal-assistant/history/index.json

Step 2: Verify file is valid JSON

Run: cat ~/.claude/state/personal-assistant/history/index.json | jq . Expected: Pretty-printed JSON with empty sessions array


Task 3: Create Memory Category Files

Files:

  • Create: ~/.claude/state/personal-assistant/memory/decisions.json
  • Create: ~/.claude/state/personal-assistant/memory/preferences.json
  • Create: ~/.claude/state/personal-assistant/memory/projects.json
  • Create: ~/.claude/state/personal-assistant/memory/facts.json
  • Create: ~/.claude/state/personal-assistant/memory/meta.json

Step 1: Create decisions.json

{
  "version": "1.0",
  "description": "Decisions made with rationale",
  "items": []
}

Step 2: Create preferences.json

{
  "version": "1.0",
  "description": "User preferences learned over time",
  "items": []
}

Step 3: Create projects.json

{
  "version": "1.0",
  "description": "Active and recent project context",
  "items": []
}

Step 4: Create facts.json

{
  "version": "1.0",
  "description": "Factual knowledge about the environment",
  "items": []
}

Step 5: Create meta.json

{
  "version": "1.0",
  "last_summarized": null,
  "total_sessions": 0,
  "total_items": {
    "decisions": 0,
    "preferences": 0,
    "projects": 0,
    "facts": 0
  }
}

Step 6: Verify all files are valid JSON

Run: for f in ~/.claude/state/personal-assistant/memory/*.json; do echo "=== $f ===" && jq . "$f"; done Expected: All 5 files display as valid JSON


Task 4: Create pa-mode Launch Script

Files:

  • Create: ~/.claude/automation/pa-mode

Step 1: Write the pa-mode script

#!/usr/bin/env bash
# PA Agent Mode - Launch/attach to persistent PA tmux session
set -euo pipefail

SESSION_NAME="pa"
HISTORY_DIR="$HOME/.claude/state/personal-assistant/history"
INDEX_FILE="$HISTORY_DIR/index.json"

usage() {
    echo "Usage: pa-mode [command]"
    echo ""
    echo "Commands:"
    echo "  (none)    Attach to existing session or create new one"
    echo "  new       Force new session (detaches existing if any)"
    echo "  kill      Terminate the PA session"
    echo "  status    Show session status"
    echo ""
}

get_session_id() {
    date +"%Y-%m-%d_%H-%M-%S"
}

create_session() {
    local session_id
    session_id=$(get_session_id)
    local history_file="$HISTORY_DIR/${session_id}.jsonl"

    # Record session start in index
    local tmp_file
    tmp_file=$(mktemp)
    jq --arg id "$session_id" --arg started "$(date -Iseconds)" \
        '.sessions += [{"id": $id, "started": $started, "ended": null, "summarized": false, "topics": []}]' \
        "$INDEX_FILE" > "$tmp_file" && mv "$tmp_file" "$INDEX_FILE"

    # Create tmux session with claude in PA mode
    # Using HISTFILE-like approach: set env var for history location
    tmux new-session -d -s "$SESSION_NAME" -c "$HOME" \
        "PA_SESSION_ID='$session_id' PA_HISTORY_FILE='$history_file' claude --dangerously-skip-permissions --agent personal-assistant"

    echo "Created new PA session: $session_id"
}

attach_session() {
    if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
        tmux attach-session -t "$SESSION_NAME"
    else
        create_session
        tmux attach-session -t "$SESSION_NAME"
    fi
}

case "${1:-}" in
    "")
        attach_session
        ;;
    new)
        if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
            echo "Killing existing session..."
            tmux kill-session -t "$SESSION_NAME"
        fi
        create_session
        tmux attach-session -t "$SESSION_NAME"
        ;;
    kill)
        if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
            tmux kill-session -t "$SESSION_NAME"
            echo "PA session terminated"
        else
            echo "No PA session running"
        fi
        ;;
    status)
        if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
            echo "PA session is running"
            tmux list-sessions -F "#{session_name}: #{session_created} (#{session_attached} attached)" | grep "^$SESSION_NAME:"
        else
            echo "PA session is not running"
        fi
        ;;
    -h|--help|help)
        usage
        ;;
    *)
        echo "Unknown command: $1"
        usage
        exit 1
        ;;
esac

Step 2: Make script executable

Run: chmod +x ~/.claude/automation/pa-mode

Step 3: Verify script syntax

Run: bash -n ~/.claude/automation/pa-mode && echo "Syntax OK" Expected: "Syntax OK"

Step 4: Test help output

Run: ~/.claude/automation/pa-mode --help Expected: Usage information displayed

Step 5: Commit

cd ~/.claude && git add automation/pa-mode && git commit -m "feat: add pa-mode launch script"

Task 5: Create pa-summarize Hook Script

Files:

  • Create: ~/.claude/automation/pa-summarize

Step 1: Write the pa-summarize script

#!/usr/bin/env bash
# PA Summarize - Extract session summary before shutdown
set -euo pipefail

MEMORY_DIR="$HOME/.claude/state/personal-assistant/memory"
INDEX_FILE="$HOME/.claude/state/personal-assistant/history/index.json"

# This script is called by tmux hook or manually
# It sends a summarization request to the running claude session

SESSION_NAME="pa"

if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
    echo "No PA session running"
    exit 1
fi

# Send summarization prompt to the tmux pane
# The PA agent will handle extracting and saving to memory files
tmux send-keys -t "$SESSION_NAME" \
    "Please summarize this session for long-term memory. Extract key decisions, preferences learned, project context, and facts into the appropriate memory files in ~/.claude/state/personal-assistant/memory/. Then mark this session as summarized in the history index." \
    Enter

echo "Summarization request sent to PA session"

Step 2: Make script executable

Run: chmod +x ~/.claude/automation/pa-summarize

Step 3: Verify script syntax

Run: bash -n ~/.claude/automation/pa-summarize && echo "Syntax OK" Expected: "Syntax OK"

Step 4: Commit

cd ~/.claude && git add automation/pa-summarize && git commit -m "feat: add pa-summarize hook script"

Task 6: Update Hyprland Keybind

Files:

  • Modify: ~/.config/hypr/bindings.conf

Step 1: Update the SUPER SHIFT C binding

Find line:

bindd = SUPER SHIFT, C, Claude Code, exec, omarchy-launch-tui tmux new-session -A -s claude-code claude

Replace with:

bindd = SUPER SHIFT, C, PA Agent Mode, exec, omarchy-launch-tui /home/will/.claude/automation/pa-mode

Step 2: Reload Hyprland config

Run: hyprctl reload Expected: No errors

Step 3: Verify binding registered

Run: hyprctl binds | grep -i "PA Agent" Expected: Shows the PA Agent Mode binding


Task 7: Update PA Agent Instructions

Files:

  • Modify: ~/.claude/agents/personal-assistant.md

Step 1: Add memory loading to initialization section

Find the initialization section after line 14 and add memory files to the list. Update the code block:

**Read these state files before executing tasks:**

~/.claude/state/system-instructions.json # Process definitions ~/.claude/state/future-considerations.json # Deferred features ~/.claude/state/model-policy.json # Model selection rules ~/.claude/state/autonomy-levels.json # Autonomy definitions ~/.claude/state/personal-assistant-preferences.json # PA persistent config ~/.claude/state/personal-assistant/session-context.json # Session context override ~/.claude/state/personal-assistant/general-instructions.json # User memory ~/.claude/state/personal-assistant/memory/decisions.json # Decisions with rationale ~/.claude/state/personal-assistant/memory/preferences.json # Learned preferences ~/.claude/state/personal-assistant/memory/projects.json # Project context ~/.claude/state/personal-assistant/memory/facts.json # Environment facts

Step 2: Add PA Agent Mode section before Notes

Insert before the "## Notes" section (around line 235):

## PA Agent Mode

When running in PA Agent Mode (tmux session "pa" with `--dangerously-skip-permissions`):

### Memory System

**On startup:**
1. Read all memory files from `~/.claude/state/personal-assistant/memory/`
2. Check `history/index.json` for unsummarized sessions
3. If unsummarized sessions exist, offer: "Last session wasn't summarized. Review it now?"

**During session:**
- Respond to `/pa --summarize` or "summarize this session" by extracting:
  - Decisions → `memory/decisions.json`
  - Preferences learned → `memory/preferences.json`
  - Project context → `memory/projects.json`
  - Facts → `memory/facts.json`
- Update `memory/meta.json` timestamps
- Mark session as summarized in `history/index.json`

**Memory item format:**
```json
{
  "id": "uuid",
  "date": "YYYY-MM-DD",
  "content": "description of item",
  "context": "optional additional context",
  "session": "session-id"
}

When asked about past conversations:

  1. Search history/index.json for relevant session IDs by topic
  2. Read the corresponding .jsonl files
  3. Provide relevant context from historical sessions

**Step 3: Commit**

```bash
cd ~/.claude && git add agents/personal-assistant.md && git commit -m "feat: add PA Agent Mode memory instructions"

Task 8: End-to-End Test

Step 1: Verify pa-mode creates session

Run: ~/.claude/automation/pa-mode status Expected: "PA session is not running"

Run: ~/.claude/automation/pa-mode new & then sleep 2 && tmux has-session -t pa && echo "Session created" Expected: "Session created"

Step 2: Verify index was updated

Run: cat ~/.claude/state/personal-assistant/history/index.json | jq '.sessions | length' Expected: 1

Step 3: Kill test session

Run: ~/.claude/automation/pa-mode kill Expected: "PA session terminated"

Step 4: Test keybind (manual)

Press Super+Shift+C Expected: Alacritty opens with PA session attached


Task 9: Final Commit

Step 1: Check git status

Run: cd ~/.claude && git status Expected: All changes committed, working tree clean

Step 2: Tag release

cd ~/.claude && git tag -a v1.0.0-pa-mode -m "PA Agent Mode implementation"

Summary

Task Description Files
1 Create directories history/, memory/
2 Create history index history/index.json
3 Create memory files memory/*.json (5 files)
4 Create pa-mode script automation/pa-mode
5 Create pa-summarize script automation/pa-summarize
6 Update Hyprland keybind ~/.config/hypr/bindings.conf
7 Update PA agent instructions agents/personal-assistant.md
8 End-to-end test (verification)
9 Final commit + tag (git)