The local-Ollama section described provider routing as only triggering
when OPENAI_BASE_URL is set and the model name contains a `:` or `.`,
but that heuristic only applies to prefix-less model names. The example
uses the explicit `openai/` prefix, which selects the OpenAI-compatible
provider directly (and is stripped before the tag reaches Ollama).
Split the explanation into the two routing paths so the colon tag is
correctly described as an Ollama requirement, not the routing trigger.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Document running claw against a local Ollama server over its OpenAI-compatible
endpoint: build, env vars (OPENAI_BASE_URL / OPENAI_API_KEY), the exact
colon-tag model-name requirement (`qwen3.5:9b`, not `qwen3.5-9b`), how to list
installed tags, a WSL connectivity note, and reasoning-model behaviour.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ollama's Qwen3 thinking models stream the chain-of-thought in a `reasoning`
field with an empty `content`. The OpenAI-compatible provider only recognised
`reasoning_content`/`thinking`, so reasoning-only responses surfaced no text
at all.
Add `reasoning` to both the streaming (`ChunkDelta`) and non-streaming
(`ChatMessage`) shapes and fall back to it when extracting thinking, preserving
the existing thinking/text content-block separation. Covered by two new tests
for the streaming and non-streaming paths.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When users type bare qwen model names (e.g., qwen3.5:9b), the validator
already suggested qwen/ prefix for DashScope. Now it also documents the
local Ollama path: use openai/ prefix with OPENAI_BASE_URL and
OPENAI_API_KEY=ollama.
This addresses the confusion observed when debugging Ollama integration
after the upstream merge, where users might follow the DashScope hint
but actually want to run models locally via Ollama.
- 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)
Updated the agents_and_skills_usage_support_help_and_unexpected_args
test to match the new skills help text that includes [--project].
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
Session save_to_path now wraps ENOENT errors from rotate and atomic
write with a clear "possible concurrent modification" message instead
of surfacing raw OS errno. Helps operators debugging race conditions
when multiple claw invocations touch the same session file.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
SessionLifecycleSummary now collects all matching tmux panes into an
all_panes field and includes them in the JSON output. Previously the
status command returned on the first non-idle pane, losing all other
active panes in the same workspace/session.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
401 and 403 errors now include a hint explaining which env vars to
check for each provider (OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.)
and suggesting claw doctor for credential verification.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
claw skills install --project <path> now installs to .claw/skills/
in the current project instead of the user-level registry. Skills
installed at project level are already discovered by the existing
registry system. Both text and JSON handlers updated.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
MCP server config now expands ${VAR} environment variable references
and ~/ home directory prefix in command, args, and url fields. Previously
these values were passed verbatim to execve/URL-parse, causing silent
"No such file or directory" failures for standard config patterns.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
deep_merge_objects now concatenates arrays when both layers provide
the same key. Previously permissions.allow, hooks.PreToolUse, etc.
from earlier config layers (e.g. ~/.claw/settings.json) were silently
discarded when a later layer (e.g. project .claw/settings.json) set
the same key. Now arrays are merged additively across layers.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
PermissionRule::parse now normalizes tool_name to lowercase, matching
the runtime convention. Previously "Bash(rm:*)" would never match
because the runtime tool name is lowercase "bash". Same fix applied
to denied_tools list.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
/resume mode /clear now preserves the original session_id instead of
generating a new one. This prevents the filename/meta-header divergence
where /session list reported an id that --resume couldn't find.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
/session switch and /session fork now return structured JSON with
kind:error, error_kind:unsupported_resumed_command, and actionable
hint instead of a raw error string that resume callers couldn't parse.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
Verified with a roundtrip test: creating a session with usage data
({input_tokens:100, output_tokens:50}), saving to JSONL, loading via
--resume, and running /cost and /stats both return correct values.
The UsageTracker::from_session reads message.usage which is properly
serialized/deserialized by ConversationMessage::to_json/from_json.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
Add friendly_cwd() helper that strips /private prefix on macOS so
status, doctor, and diff JSON output matches user-visible invocation
cwd instead of the canonicalized /private/tmp path.
Applied to status_context() and render_doctor_report().
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
342: /commands command-index alias is now covered by /help --output-format
json which returns structured commands array with 139 entries (name,
summary, resume_supported per command). Implemented in #325.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
/model was in the unsupported resume group but is a read-only command
that can safely return model configuration. Now returns default_model,
configured_model, resolved_model, and requested_model in JSON mode.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
--compact was silently ignored when used with non-prompt commands like
claw --compact status or claw --compact config. Now returns a typed
error with guidance on proper usage.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
/tasks was marked resume_supported but rejected in resume mode.
Now returns a structured JSON response with kind:'tasks' and note
that background tasks are only available in the interactive REPL.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
- /config help now returns available_sections array and loaded_keys
count instead of treating 'help' as an unsupported section
- Updated test to exclude 'help' from unsupported sections test
- Added new test config_help_returns_structured_section_list_344
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
/config help now returns a list of available config sections in both
text and JSON mode instead of treating 'help' as an unsupported section.
Text mode shows available sections with descriptions.
JSON mode returns available_sections array with loaded_keys count.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
Top-level 'claw --output-format json help' now includes a 'commands'
array with name, summary, and resume_supported for each registered
slash command, plus 'total_commands' count.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
plugins enable now checks if the plugin was already enabled before
setting reload_runtime:true. Same for disable. Returns 'already enabled'
or 'already disabled' in the message when no state change occurred.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
339: /session delete works in resume mode with --force flag. The
confirmation-required path returns a typed JSON error with hint.
delete-force path performs actual deletion with proper JSON response.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
129: MCP server startup does not block credential validation - credentials
are resolved via resolve_cli_auth_source() before build_runtime() which
is where MCP state discovery happens.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
Add GitOperation enum to detect mid-operation git states from the
branch header in git status --short --branch output.
- Rebase: 'rebasing ...' in branch header
- Merge: '[merge-in-progress]' tag
- Cherry-pick: 'cherry-pick-in-progress' tag
- Bisect: 'bisect-in-progress' tag
Operation state appears in:
- status text: 'rebase-in-progress, dirty · 3 files · ...'
- status JSON: 'git_operation' field (null when no operation)
- git_state headline includes operation prefix
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
--base-commit now rejects non-hex strings and strings outside 7-64
character range. Matches the pattern used by --reasoning-effort.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
The --cwd validation added in #99 rejects non-existent paths, but the
test used /tmp/project which doesn't exist on CI Linux runners. Changed
to /tmp which exists everywhere.
Also marks ROADMAP #123 DONE (--allowedTools normalization verified).
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
120: config parse errors now surfaced via load_error with hint
121: hooks already uses PreToolUse/PostToolUse/Claude Code format
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
MCP server details JSON now redacts args (shows count only),
strips URL query params which may contain tokens, and shows
headers_helper as configured/not-configured boolean instead of
the raw command string. env_keys and header_keys still exposed
(key names only, not values).
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
111: /providers routes to doctor slash command
115: init generates acceptEdits not dontAsk
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
status/doctor JSON now reports git_state:'no_git_repo' when
project_root is None, instead of the misleading 'clean' which
implied a git repo was present with zero changes.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
bootstrap-plan --output-format json now returns phases as structured
objects with id, label, description, and order fields instead of
raw Rust enum variant name strings. Also exposes total_phases count.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
--cwd now validates the path exists and is a directory before passing
it to the system prompt renderer. --date rejects values with newlines
or >20 chars to prevent prompt injection.
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>
105: status reads model from .claw.json config (model_source: config)
118: /stats and /tokens both route to stats handler
Generated with https://github.com/Yeachan-Heo/gajae-code
Co-authored-by: Gajae Code <dev@gajae-code.com>