From 3047105ea4f3a865d644c69df38d119d3779f95a Mon Sep 17 00:00:00 2001 From: esengine <359807859@qq.com> Date: Fri, 25 Sep 2026 07:22:29 -0700 Subject: [PATCH] feat(cli): --permission-mode reads 1.x's names A 1.x command line keeps working under 2.x: workspace-write is Auto, danger-full-access is Yolo, and read-only, which 2.x has no mode for, falls back to Ask. MIGRATING says where yolo's meaning differs. Co-authored-by: BuGlessRB <2543983+BuGlessRB@users.noreply.github.com> --- docs/CLI.md | 9 ++++++--- docs/CLI.zh-CN.md | 2 +- docs/MIGRATING.md | 6 +++++- docs/ROADMAP.md | 2 +- internal/frontend/cli/cli.go | 11 +++++++---- internal/frontend/cli/cli_test.go | 4 ++++ internal/frontend/cli/shell_completion.go | 2 +- 7 files changed, 25 insertions(+), 11 deletions(-) diff --git a/docs/CLI.md b/docs/CLI.md index d9fdef21c6..07f126ee82 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -19,8 +19,10 @@ reasonix --preset delivery --effort high reasonix --dir /path/to/project ``` -Running `reasonix` without a subcommand starts the interactive terminal UI. Use -`reasonix setup` first when no provider is configured. +Running `reasonix` without a subcommand starts the interactive terminal UI; +`reasonix tui` is the same command. Without a terminal, for example in a script +or a pipe, it prints usage instead. Use `reasonix setup` first when no provider +is configured. | Flag | Purpose | | --- | --- | @@ -35,8 +37,9 @@ Running `reasonix` without a subcommand starts the interactive terminal UI. Use | `-r`, `--resume [QUERY]` | Open the session picker, or resume a matching session. | | `--copy` | Continue in a writable copy of the resumed session. | | `--allowed-tools RULES` | Add session-only permission allow rules. Repeatable; `--allowedTools` is an alias. | -| `--permission-mode MODE` | Start with a specific permission posture. | +| `--permission-mode MODE` | Start with a specific permission posture: `ask`, `auto`, `acceptEdits`, `dontAsk`, `plan` or `bypassPermissions`. 1.x's `workspace-write`, `danger-full-access` and `read-only` also work, as Auto, Yolo and Ask. | | `--yolo` | Start in YOLO mode; alias for `--dangerously-skip-permissions`. | +| `--inline` | Write the conversation into the terminal's scrollback instead of taking the full screen. | Flags may appear before or after the prompt where applicable. diff --git a/docs/CLI.zh-CN.md b/docs/CLI.zh-CN.md index 1fa7ef124a..20a5313fea 100644 --- a/docs/CLI.zh-CN.md +++ b/docs/CLI.zh-CN.md @@ -34,7 +34,7 @@ reasonix --dir /path/to/project | `-r`、`--resume [QUERY]` | 打开会话选择器,或恢复匹配的会话。 | | `--copy` | 复制要恢复的会话,并在可写副本中继续。 | | `--allowed-tools RULES` | 增加仅当前会话生效的权限 allow 规则;可重复传入,`--allowedTools` 是别名。 | -| `--permission-mode MODE` | 以指定的权限姿态启动。 | +| `--permission-mode MODE` | 以指定的权限姿态启动:`ask`、`auto`、`acceptEdits`、`dontAsk`、`plan` 或 `bypassPermissions`。1.x 的 `workspace-write`、`danger-full-access`、`read-only` 也能用,分别对应 Auto、Yolo、Ask。 | | `--yolo` | 以 YOLO 模式启动;是 `--dangerously-skip-permissions` 的别名。 | 适用时,参数可以放在 prompt 前面或后面。 diff --git a/docs/MIGRATING.md b/docs/MIGRATING.md index 7c3cffc26f..e5d2a868c9 100644 --- a/docs/MIGRATING.md +++ b/docs/MIGRATING.md @@ -61,7 +61,11 @@ Where 1.x keeps a conversation depends on the 1.x version that last saved it. | 1.x | 2.x | | --- | --- | -| `reasonix`, `reasonix -c`, `reasonix -r` | `reasonix tui`, `reasonix tui -c`, `reasonix tui -r`. Bare `reasonix` prints usage in 2.x. | +| `reasonix`, `reasonix -c`, `reasonix -r` | The same, in a terminal. `reasonix tui` is another name for it. | +| `--permission-mode workspace-write` | Auto | +| `--permission-mode danger-full-access` | Yolo | +| `--permission-mode read-only` | Ask. 2.x has no read-only mode, so this is the most careful one it has. | +| `--yolo`, `--permission-mode yolo` or `bypassPermissions` | Yolo. In 1.x these meant `workspace-write`; in 2.x they skip ordinary approval prompts. | | `reasonix run`, `serve`, `web`, `acp`, `mcp`, `setup`, `doctor` | Same names | | `reasonix bot` | Not in 2.x. The `[bot]` config section stays for 1.x. | | VS Code extension | Starts the `reasonix` found on `PATH`, so it runs whichever line's CLI comes first there. | diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index d2fadf67f9..063da538d4 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -57,7 +57,7 @@ The 2.x terminal UI (`reasonix tui`) replaces the 1.x chat screen for people who | T3 | Full screen by default with scrollbar, wheel, drag-select copy, `/mouse`; `--inline` for the terminal's own scrollback | Done | | T4 | `-r` session picker and `/resume`; system notifications; Ctrl+B for long shell output | Done | | T5 | Ctrl+V pastes a screenshot (Alt+V on Windows) | Done | -| T6 | Bare `reasonix`, `reasonix -c` and `reasonix -r` start the terminal UI, as they do in 1.x | Not started | +| T6 | Bare `reasonix`, `reasonix -c` and `reasonix -r` start the terminal UI, as they do in 1.x, with 1.x's session options and permission-mode names | Done | | T7 | Windows checks by hand: IME candidate window position, Alt+V image paste | Not started | | T8 | Local install test of the npm package and the Homebrew cask before the switch release | Not started | | T9 | `README.md` and `README.zh-CN.md` name npm and Homebrew as the 2.x CLI channels in the switch release | Not started | diff --git a/internal/frontend/cli/cli.go b/internal/frontend/cli/cli.go index b8fd32bdc4..dea478c28c 100644 --- a/internal/frontend/cli/cli.go +++ b/internal/frontend/cli/cli.go @@ -231,11 +231,14 @@ type cliPermissionMode struct { allow []string } +// parsePermissionMode also reads 1.x's three names, so a 1.x command line +// keeps working: workspace-write is Auto, danger-full-access is Yolo, and +// read-only, which 2.x has no mode for, falls back to the most careful one. func parsePermissionMode(value string) (cliPermissionMode, error) { switch strings.ToLower(strings.TrimSpace(value)) { - case "", "default", "ask": + case "", "default", "ask", "read-only": return cliPermissionMode{approval: control.ToolApprovalAsk}, nil - case "auto": + case "auto", "workspace-write": return cliPermissionMode{approval: control.ToolApprovalAuto}, nil case "acceptedits", "accept-edits": return cliPermissionMode{approval: control.ToolApprovalAsk, allow: []string{ @@ -247,10 +250,10 @@ func parsePermissionMode(value string) (cliPermissionMode, error) { return cliPermissionMode{approval: control.ToolApprovalDontAsk}, nil case "plan": return cliPermissionMode{approval: control.ToolApprovalAsk, plan: true}, nil - case "bypasspermissions", "bypass-permissions", "yolo": + case "bypasspermissions", "bypass-permissions", "yolo", "danger-full-access": return cliPermissionMode{approval: control.ToolApprovalYolo}, nil default: - return cliPermissionMode{}, fmt.Errorf("unknown permission mode %q (want manual, ask, auto, acceptEdits, dontAsk, plan, or bypassPermissions)", value) + return cliPermissionMode{}, fmt.Errorf("unknown permission mode %q (want manual, ask, auto, acceptEdits, dontAsk, plan, or bypassPermissions; 1.x's read-only, workspace-write and danger-full-access also work)", value) } } diff --git a/internal/frontend/cli/cli_test.go b/internal/frontend/cli/cli_test.go index d0d7a2b621..61bb6684ee 100644 --- a/internal/frontend/cli/cli_test.go +++ b/internal/frontend/cli/cli_test.go @@ -333,6 +333,10 @@ func TestParsePermissionModeClaudeAliases(t *testing.T) { "dontAsk": {approval: control.ToolApprovalDontAsk}, "plan": {approval: control.ToolApprovalAsk, plan: true}, "bypassPermissions": {approval: control.ToolApprovalYolo}, + // 1.x's names, so a 1.x command line keeps working. + "workspace-write": {approval: control.ToolApprovalAuto}, + "danger-full-access": {approval: control.ToolApprovalYolo}, + "read-only": {approval: control.ToolApprovalAsk}, } for input, want := range tests { got, err := parsePermissionMode(input) diff --git a/internal/frontend/cli/shell_completion.go b/internal/frontend/cli/shell_completion.go index ce9dc75f06..53647ad0c0 100644 --- a/internal/frontend/cli/shell_completion.go +++ b/internal/frontend/cli/shell_completion.go @@ -81,7 +81,7 @@ func cliCompletionRootSpec() cliCompletionSpec { resume := completionFlag("--resume -r", cliCompletionOptionalValue) // optional QUERY effort := completionFlag("--effort", cliCompletionStaticValue, "auto", "low", "medium", "high", "max") permissionMode := completionFlag("--permission-mode", cliCompletionStaticValue, - "manual", "ask", "auto", "acceptEdits", "dontAsk", "plan", "bypassPermissions") + "manual", "ask", "auto", "acceptEdits", "dontAsk", "plan", "bypassPermissions", "read-only", "workspace-write", "danger-full-access") help := completionFlag("--help -h", cliCompletionNoValue) // run/serve --resume require a value; only interactive root --resume [QUERY] is optional.