fix(llm): strip CLAUDECODE env var before spawning claude subprocess The claude CLI refuses to run when CLAUDECODE is set in the environment, as it detects a nested Claude Code session. When llm9p is launched from within Claude Code, all subprocesses inherit this variable and every LLM call fails with "Cannot be launched inside another Claude Code session". Added claudeEnv() helper that filters CLAUDECODE from os.Environ() before passing the environment to cmd. Replaced all five cmd.Environ() call sites in cli_client.go (Ask, Compact, StartStream, AskWithHistory, AskWithRequest). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(llm9p): per-session compact and usage files for context window management Add automatic context window compaction support to the per-session 9P API: - session.go: Add Session.EstimatedContextTokens() (4 chars/token heuristic over current messages — more accurate than cumulative totalTokens for threshold decisions). Add SessionManager.Compact(ctx, id) which summarises the conversation via AskWithRequest then replaces session.messages with a compact 2-message exchange. Add SessionManager.EstimatedContextTokens(id) and SessionManager.ContextLimit() (200K for all Claude models). - session_compact.go: New /n/llm/N/compact file. Write any content to trigger Compact() for that session. Follows the SessionModelFile pattern. - session_usage.go: New /n/llm/N/usage file. Read returns "estimated_tokens/200000\n". Follows the SessionModelFile pattern. - session_dir.go: Wire compact and usage into Children() and Lookup(). Also land two pre-existing uncommitted fixes: - cli_client.go: Accept result messages with empty Result field - protocol.go: Increase MaxMessageSize 8192→65536 for large system prompts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(llm9p): Implement clone-based session architecture Replace per-fid session model with Plan 9 clone pattern: - Reading /n/llm/new creates a session and returns its ID - Each session gets its own directory: /n/llm/<id>/ - Per-session files: ask, ctl, model, system, thinking, context, metrics - AskWithRequest method for stateless CSP-style LLM calls - Session settings (model, temperature, thinking) are per-session - Remove old ask.go, context.go in favor of session-scoped files Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
feat(llm9p): Add per-fid session isolation and prefill support - Add SessionManager for per-fid conversation isolation - Each 9P fid now gets its own conversation history - Add FidAwareFile interface for files needing fid context - Add /n/llm/prefill file for assistant response prefill - Prefill helps keep model in character (e.g., "[Veltro]") - Update ask, new, context files to use session manager - Fix context contamination between parent and subagent Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat(llm): Add extended thinking support and usage tracking - Add thinking token control via /n/llm/thinking file (max/off/number) - CLI backend sets MAX_THINKING_TOKENS env var for Claude CLI - Default to max thinking (31999 tokens) for CLI backend - Add /n/llm/usage file for token usage monitoring - Add /n/llm/compact file for conversation summarization - Extend Backend interface with ThinkingTokens, TotalTokens, ContextLimit, Compact - Add true streaming support for CLI backend with line-by-line output - Update example file with thinking documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat: Add system prompt file for persistent persona configuration - Add system file (read/write) to set system prompt - System prompt persists across conversation resets - Add SystemPrompt() and SetSystemPrompt() to Backend interface - Update both API and CLI clients to support dedicated system prompt - Update documentation and examples Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
refactor: Remove unnecessary --dangerously-skip-permissions flag Testing confirmed that --dangerously-skip-permissions is NOT needed when: 1. --print mode is used (non-interactive) 2. Tools are disabled with --allowedTools "" The CLI only prompts for permission when tools might take actions. With tools disabled, it's purely text-in/text-out and no prompts occur. Added explanatory comments documenting each CLI flag's purpose. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat: Add CLI backend for Claude Max subscription Add support for using Claude Code CLI as an alternative backend, allowing users with Claude Max subscriptions to use llm9p without API tokens. New files: - internal/llm/backend.go: Backend interface for swappable LLM providers - internal/llm/cli_client.go: CLI-based client using `claude` command Changes: - Add -backend flag: 'api' (default) or 'cli' - Refactor llmfs to use Backend interface instead of concrete Client - Model names normalized for CLI (opus, sonnet, haiku) Usage: ./llm9p -backend cli # Uses Claude Max subscription ./llm9p -backend api # Uses Anthropic API (default) Limitations of CLI backend: - Token counting not available (always 0) - Streaming is simulated (full response as single chunk) - Uses short model names (opus, sonnet, haiku) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>