When the model returns multiple tool_use blocks in a single response,
read-only tools (read_file, glob_search, grep_search, WebFetch,
WebSearch, LSP, Git*) now execute concurrently via std:🧵:scope
instead of sequentially.
Architecture:
- Add ToolCall/ToolResult types to ToolExecutor trait
- Add execute_batch() with default sequential fallback
- CliToolExecutor overrides execute_batch to classify tools as
parallel-safe or sequential, then runs parallel-safe tools
concurrently via thread scopes
- run_turn refactored into 3 phases:
1. Pre-hooks + permission checks (sequential, hooks may mutate state)
2. Tool execution (batch, parallel for read-only tools)
3. Post-hooks + session updates (sequential, preserves ordering)
Safety guarantees:
- Pre/post hooks always run sequentially
- Permission checks complete before any tool executes
- Tool results pushed to session in original model order
- Fallback to sequential for single-tool batches
Adds a project rules system for loading instruction files into the
system prompt, plus auto-import from other AI coding frameworks.
- `.claw/rules/*.md` / `.claw/rules/*.txt` / `.claw/rules/*.mdc`
- `.claw/rules.local/*.md` — personal/local rules (gitignored)
- Existing: `CLAUDE.md`, `CLAUDE.local.md`, `.claw/CLAUDE.md`,
`.claw/instructions.md`
When users switch to claw-code from another tool, their existing
rules are automatically detected and loaded:
- Cursor: `.cursorrules`, `.cursor/rules/`
- GitHub Copilot: `.github/copilot-instructions.md`
- Windsurf: `.windsurfrules`, `.windsurfrules/`
- Aider: `.aider.conf.yml` instructions block
- Pi (Plandex): `.plandex/instructions.md`, `.plandex/plan.md`
- OpenCode: `opencode.json` instructions field
- Crush: `.crush/CLAUDE.md`, `.crush/rules/`
`rulesImport` in settings.json controls framework auto-import:
- `"auto"` (default) — import from all detected frameworks
- `"none"` — only load .claw/rules/ and CLAUDE.md files
- `["cursor", "copilot"]` — import only from listed frameworks
```json
{
"rulesImport": "auto"
}
```
💘 Generated with Crush
Assisted-by: GLM 5.1 FP8 via Crush <crush@charm.land>
- Startup now shows "Loading LSP servers..." then ✓/✗ per server
- When auto-start is on: shows disable hint (toggle or settings.json)
- When auto-start is off: shows available servers with how to start
💘 Generated with Crush
Assisted-by: GLM 5.1 FP8 via Crush <crush@charm.land>
Set NODE_NO_WARNINGS=1 when spawning LSP server processes to suppress
noisy punycode deprecation warnings from bash-language-server,
yaml-language-server, vscode-* servers, etc.
💘 Generated with Crush
Assisted-by: GLM 5.1 FP8 via Crush <crush@charm.land>
Godot LSP runs as a TCP server on localhost:6008 when the editor is
open — it doesn't speak LSP over stdio like other servers. Added
connect_tcp() to LspTransport which uses socat (or nc fallback) as
a stdio↔TCP bridge, reusing the existing Content-Length framing.
lsp_process detects tcp:// URIs and routes to TCP transport.
LSP startup now gracefully handles servers that fail to start
(gdscript without a running Godot editor) without blocking other
servers from initializing.
💘 Generated with Crush
Assisted-by: GLM 5.1 FP8 via Crush <crush@charm.land>
- 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>
Remove SlashCommand::Setup (provider wizard), PROVIDER_FIELDS
(provider config), and stale imports that leaked in from the
feat/lsp-integration branch which included other PRs. Also fix
pre-existing clippy findings (Duration::from_hours, is_ok_and).
- Add lsp_auto_start field to RuntimeFeatureConfig (default: true)
- Add lspAutoStart bool field validation in config_validate
- Parse lspAutoStart from config JSON
- Auto-start discovered LSP servers on REPL init when enabled
- Add /lsp toggle command to enable/disable auto-start at runtime
- Remove lsp_client.rs, lsp_process.rs, lsp_transport.rs (2831 lines)
— functionality consolidated into discovery-based auto-start
- Show auto-start status in /lsp status output
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>
- Add TimeoutConfig to HTTP client builder with connect_timeout (30s)
and request_timeout (5min) defaults, configurable via
CLAW_API_CONNECT_TIMEOUT and CLAW_API_REQUEST_TIMEOUT env vars
- Add with_timeout() builder to both AnthropicClient and
OpenAiCompatClient for per-client timeout configuration
- Parse Retry-After header on 429 responses and use it to override
exponential backoff delay when present
- Add ApiTimeoutConfig to runtime config with apiTimeout settings
in ~/.claw/settings.json (connectTimeout, requestTimeout, maxRetries)
- Add retry_after field to ApiError::Api for propagating rate limit
backoff hints through the retry pipeline
Add the 3-stage Trident compaction strategy from R.A.D.1.C.A.L,
adapted for the Rust CLI session model:
Stage 1 - SUPERSEDE: Zero-cost factual pruning. If a file was read
and then later written/edited, the earlier read is obsolete and
removed. Earlier writes superseded by later writes are also dropped.
Stage 2 - COLLAPSE: Buffer short chatty exchanges (under 200 chars,
no tool calls) and collapse them into dense summary blocks when the
threshold is exceeded.
Stage 3 - CLUSTER: Group semantically similar messages (same tool
names, same file paths, similar lengths) using Jaccard-based
fingerprinting and collapse clusters into summary blocks.
All three stages run before the existing summary-based compaction,
so less data needs to be summarized. Wired into both /compact and
the auto-compact retry on context window errors.
- Add lsp_auto_start field to RuntimeFeatureConfig (default: true)
- Add lspAutoStart bool field validation in config_validate
- Parse lspAutoStart from config JSON
- Auto-start discovered LSP servers on REPL init when enabled
- Add /lsp toggle command to enable/disable auto-start at runtime
- Remove lsp_client.rs, lsp_process.rs, lsp_transport.rs (2831 lines)
— functionality consolidated into discovery-based auto-start
- Show auto-start status in /lsp status output
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>
rust-analyzer installed through rustup exits non-zero on --version
("Unknown binary in official toolchain"), which caused discovery
to skip it. Changed command_exists_on_path to treat any successful
spawn as "found", regardless of exit code — only a failure to
spawn (command not found) means the server isn't available.
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>
Ctrl+P now inserts a sentinel char (\x01) that the highlighter renders
as a cyan "[Provider Swap]" prompt. User presses Enter to confirm and
launch the setup wizard. Returns ReadOutcome::ProviderSwap so the REPL
loop can hot-swap the model and reprint the connection line.
Also fixes clippy warnings: merged duplicate match arms in
provider_config_value, doc_markdown on ProviderKind, map_unwrap_or
idioms in setup_wizard.rs, and pre-existing clippy issues in main.rs
and commands/lib.rs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds an interactive setup wizard that lets users configure their provider,
API key, base URL, and model without setting environment variables.
Configuration is persisted to ~/.claw/settings.json (with 0600 permissions).
New features:
- `claw setup` CLI subcommand runs the wizard from the terminal
- `/setup` slash command runs the wizard inside the REPL (hot-swaps model)
- Ctrl+P hotkey in the REPL triggers /setup for in-session provider swap
- Stored provider config used as fallback when env vars are absent
- Three-tier auth resolution: env var > .env file > stored config
- RuntimeProviderConfig struct and validation in settings schema
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- OLLAMA_HOST takes priority over OPENAI_BASE_URL for local Ollama instances
- No API key required; placeholder token used for Authorization header
- Model names like 'qwen3:8b' bypass strict provider/model syntax validation
- detect_provider_kind() checks OLLAMA_HOST first in routing cascade
- ProviderClient dispatch uses from_ollama_env() when OLLAMA_HOST is set
- Updated USAGE.md and docs with OLLAMA_HOST as preferred env var
- Added OLLAMA_CONFIG constant and from_ollama_env() to openai_compat
- Added test_ollama_host_bypasses_model_validation unit test
- Supersedes PR #3213 (which had a duplicate if-let bug in mod.rs)
- Update slash_command_specs().len() assertion from 139 to 140.
The /setup command added by this PR increased the spec count by 1
but the test's expected count was not updated, causing CI failure.
- Add assert!(help.contains("/setup")) to the
renders_help_from_shared_specs test so the new command is
verified in the help output.
Fixes CI Build ❌ and Test ❌ on #3218.
The setup wizard was merged in PR #3017 but was orphaned -- it was not
declared as a module in main.rs, making it unreachable. Additionally,
the setup_wizard.rs imports RuntimeProviderConfig which did not exist
on upstream/main. This commit makes the wizard accessible and adds the
necessary RuntimeProviderConfig type.
Changes:
- Add RuntimeProviderConfig struct to runtime/src/config.rs with
kind(), api_key(), base_url(), model() accessors.
- Add parse_optional_provider_config() to parse the provider object
from merged settings JSON.
- Add provider() method to RuntimeConfig and RuntimeFeatureConfig.
- Export RuntimeProviderConfig, save_user_provider_settings,
clear_user_provider_settings, and default_config_home from runtime
crate public API (runtime/src/lib.rs).
- Add mod setup_wizard to rusty-claude-cli/src/main.rs.
- Add claw setup CLI subcommand.
- Add /setup slash command.
- Add Setup variant to SlashCommand enum.
- Add Setup to LocalHelpTopic enum.
- Add setup to diagnostic subcommand matching.
- Add subagentModel to TOP_LEVEL_FIELDS in config_validate.rs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>