This repository has been archived on 2026-08-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
kb-skills/gsd-openclaw/.planning/research/ARCHITECTURE.md
T
starmen1265 96f06f3751
PR Test / lint (pull_request) Successful in 2s
feat: 添加 gsd-openclaw 技能
2026-03-11 10:41:01 +08:00

377 lines
21 KiB
Markdown

# Architecture Patterns
**Domain:** tmux-Claude CLI integration + OpenClaw skill bridge
**Researched:** 2026-03-10
## Recommended Architecture
The gsd-openclaw skill acts as a bridge between OpenClaw's multi-channel messaging system and GSD's Claude CLI-based project management. The architecture follows a **session-orchestrator-bridge** pattern.
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ USER INTERFACES │
│ WhatsApp / Telegram / Slack / Discord / Feishu / WeChat / WebChat │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ OpenClaw Gateway │
│ (WebSocket Control Plane) │
│ ws://127.0.0.1:18789 │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Channel │ │ Session │ │ Skill │ │
│ │ Handlers │ │ Manager │ │ Registry │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
│ Skill Invocation (SKILL.md trigger)
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ gsd-openclaw Skill Layer │
│ ~/.openclaw/workspace/skills/gsd-openclaw/ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ SKILL.md │ │
│ │ - Trigger patterns: "/gsd:*", "gsd*", project management keywords │ │
│ │ - Routes to orchestrator.py with parsed intent │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ orchestrator.py │ │
│ │ - Command routing and validation │ │
│ │ - User/project authentication │ │
│ │ - State coordination │ │
│ │ - Response formatting for messaging channels │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ tmux_session_manager.py │ │
│ │ - Create/destroy tmux sessions per user-project │ │
│ │ - Send commands to Claude CLI │ │
│ │ - Capture output (sync/async) │ │
│ │ - Session health monitoring │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ state_manager.py │ │
│ │ - Persistent state storage (JSON) │ │
│ │ - Project workspace tracking │ │
│ │ - User session mapping │ │
│ │ - Conversation history (for context recovery) │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
│ libtmux / tmux commands
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ tmux Session Layer │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ ┌────────────────────┐ │
│ │ tmux:gsd-user1-projA│ │ tmux:gsd-user1-projB│ │ tmux:gsd-user2-projC│ │
│ │ (Claude CLI) │ │ (Claude CLI) │ │ (Claude CLI) │ │
│ │ workspace: ~/projA │ │ workspace: ~/projB │ │ workspace: ~/projC│ │
│ └─────────────────────┘ └─────────────────────┘ └────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
│ Slash commands (/gsd:*)
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ GSD System │
│ ~/.claude/get-shit-done/ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ /gsd:new- │ │ /gsd:plan │ │ /gsd:ship │ │ /gsd:status │ │
│ │ project │ │ │ │ │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ GSD Core │ │
│ │ - Project scaffolding (.planning/ structure) │ │
│ │ - Roadmap generation │ │
│ │ - Task management │ │
│ │ - Git integration │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
### Component Boundaries
| Component | Responsibility | Communicates With |
|-----------|---------------|-------------------|
| **SKILL.md** | Trigger pattern matching, skill description | OpenClaw Gateway |
| **orchestrator.py** | Command routing, user auth, response formatting | state_manager, tmux_session_manager |
| **tmux_session_manager.py** | tmux session lifecycle, I/O with Claude CLI | tmux (via libtmux/subprocess), orchestrator |
| **state_manager.py** | Persistent state, workspace tracking, user mapping | orchestrator (reads/writes JSON) |
| **prompts/** | LLM prompt templates for different scenarios | orchestrator (loads as needed) |
### Data Flow
```
1. User sends message: "Create a new project for user authentication"
│
▼
2. OpenClaw Gateway receives via channel (WhatsApp/Telegram/etc.)
│
▼
3. Gateway matches trigger pattern → invokes gsd-openclaw skill
│
▼
4. orchestrator.py:
a. Extracts intent: "new-project" command
b. Validates user authentication
c. Checks state_manager for existing sessions
│
▼
5. tmux_session_manager.py:
a. Gets or creates tmux session for user+project
b. Sends "/gsd:new-project user authentication" to Claude CLI
│
▼
6. Claude CLI processes in tmux (persistent context):
a. GSD system scaffolds project
b. Generates initial planning files
c. Outputs progress/response
│
▼
7. tmux_session_manager captures output (async polling)
│
▼
8. orchestrator formats response for channel:
- Compact for mobile (WhatsApp/Telegram)
- Rich for Slack/Discord
│
▼
9. Response sent back through OpenClaw Gateway to user
│
▼
10. state_manager updates:
- Session last activity
- Project state changes
- Conversation checkpoint
```
## Patterns to Follow
### Pattern 1: Session-per-Project Isolation
**What:** Each user-project combination gets its own tmux session with isolated Claude context.
**When:** Always, for any project-specific work.
**Why:** Prevents context pollution between projects, enables parallel work.
```python
# tmux_session_manager.py
class TmuxSessionManager:
def get_or_create_session(self, user_id: str, project_id: str) -> TmuxSession:
session_name = f"gsd-{user_id}-{project_id}"
# Check if session exists
session = self.find_session(session_name)
if session:
return session
# Create new session with project workspace
workspace = self.state_manager.get_project_workspace(user_id, project_id)
return self.create_session(
name=session_name,
working_dir=workspace,
command="claude" # Start Claude CLI
)
```
### Pattern 2: Async Response Handling
**What:** Non-blocking output capture with callback-based response delivery.
**When:** Any command that may take time (GSD operations can be slow).
**Why:** Messaging channels expect timely responses; Claude operations may take minutes.
```python
# orchestrator.py
async def handle_command(self, user_id: str, command: str, context: dict):
session = self.tmux_manager.get_or_create_session(
user_id,
context.get("project_id")
)
# Send command
session.send_keys(command)
# Start async output capture
output_future = self.tmux_manager.capture_output_async(
session,
timeout=300, # 5 min max
idle_timeout=30 # 30s of no output = done
)
# Return immediately with "processing" status
# Callback will send response when complete
return Response(status="processing", estimated_time="1-2 minutes")
```
### Pattern 3: State Checkpointing
**What:** Periodic state snapshots to enable recovery from interruption.
**When:** After each significant GSD operation, every N minutes during long operations.
**Why:** Network interruptions, server restarts, user timeouts should not lose work.
```python
# state_manager.py
def checkpoint_session(self, session_id: str, claude_output: str):
state = self.load_state()
state["sessions"][session_id]["last_checkpoint"] = {
"timestamp": datetime.now().isoformat(),
"claude_context_summary": self._extract_context_summary(claude_output),
"project_phase": self._detect_current_phase(claude_output),
"pending_actions": self._extract_pending_actions(claude_output)
}
self.save_state(state)
```
### Pattern 4: Channel-Adaptive Formatting
**What:** Same content rendered differently based on target channel.
**When:** Every response going back to user.
**Why:** WhatsApp has 4096 char limit, Discord supports markdown, mobile needs compactness.
```python
# response_formatter.py
def format_response(self, content: dict, channel: str) -> str:
formatters = {
"whatsapp": self._format_compact,
"telegram": self._format_markdown_lite,
"slack": self._format_rich_slack,
"discord": self._format_rich_discord,
"feishu": self._format_feishu_card
}
formatter = formatters.get(channel, self._format_generic)
return formatter(content)
```
## Anti-Patterns to Avoid
### Anti-Pattern 1: Shared Global tmux Session
**What:** One tmux session for all users/projects.
**Why bad:** Context mixing, race conditions, security issues (users see each other's data).
**Instead:** Session-per-project isolation (Pattern 1).
### Anti-Pattern 2: Synchronous Blocking on Claude Output
**What:** Wait for Claude to complete before returning any response.
**Why bad:** Timeouts on messaging channels (often 30-60s), poor UX, gateway hangs.
**Instead:** Async with status updates (Pattern 2).
### Anti-Pattern 3: State in Memory Only
**What:** Keep all state in Python process memory.
**Why bad:** Lost on restart, cannot scale horizontally, no recovery from crash.
**Instead:** Persistent JSON state with checkpointing (Pattern 3).
### Anti-Pattern 4: Direct GSD Code Modification
**What:** Modify GSD source to add OpenClaw-specific features.
**Why bad:** Breaks GSD updates, creates maintenance burden, diverges from upstream.
**Instead:** Pure bridge pattern - send slash commands, capture output, no GSD modifications.
### Anti-Pattern 5: Claude CLI in Non-Interactive Mode
**What:** Use Claude CLI with `--no-interactive` or pipe-only input.
**Why bad:** Loses conversational context, breaks GSD's interactive prompts, no approval flows.
**Instead:** Full tmux session with pseudo-terminal.
## Scalability Considerations
| Concern | At 1 user | At 10 users | At 100 users |
|---------|-----------|-------------|--------------|
| **tmux sessions** | 1-5 per user | 10-50 total | 100-500 total (consider session pooling/LRU eviction) |
| **Memory** | ~100MB (Claude) | ~1GB (10x Claude) | ~10GB (need session limits, swap to disk) |
| **State storage** | ~1MB JSON | ~10MB | ~100MB (consider SQLite migration) |
| **Response latency** | Immediate | Slight queue | Need job queue, async workers |
| **Channel limits** | N/A | Monitor rate limits | Implement rate limiting, batching |
## Directory Structure
```
~/.openclaw/workspace/skills/gsd-openclaw/
├── SKILL.md # Skill definition and triggers
├── orchestrator.py # Main orchestration logic
├── tmux_session_manager.py # tmux session lifecycle
├── state_manager.py # Persistent state management
├── response_formatter.py # Channel-adaptive formatting
├── prompts/
│ ├── context_recovery.md # Prompt for recovering session context
│ ├── command_mapping.md # Natural language to GSD commands
│ └── error_recovery.md # Prompt for handling errors
└── state/
├── sessions.json # Active sessions mapping
├── users.json # User project mappings
└── projects/ # Per-project state snapshots
├── user1-projA.json
└── user1-projB.json
```
## Build Order Implications
Based on component dependencies, recommended build order:
1. **Phase 1: Core Infrastructure**
- `state_manager.py` (no dependencies, needed by all)
- `tmux_session_manager.py` (depends on state_manager for workspace paths)
2. **Phase 2: Integration Layer**
- `response_formatter.py` (standalone, needed by orchestrator)
- `prompts/` (static files, needed by orchestrator)
3. **Phase 3: Orchestration**
- `orchestrator.py` (depends on all above)
- `SKILL.md` (defines triggers, depends on orchestrator interface)
4. **Phase 4: Testing & Polish**
- Integration tests
- Channel-specific formatting refinement
- Error handling edge cases
## Key Integration Points
### OpenClaw Gateway Integration
- Skill is auto-loaded from `~/.openclaw/workspace/skills/gsd-openclaw/`
- SKILL.md frontmatter defines trigger patterns
- Gateway calls orchestrator with: user_id, message, channel, context
### GSD Integration
- **No code changes to GSD** - pure bridge pattern
- All interaction via tmux + slash commands
- Workspace paths from GSD conventions (`~/projects/{name}`)
### tmux Integration Options
1. **libtmux (Python)** - Recommended, cleaner API
2. **subprocess + tmux commands** - Fallback, more control
```python
# Option 1: libtmux
import libtmux
server = libtmux.Server()
session = server.new_session("gsd-user1-projA", attach=False)
pane = session.attached_window.attached_pane
pane.send_keys("/gsd:status")
# Option 2: subprocess
import subprocess
subprocess.run(["tmux", "new-session", "-d", "-s", "gsd-user1-projA"])
subprocess.run(["tmux", "send-keys", "-t", "gsd-user1-projA", "/gsd:status", "Enter"])
```
## Sources
- OpenClaw GitHub Repository: https://github.com/openclaw/openclaw (HIGH confidence - official source)
- OpenClaw Website: https://openclaw.ai/ (HIGH confidence - official documentation)
- dev-workflow skill reference implementation (HIGH confidence - existing pattern in same ecosystem)
- GSD project context from PROJECT.md (HIGH confidence - project requirements)
## Confidence Assessment
| Area | Confidence | Reason |
|------|------------|--------|
| OpenClaw skill structure | HIGH | Direct reference from dev-workflow, official docs |
| tmux integration patterns | MEDIUM | Standard Python/tmux patterns, needs validation with Claude CLI specifics |
| Async response handling | HIGH | Standard pattern for messaging bots, well-established |
| GSD bridge approach | HIGH | Project requirement explicitly states "bridge not modify" |
| Scalability estimates | LOW | Theoretical, needs real-world testing |