docs: document session input methods and CLI commands

- Add detailed documentation for session.write() vs session.writeViaScreen()
- Explain how writeViaScreen auto-splits text and Enter for Ink compatibility
- Add API usage examples showing text and Enter sent separately
- Add CLI commands quick reference section
- Clarify vitest globals: true config and PTY mocking in tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-20 08:40:14 +01:00
co-authored by Claude Opus 4.5
parent b230785909
commit be414f2126
+50 -12
View File
@@ -24,7 +24,7 @@ npx tsx src/index.ts web -p 8080 # Dev mode with custom port
node dist/index.js web # After npm run build
claudeman web # After npm link
# Testing (vitest - tests run against WebServer, no real Claude CLI spawned)
# Testing (vitest with globals: true - no imports needed for describe/it/expect)
npm run test # Run all tests once
npm run test:watch # Watch mode
npm run test:coverage # With coverage report
@@ -32,6 +32,7 @@ npx vitest run test/session.test.ts # Single file
npx vitest run -t "should create session" # By pattern
# Tests use ports 3099-3121 to avoid conflicts with dev server (3000)
# Test timeout: 30s (configured in vitest.config.ts for integration tests)
# Tests mock PTY - no real Claude CLI spawned
# TypeScript checking (no linter configured)
npx tsc --noEmit # Type check without building
@@ -158,21 +159,47 @@ pty.spawn('claude', ['--dangerously-skip-permissions'], { ... })
pty.spawn('bash', [], { ... })
```
### Screen Input for Ink/Claude CLI
### Sending Input to Sessions
Claude CLI uses Ink (React for terminals) which has specific input handling. When sending programmatic input via `screen -X stuff`:
There are two methods for sending input to Claude sessions:
**IMPORTANT**: Text and Enter key MUST be sent as separate commands:
```bash
# Correct - two separate commands
screen -S claudeman-xxx -p 0 -X stuff "hello world"
screen -S claudeman-xxx -p 0 -X stuff "$(printf '\015')"
# Wrong - doesn't work with Ink
screen -S claudeman-xxx -p 0 -X stuff "$(printf 'hello world\015')"
#### 1. `session.write(data)` - Direct PTY write
Used by the `/api/sessions/:id/input` API endpoint. Writes directly to PTY.
```typescript
session.write('hello world'); // Text only, no Enter
session.write('\r'); // Enter key separately
```
The `\015` (octal) is carriage return (ASCII 13), which Ink interprets as `key.return` for submission. Use `writeViaScreen()` method for programmatic input that needs Enter key.
#### 2. `session.writeViaScreen(data)` - Via GNU screen (RECOMMENDED for programmatic input)
Used by RespawnController, auto-compact, auto-clear. More reliable for Ink/Claude CLI.
```typescript
// Append \r to include Enter - the method handles splitting automatically
session.writeViaScreen('your command here\r');
session.writeViaScreen('/clear\r');
session.writeViaScreen('/init\r');
```
**How `writeViaScreen` works internally** (in `screen-manager.ts:sendInput`):
1. Splits input into text and `\r` (carriage return)
2. Sends text first: `screen -S name -p 0 -X stuff "text"`
3. Sends Enter separately: `screen -S name -p 0 -X stuff "$(printf '\015')"`
**Why separate commands?** Claude CLI uses Ink (React for terminals) which requires text and Enter as separate `screen -X stuff` commands. Combining them doesn't work.
#### API Usage
```bash
# Send text (won't submit until Enter is sent)
curl -X POST localhost:3000/api/sessions/:id/input \
-H "Content-Type: application/json" \
-d '{"input": "your prompt here"}'
# Send Enter separately to submit
curl -X POST localhost:3000/api/sessions/:id/input \
-H "Content-Type: application/json" \
-d '{"input": "\r"}'
```
**Note**: The API uses `session.write()` which goes to PTY directly. For reliability with Ink, consider using the respawn controller pattern or adding an API endpoint that uses `writeViaScreen()`.
### Idle Detection
@@ -290,6 +317,17 @@ npx agent-browser open http://localhost:3000 && npx agent-browser snapshot
| POST | `/api/cases` | Create new case |
| GET | `/api/screens` | List screen sessions with stats |
## CLI Commands (when using `claudeman` globally)
```bash
claudeman web [-p PORT] # Start web interface
claudeman start [--dir PATH] # Start Claude session
claudeman list # List sessions
claudeman task add "PROMPT" # Add task to queue
claudeman ralph start [--min-hours N] # Start autonomous loop
claudeman status # Overall status
```
## Notes
- State persists to `~/.claudeman/state.json`, `~/.claudeman/state-inner.json`, and `~/.claudeman/screens.json`