- Split multi-line user input and system messages on newlines so each
visual line gets its own ConversationLine (same pattern push_output
already used). This fixes text misalignment when Enter is pressed.
- Don't enable Wrap on the conversation Paragraph — the FIFO viewport
counts Line items to fill the pane, so soft-wrapping would throw off
the row count and misalign content.
- Restore non-TUI files from upstream/main to clear conflict artifacts.
- Fix clippy warnings in lsp_client, lsp_process/parse, and trident.
- Add HandlerSwap and TeamToggle match arms in main.rs ReadOutcome.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Agents post completion/failure to team inbox on termination
(.clawd-agents/mailbox/team/{team_id}/{agent_id}-{ts}.json)
- Team watcher reads from inbox instead of polling .json files
- New TeamStatus action=inbox reads team messages from the inbox
- AgentOutput carries team_id, persisted in manifest
- AgentInput accepts team_id from TeamCreate
- TeamCreate passes team_id to each spawned agent
- Inbox cleaned up when all agents finish
Co-authored-by: GLM 5.1 FP8 via Crush <crush@charm.land>
- TeamStatus tool with 3 actions:
- status: live snapshot (running/completed/failed counts, agent details)
- summary: final results when agents finish (includes result content)
- events: timeline from append-only event log
- Background team watcher thread spawned by TeamCreate:
- Polls agent .json files every 2s
- Prints [team] progress to stderr on agent completion/failure
- Updates team manifest status when all agents finish
- Writes events to .clawd-agents/teams/{team_id}-events.jsonl
- TeamStatus added to PARALLEL_SAFE_TOOLS and all agent allowed_tools
Co-authored-by: GLM 5.1 FP8 via Crush <crush@charm.land>
Instead of erroring when neither mode nor tasks are specified,
default to "2x" (2 Explore + 2 Plan + 2 Verification = 6 agents).
Co-authored-by: GLM 5.1 FP8 via Crush <crush@charm.land>
Add 'mode' field to TeamCreate that auto-generates agent teams:
- "2x" = 2 Explore + 2 Plan + 2 Verification = 6 agents
- "4x" = 4 Explore + 4 Plan + 4 Verification = 12 agents
- "6x" = 6 Explore + 6 Plan + 6 Verification = 18 agents
When mode is set, 'prompt' provides the shared task description and
'tasks' is ignored. Also add 'subagent_type' and 'model' fields to
manual task items for per-task role and model control.
Co-authored-by: GLM 5.1 FP8 via Crush <crush@charm.land>
- Add missing AgentMessage dispatch entry in execute_tool_with_enforcer
(tool spec existed but couldn't actually be called)
- Add AgentMessage to Explore/Plan/Verification/general-purpose
allowed_tools lists so sub-agents can communicate
- Add debug logging to resolve_agent_model and load_subagent_model_from_config
to diagnose subagentModel config chain
Co-authored-by: GLM 5.1 FP8 via Crush <crush@charm.land>
- Agent tool is now parallel-safe: multiple Agent calls execute concurrently
- AgentMessage tool: send/read/broadcast between agents via shared mailbox
- TeamCreate rewired to spawn real Agent threads instead of TaskRegistry
- Agents set CLAWD_AGENT_ID env var so they can identify themselves for messaging
- AgentMessage added to Explore/Plan/Verification sub-agent tool lists
- Team manifest persisted to .clawd-agents/teams/{team_id}.json
Match Claude Code's architecture: a single Agent tool with subagent_type
(Explore/Plan/Verification) that uses the subagentModel setting when
no explicit model override is provided. The separate SubAgent tool is
removed since it duplicated existing functionality.
Add a SubAgent tool that lets the main model delegate multi-step read
and search tasks to a fast, inexpensive sub-agent. The sub-agent runs
autonomously with its own ConversationRuntime, making multiple tool
calls without round-tripping through the main model.
- SubAgent tool with prompt, task_type (Explore/Plan/Verify), and
optional model override
- Explore: read_file, glob_search, grep_search, WebFetch, WebSearch
- Plan: Explore + TodoWrite
- Verify: Plan + bash
- subagentModel config field in settings.json (falls back to main model)
- Uses ProviderRuntimeClient + SubagentToolExecutor (same as Agent tool)
This dramatically reduces token usage for information-gathering tasks.
Example: "find all Rust files that import X and summarize their usage"
→ one SubAgent call instead of 10 sequential main-model round trips.
- Add distro-aware install prompt system: detects Ubuntu/Debian/Fedora/
Arch/openSUSE/Alpine/Void/NixOS/macOS and suggests the right install
command for each missing LSP server at startup
- Add 6 new language servers: HTML, CSS, JSON, Bash, YAML, GDScript
- Add didClose notifications for proper file lifecycle
- Add code_action support (quick fixes, refactors)
- Add rename support (workspace-wide symbol renaming)
- Add signature_help (function signatures + parameter hints)
- Add code_lens (inline actionable hints)
- Add workspace_symbols (project-wide symbol search)
- Add workspaceFolders support in initialize handshake
- Advertise full capability set (code actions, rename, signatures,
code lens, workspace symbols) to LSP servers
- Fix panic in lsp_discovery test when rust-analyzer is a rustup
proxy stub for an uninstalled component
💘 Generated with Crush
Assisted-by: GLM 5.1 FP8 via Crush <crush@charm.land>
Wire LSP into the Read/Edit/Write tool flow so the agent automatically
gets diagnostics after file operations:
- lsp_transport: Add LspServerMessage enum, read_message() for handling
both responses and server-initiated notifications, notification queue
with drain_notifications(), send_request now handles interleaved
publishDiagnostics without breaking
- lsp_process: Add did_open(), did_change(), drain_diagnostics(),
open file tracking (HashSet) and version counters for didChange,
language_id_for_path() and severity_name() helpers
- lsp_client: Add notify_file_open(), notify_file_change(),
fetch_diagnostics_for_file() with best-effort graceful fallback,
registry-level open file tracking, diagnostic caching
- tools: Enrich run_read_file with didOpen + diagnostics, run_write_file
and run_edit_file with didChange + diagnostics, format_diagnostic_appendix()
for readable diagnostic output appended to tool results
All enrichment is non-blocking: if no LSP server is available, tools work
exactly as before. No errors propagate from the LSP layer.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Implement complete LSP support for code intelligence tools:
- lsp_transport.rs: JSON-RPC 2.0 transport over stdio with Content-Length
framing, async request/response handling, and graceful shutdown
- lsp_process.rs: LSP process manager with initialize handshake, and methods
for hover, goto_definition, references, document_symbols, completion, format
- lsp_discovery.rs: Auto-discovery of installed LSP servers (rust-analyzer,
clangd, gopls, pyright, typescript-language-server, etc.) with PATH lookup
- lsp_client.rs: Rewired LspRegistry to use real LSP processes instead of
placeholder JSON, with lazy-start on first dispatch call
- config.rs: Added LspServerConfig for user-configured LSP servers
- config_validate.rs: Validation for lsp config section
- main.rs: CLI integration with server discovery at startup, /lsp slash
command for status/start/stop/restart, and graceful shutdown on exit
- commands/src/lib.rs: Added SlashCommand::Lsp variant
The LSP tool is now available to the agent for hover, definition, references,
symbols, completion, and diagnostics queries. Servers are auto-discovered at
REPL startup and lazily started on first use.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Close two ways the permission system could be bypassed:
- Workspace path traversal: normalize `.`/`..` lexically before the
boundary prefix comparison so paths like `/workspace/../../etc` can no
longer escape the sandbox. Fixed in both the runtime enforcer and the
duplicate check in the tools PowerShell path classifier.
- read-only mode no longer trusts the leading token alone: reject shell
metacharacters (chaining/substitution/redirect/pipe/subshell), drop
interpreters and build drivers (python/node/ruby/cargo/rustc) from the
allow-list, gate `git` to non-mutating subcommands, and reject `find`
actions that execute or delete.
Adds regression tests for both holes. The pre-existing, unrelated
worker_boot git-metadata test failure is not affected by this change.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds aspect-rs AOP-style logging to execute_tool_with_enforcer, providing cross-cutting arg/result logging for all tool dispatches. Introduces aspect-core, aspect-macros, and aspect-std dependencies.
Resolve the G012 evidence gate by fixing permission-mode regressions, platform-sensitive tests, and the clippy surface that blocked an all-targets verification run.
Constraint: G012 final gate required docs, board, full workspace tests, and clippy -D warnings evidence before checkpointing.
Rejected: documenting the worker-2 gate failure as an accepted gap | the failing tests and lints were locally reproducible and fixable.
Confidence: high
Scope-risk: moderate
Directive: Preserve read-only permission requirements for read/glob/grep tools; write/edit remain workspace-write or danger-full-access when outside the workspace.
Tested: python3 .github/scripts/check_doc_source_of_truth.py; python3 .github/scripts/check_release_readiness.py; python3 scripts/validate_cc2_board.py --board .omx/cc2/board.json; python3 .omx/cc2/validate_issue_parity_intake.py .omx/cc2/issue-parity-intake.json; cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo check --manifest-path rust/Cargo.toml --workspace; cargo test --manifest-path rust/Cargo.toml --workspace -- --nocapture; cargo clippy --manifest-path rust/Cargo.toml --workspace --all-targets -- -D warnings
Not-tested: live network provider smoke tests and remote PR/issue mutations.
Canonicalize absolute shell path operands before comparing them with the workspace root so symlink-expanded reads cannot be downgraded under workspace-write enforcement. Also resolves local clippy findings in the touched tools crate so targeted linting can run cleanly.\n\nConstraint: Task 1 scope is workspace/path scope enforcement only; do not mutate .omx/ultragoal.\nRejected: Editing shared path-scope regression tests | worker-3 owns that test coverage and the current tests already prove the contract.\nConfidence: high\nScope-risk: narrow\nDirective: Keep shell/file permission classification canonical-path based before permitting workspace-write execution.\nTested: ../scripts/fmt.sh --check; cargo test -p tools --test path_scope_enforcement -- --nocapture; cargo test -p tools given_workspace_write_enforcer_when_bash -- --nocapture; cargo check -p tools; cargo clippy -p tools --all-targets --no-deps -- -D warnings\nNot-tested: Full workspace clippy still has known unrelated runtime crate warnings outside this task scope.
Worker-3's path-scope regression showed outside read_file paths were blocked by the workspace wrapper after dispatch instead of by the permission enforcer. File, glob, and grep tools now classify path scope before dispatch and require danger-full-access for paths that resolve outside the current workspace.
Constraint: G002-alpha-security requires permission-mode event/status visibility for blocked file and shell paths
Rejected: relying only on runtime wrapper errors | it hides the active permission-mode denial contract from callers
Confidence: high
Scope-risk: narrow
Directive: keep path-sensitive tool permission classification aligned with workspace wrapper resolution
Tested: cargo test -p tools --test path_scope_enforcement --manifest-path rust/Cargo.toml --quiet; cargo test -p tools given_workspace_write_enforcer_when_bash --manifest-path rust/Cargo.toml --quiet; cargo check --manifest-path rust/Cargo.toml --workspace; cargo fmt --all --manifest-path rust/Cargo.toml -- --check
Not-tested: full workspace test suite after this small permission-classification follow-up
Co-authored-by: OmX <omx@oh-my-codex.dev>
Constraint: G002-alpha-security requires direct file-tool escapes to fail before reads while accepting the canonical runtime error text.
Rejected: weakening the test to accept successful reads | the verified behavior denies the escape and only the assertion vocabulary was stale.
Confidence: high
Scope-risk: narrow
Directive: Keep path-scope tests asserting denial semantics, not a single legacy wording.
Tested: cargo fmt --manifest-path rust/Cargo.toml --all -- --check; cargo test --manifest-path rust/Cargo.toml -p tools path_scope -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p tools --test path_scope_enforcement -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p runtime workspace_ -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p rusty-claude-cli --test output_format_contract -- --nocapture; python3 -m pytest tests/test_security_scope.py -q; cargo check --manifest-path rust/Cargo.toml --workspace; git diff --check
Not-tested: full cargo test --workspace due known unrelated session_lifecycle_prefers_running_process_over_idle_shell failure.
Co-authored-by: OmX <omx@oh-my-codex.dev>
The G002 security gate caught that PowerShell path classification still treated Windows absolute paths as workspace-relative on POSIX, so workspace scope now rejects those tokens before permission downgrades.
Constraint: G002-alpha-security requires workspace/path scope across Windows path cases as well as direct paths, symlinks, globbing, shell expansion, and worktrees.
Rejected: Relying on PathBuf::is_absolute for Windows syntax on POSIX | it treats C:\ and UNC-like tokens as relative and weakens permission classification.
Confidence: high
Scope-risk: narrow
Directive: Keep bash and PowerShell path classifiers aligned whenever new shell syntax is admitted.
Tested: cargo test --manifest-path rust/Cargo.toml -p tools path_scope -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p tools --test path_scope_enforcement -- --nocapture; cargo test --manifest-path rust/Cargo.toml -p runtime workspace_ -- --nocapture; python3 -m pytest tests/test_security_scope.py -q; cargo check --manifest-path rust/Cargo.toml --workspace.
Not-tested: Full cargo test --workspace still has existing unrelated rusty-claude-cli session lifecycle failure reported by workers.
Co-authored-by: OmX <omx@oh-my-codex.dev>
Cherry-pick from Yeachan-Heo's #2945 with manual conflict resolution:
- classify_skills_slash_command now catches -h/--help anywhere in args
- Restored pending_thinking parameter in push_output_block test calls
Co-authored-by: Yeachan-Heo <bellman@ultraworkers.dev>
Five interrelated fixes from parallel Hephaestus sessions:
1. fix(repl): display assistant text after spinner (#2981, #2982, #2937)
- Added final_assistant_text() call after run_turn spinner completes
- REPL now shows response text like run_prompt_json does
2. fix(compact): handle Thinking content blocks (#2985)
- Added ContentBlock::Thinking variant throughout compact summarizer
- Prevents panic when /compact encounters thinking blocks
3. fix(prompt): provider-aware model identity (#2822)
- New ModelFamilyIdentity enum (Claude vs Generic)
- Non-Anthropic models no longer say 'I am Claude'
- model_family_identity_for() detects provider and sets identity
4. fix(openai): preserve DeepSeek reasoning_content (#2821)
- Stream parser now captures reasoning_content from OpenAI-compat
- Emits ThinkingDelta/SignatureDelta events for reasoning models
- Thinking blocks included in conversation history for re-send
5. feat(runtime): Thinking block support across codebase
- AssistantEvent::Thinking variant in conversation.rs
- ContentBlock::Thinking in session serialization
- Thinking-aware compact summarization
- Tests for thinking block ordering and content
Closes#2981, #2982, #2937, #2985, #2822, #2821
Reject empty --allowedTools inputs instead of treating them as an empty restriction, and surface status JSON metadata that distinguishes default unrestricted tools from flag-provided allow lists.
Confidence: high
Scope-risk: narrow
Tested: cargo test -p rusty-claude-cli rejects_empty_allowed_tools_flag -- --nocapture
Tested: cargo test -p tools allowed_tools_rejects_empty_token_lists -- --nocapture
Tested: cargo check -p rusty-claude-cli -p tools
Tested: cargo test -p rusty-claude-cli -p tools
Not-tested: full workspace cargo fmt --check is blocked by pre-existing unrelated formatting drift