Fix OpenClaw start default to local TUI (#6937)

* fix: launch OpenClaw local TUI by default

* Fix/adjust OpenClaw launch paths for PR #6937

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Default OpenClaw to the local TUI only on a bare invocation

The first-arg startswith('-') branch rewrote passthrough globals into a broken
command: OpenClaw's grammar is openclaw [--dev] [--profile <name>] <command>, so
'unsloth start openclaw --profile test' became 'openclaw tui --local --profile
test', but tui does not accept --profile (or --dev), so the invocation failed.

A leading '--flag value' is ambiguous between a global (--profile test) and a tui
option (--message hi), so it cannot be reinterpreted safely. Default to the local
TUI only when no passthrough args are given, and forward everything else verbatim
so OpenClaw parses it under its own grammar. The bare-launch default (the point
of this change) is preserved; explicit subcommands and global flags pass through.

---------

Co-authored-by: wasimysaid <112766706+wasimysaid@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: danielhanchen <danielhanchen@gmail.com>
Co-authored-by: Wasim Yousef Said <wasimysdev@gmail.com>
This commit is contained in:
Lee Jackson 2026-07-08 12:25:42 +01:00 committed by GitHub
parent 0e1ed88bb8
commit 6ef0936180
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 37 additions and 3 deletions

View file

@ -376,7 +376,7 @@ case "$MODE" in
hermes) patch_hermes_tools none
invoke_via_connect "$OUT" -z "$PROMPT" ;;
openclaw) patch_openclaw_agent notools
invoke_via_connect "$OUT" agent --local --agent ci \
CONNECT_CMD_OVERRIDE=openclaw invoke_via_connect "$OUT" agent --local --agent ci \
--model "unsloth/${UNSLOTH_MODEL_ID}" --message "$PROMPT" ;;
*) invoke_via_connect "$OUT" "$PROMPT" ;;
esac
@ -449,7 +449,7 @@ case "$MODE" in
fi ;;
opencode) invoke_via_connect "$out" run "$prompt" ;;
hermes) invoke_via_connect "$out" -z "$prompt" ;;
openclaw) invoke_via_connect "$out" agent --local --agent ci \
openclaw) CONNECT_CMD_OVERRIDE=openclaw invoke_via_connect "$out" agent --local --agent ci \
--model "unsloth/${UNSLOTH_MODEL_ID}" --message "$prompt" ;;
*) invoke_via_connect "$out" "$prompt" ;;
esac

View file

@ -1568,7 +1568,17 @@ def openclaw(
serve = serve,
launch = launch,
)
command = ["openclaw", *ctx.args]
openclaw_args = list(ctx.args)
# Default a bare `unsloth start openclaw` to the local TUI. Anything the caller
# passes through is forwarded verbatim so OpenClaw parses it under its own grammar
# (openclaw [global-flags] <command> [options]): an explicit subcommand, a global
# flag that must precede the command such as --profile/--dev, or a tui option. We
# cannot reinterpret those safely because a leading "--flag value" is ambiguous
# between a global (`--profile test`) and a tui option (`--message hi`); prepending
# `tui --local` would break the global form, so only the empty case is defaulted.
if not openclaw_args:
openclaw_args = ["tui", "--local"]
command = ["openclaw", *openclaw_args]
install_hint = (
"iwr -useb https://openclaw.ai/install.ps1 | iex"
if os.name == "nt"

View file

@ -1634,10 +1634,34 @@ def test_connect_openclaw_no_launch(fake_studio, tmp_path):
config = json.loads(config_path.read_text())
assert config["models"]["providers"]["unsloth"]["apiKey"] == "sk-unsloth-feedfacefeedface"
assert config["agents"]["defaults"]["model"]["primary"] == f"unsloth/{MODEL['id']}"
assert _launch_command(result.output) == ["openclaw", "tui", "--local"]
# OpenAI /v1/chat/completions works on either backend — no GGUF gate.
assert not any(c[1].endswith("/api/inference/status") for c in fake_studio)
def test_connect_openclaw_no_launch_keeps_explicit_subcommand(fake_studio):
result = CliRunner().invoke(start.start_app, ["openclaw", "--no-launch", "crestodian"])
assert result.exit_code == 0, result.output
assert _launch_command(result.output) == ["openclaw", "crestodian"]
def test_connect_openclaw_no_launch_passes_global_flags_through(fake_studio):
# OpenClaw globals (openclaw [--dev] [--profile <name>] <command>) precede the
# command, and tui does not accept them, so any passthrough args must be forwarded
# verbatim rather than rewritten into `openclaw tui --local <globals>`.
result = CliRunner().invoke(start.start_app, ["openclaw", "--no-launch", "--profile", "test"])
assert result.exit_code == 0, result.output
assert _launch_command(result.output) == ["openclaw", "--profile", "test"]
def test_connect_openclaw_no_launch_keeps_explicit_tui(fake_studio):
result = CliRunner().invoke(
start.start_app, ["openclaw", "--no-launch", "tui", "--message", "hi"]
)
assert result.exit_code == 0, result.output
assert _launch_command(result.output) == ["openclaw", "tui", "--message", "hi"]
# ── OpenCode (OpenAI /v1/chat/completions) ───────────────────────────