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

471 lines
12 KiB
Markdown

# 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**
```bash
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**
```bash
# 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**
```json
{
"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**
```json
{
"version": "1.0",
"description": "Decisions made with rationale",
"items": []
}
```
**Step 2: Create preferences.json**
```json
{
"version": "1.0",
"description": "User preferences learned over time",
"items": []
}
```
**Step 3: Create projects.json**
```json
{
"version": "1.0",
"description": "Active and recent project context",
"items": []
}
```
**Step 4: Create facts.json**
```json
{
"version": "1.0",
"description": "Factual knowledge about the environment",
"items": []
}
```
**Step 5: Create meta.json**
```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**
```bash
#!/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**
```bash
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**
```bash
#!/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**
```bash
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:
```conf
bindd = SUPER SHIFT, C, Claude Code, exec, omarchy-launch-tui tmux new-session -A -s claude-code claude
```
Replace with:
```conf
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:
```markdown
**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):
```markdown
## 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"
}
```
### History Search
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**
```bash
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) |