anthropics / anthropics/claude-agent-sdk-typescript

listSessions() spawns full CLI process — 900MB+ memory for metadata query

Aperta
#268 1 commento 0 reazioni 0 assegnatari Vedi su GitHub
bug enhancement
Lingua principale
Shell
Stelle
1.8k
Fork
226
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

## Summary

`listSessions()` from `@anthropic-ai/claude-agent-sdk` consumes ~900MB of memory per call because it spawns a full Claude Code CLI child process via stdio pipes to enumerate session files. This makes it unsuitable for periodic polling (e.g., a sidecar health check every 30 seconds).

## Environment

- `@anthropic-ai/claude-agent-sdk`: latest (installed via npm)
- Node.js: v24.13.1
- macOS (Apple Silicon)
- ~50+ session JSONL files in `~/.claude/projects/`

## Reproduction

Minimal sidecar server that calls `listSessions()` on an HTTP endpoint:

```typescript
import { listSessions } from '@anthropic-ai/claude-agent-sdk'

// On startup: RSS = 77 MB
// After 2 calls to listSessions(): RSS = 950 MB
const sessions = await listSessions()
```

### Experiment: memory timeline

| Time | Event | RSS |
|------|-------|-----|
| 0s | Sidecar starts (Hono HTTP server, no SDK calls) | **77 MB** |
| 3s | First `GET /sessions` → calls `listSessions()` | growing... |
| 8s | Second `GET /sessions` → calls `listSessions()` | **950 MB** |
| 5min | Idle, no further calls, 0 active sessions | **1,340 MB** |

### Memory breakdown (via Node.js inspector protocol)

```
RSS: 1,340 MB
├─ V8 Heap: 522 MB
├─ External: 341 MB
│ └─ ArrayBuffers: 337 MB ← stdio pipe buffers
└─ Node overhead: ~77 MB
```

The 337 MB of ArrayBuffers strongly suggests stdio pipe buffering from the spawned CLI process. V8 does not return these pages to the OS after GC, so RSS ratchets up permanently with each call.

### Control experiment

With `listSessions()` removed (only `registry.list()` for in-memory active sessions), the sidecar stays at **77 MB** indefinitely.

## Expected behavior

`listSessions()` should be a lightweight metadata query — reading file stats and first/last lines of JSONL files. It should not need to spawn a full Claude Code CLI process with its entire runtime just to enumerate sessions.

Ideally:
- **< 10 MB** memory overhead per call
- **No child process spawn** — direct filesystem scan
- Safe for polling every 10-30 seconds

## Impact

Any application that periodically calls `listSessions()` (e.g., a session picker, dashboard, health monitor) will see memory grow to 1+ GB within seconds, even with zero active SDK sessions. The memory is never returned to the OS.

## Workaround

We're replacing `listSessions()` with a direct filesystem scan of `~/.claude/projects/` to read session metadata, avoiding the SDK call entirely.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.