Skip to content

fix(tui): rename internal bash tool to terminal for cross-platform accuracy - #1077

Open
ainaanraza wants to merge 1 commit into
AltimateAI:mainfrom
ainaanraza:fix-bash-rename-clean
Open

fix(tui): rename internal bash tool to terminal for cross-platform accuracy#1077
ainaanraza wants to merge 1 commit into
AltimateAI:mainfrom
ainaanraza:fix-bash-rename-clean

Conversation

@ainaanraza

@ainaanraza ainaanraza commented Aug 5, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #1070

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

This renames the internal bash tool to terminal across the codebase.

Calling the shell tool "bash" was misleading on platforms like Windows where the shell is usually PowerShell or CMD. This updates the tool IDs, exported classes (BashTool -> TerminalTool), and UI labels to be shell-agnostic.

(Note: Because this is a core tool rename, this PR unavoidably touches a large number of files—over 90—but the vast majority of these changes are simple 1-to-1 string and import renames).

I also added a backward compatibility layer in packages/core/src/v1/config/permission.ts and next.ts. This remaps the legacy bash key to terminal during config parsing, so existing users' altimate-code.json permission rules won't break. If a user happens to define both bash and terminal in their config, terminal takes precedence.

How did you verify your code works?

I ran bun run typecheck and bun test across the monorepo to ensure everything still builds and all snapshot/permission tests pass. I also verified that the module exports (like TerminalTool.layer) resolve correctly without circular dependencies.

Screenshots / recordings

N/A

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Summary by cubic

Renamed the internal bash tool to terminal for cross‑platform accuracy and clearer UX. Adds a compatibility layer that maps bash permissions to terminal so existing configs keep working (closes #1070).

  • Refactors

    • Tool ID and exports: bash -> terminal (BashTool -> TerminalTool), registry defaults and UI labels updated.
    • Permissions: config parser remaps bash to terminal; if both exist, terminal wins. Tests, telemetry, retrieval lists, and viewers updated.
    • CLI/TUI: renderers, session replay, and event handling now use terminal and accept legacy bash where needed.
  • Migration

    • No action required for existing altimate-code.json; bash continues to work.
    • For new code/plugins, import TerminalTool and use the terminal permission key.

Written for commit 5861452. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Renamed the built-in shell command tool from “Bash” to “Terminal” across the CLI, TUI, API, and tool listings.
    • Terminal commands now appear consistently in output, session history, tracing, and observability views.
  • Bug Fixes
    • Preserved compatibility with legacy “bash” permission settings while prioritizing explicit “terminal” rules.
    • Maintained existing command safety behavior: destructive commands remain denied, while permitted commands continue to prompt or run as configured.

Copilot AI review requested due to automatic review settings August 5, 2026 18:51

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The built-in BashTool is renamed to TerminalTool. The terminal identifier now propagates through registration, permissions, execution, observability, CLI, TUI, and tests. Legacy bash permission configuration remains supported when no explicit terminal configuration exists.

Changes

Terminal tool rename

Layer / File(s) Summary
Core tool contract and registration
packages/core/src/tool/*, packages/opencode/src/tool/*, packages/opencode/specs/v2/api.ts
The exported tool and registered identifier change from bash to terminal. Built-in registries, retrieval, shell IDs, permission requests, and metadata use the terminal name.
Permission compatibility and agent rules
packages/core/src/v1/config/permission.ts, packages/opencode/src/permission/*, packages/opencode/src/agent/agent.ts, packages/opencode/src/cli/cmd/agent.ts
Permission schemas accept terminal and retain bash compatibility. Explicit terminal settings take precedence. Agent safety, reviewer, analyst, explore, and CLI permission rules use terminal.
Runtime, CLI, and observability integration
packages/opencode/src/acp/*, packages/opencode/src/altimate/*, packages/opencode/src/cli/cmd/*, packages/opencode/src/session/prompt.ts
Shell detection, output snapshots, telemetry, command extraction, replay, rendering, demos, skill templates, and session parts recognize terminal.
Validation and interface fixtures
packages/core/test/*, packages/opencode/test/*, packages/tui/src/*, packages/tui/test/*
Permission, tool execution, tracing, session, provider, release, CLI, TUI, ACP, and transcript tests update tool fixtures and expectations to terminal while preserving existing behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: copilot, anandgupta42

Poem

A rabbit hops through names anew,
From bash to terminal, clean and true.
Permissions follow, tests align,
CLI and TUI now share the sign.
The shell wears one clear name.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the cross-platform rename of the internal bash tool to terminal.
Linked Issues check ✅ Passed The changes rename the internal bash tool to the shell-agnostic terminal name and update related references, satisfying issue #1070.
Out of Scope Changes check ✅ Passed The production and test changes support the requested tool rename and its backward-compatible permission mapping.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR performs a broad internal rename of the shell-execution tool from bash to terminal to better reflect cross-platform behavior (e.g., PowerShell/CMD on Windows) across the CLI/TUI runtime, permission wiring, telemetry, and tests.

Changes:

  • Renames tool IDs/usages from bashterminal across TUI/CLI/session/telemetry codepaths and associated test fixtures/snapshots.
  • Updates permission parsing and evaluation call sites to use terminal as the permission key (with some compatibility handling).
  • Updates documentation strings/readmes/specs to reflect the new tool name.

Reviewed changes

Copilot reviewed 95 out of 95 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/tui/test/util/transcript.test.ts Update transcript fixtures to terminal tool name
packages/tui/test/cli/tui/inline-tool-wrap-snapshot.test.tsx Update tool display test inputs for terminal
packages/tui/test/cli/tui/data.test.tsx Update tool event fixtures from bashterminal
packages/tui/src/routes/session/index.tsx Render shell tool under terminal and update known tool set
packages/tui/src/feature-plugins/home/tips-view.tsx Update config tip example to terminal
packages/opencode/test/v2/session-message-updater.test.ts Update v2 session updater fixtures to terminal
packages/opencode/test/upstream/v140-permission-deadlock.test.ts Update permission deadlock regression to terminal
packages/opencode/test/upstream/v140-merge-fuzz.test.ts Update telemetry outcome fixture tool name
packages/opencode/test/upstream/altimate-features.test.ts Rename safety rule fixtures from bash → terminal
packages/opencode/test/upstream/adversarial/upi-tool-api.test.ts Update UPI adversarial test to request terminal permission
packages/opencode/test/tui-journeys/README.md Update journey scripting docs to terminal tool
packages/opencode/test/tui-journeys/journeys.test.ts Update journey tool invocation to terminal
packages/opencode/test/tool/terminal.test.ts Rename tool import/usage to TerminalTool
packages/opencode/test/tool/task.test.ts Update task tool permission fixtures to terminal
packages/opencode/test/tool/shell.test.ts Update test helper naming for terminal init
packages/opencode/test/tool/retrieval.test.ts Update core-tool retention assertion to terminal
packages/opencode/test/tool/parameters.test.ts Update schema snapshot test label to terminal
packages/opencode/test/telemetry/telemetry.test.ts Update telemetry categorization fixtures
packages/opencode/test/skill/release-v0.8.6-adversarial.test.ts Update skill adversarial fixtures to terminal
packages/opencode/test/skill/release-v0.8.0-adversarial.test.ts Update release adversarial permission eval to terminal
packages/opencode/test/skill/release-v0.6.0-adversarial.test.ts Update tool name extraction expectations
packages/opencode/test/session/schema-decoding.test.ts Update session schema decode fixture permissions
packages/opencode/test/session/revert-compact.test.ts Update compact/revert tool fixture to terminal
packages/opencode/test/session/regression.test.ts Update regression fixture tool name
packages/opencode/test/session/prompt.test.ts Update prompt tests to use terminal tool key
packages/opencode/test/session/processor.test.ts Update processor telemetry fixtures to terminal
packages/opencode/test/session/observation-mask.test.ts Update observation mask formatting expectations
packages/opencode/test/session/message-v2.test.ts Update message-v2 tool call/result fixtures to terminal
packages/opencode/test/session/llm.test.ts Update toolNamesFromMessages expectations
packages/opencode/test/session/llm-native.test.ts Update native request/response fixtures to terminal
packages/opencode/test/session/compaction.test.ts Update compaction tool fixture to terminal
packages/opencode/test/session/compaction-mask.test.ts Update compaction mask fixtures/expectations
packages/opencode/test/release-validation/session-transcript-941.test.ts Update release validation transcript tool fixture
packages/opencode/test/release-validation/question-937.test.ts Update validation test tool import and references
packages/opencode/test/release-validation/question-937-codex.test.ts Update source-path read to terminal.ts
packages/opencode/test/provider/transform.test.ts Update provider transform fixtures to terminal
packages/opencode/test/permission/next.test.ts Update PermissionNext config parsing/eval fixtures
packages/opencode/test/permission-yolo.test.ts Update yolo-mode permission fixtures to terminal
packages/opencode/test/permission-task.test.ts Update permission-task assertions to terminal
packages/opencode/test/file/security-e2e.test.ts Update security E2E permission eval fixtures
packages/opencode/test/config/config.test.ts Update config-order preservation assertions
packages/opencode/test/cli/run/subagent-data.test.ts Update run subagent tool/permission fixtures
packages/opencode/test/cli/run/stream.transport.test.ts Update stream transport tool fixture to terminal
packages/opencode/test/cli/run/session-replay.test.ts Update replay fixtures to terminal
packages/opencode/test/cli/run/session-data.test.ts Update session-data fixtures to terminal
packages/opencode/test/cli/run/scrollback.surface.test.ts Update scrollback tool fixtures to terminal
packages/opencode/test/cli/run/permission.shared.test.ts Update permission UI copy fixtures to terminal
packages/opencode/test/cli/run/footer.view.test.tsx Update footer view fixtures to terminal
packages/opencode/test/cli/run/entry.body.test.ts Update entry body fixtures to terminal
packages/opencode/test/branding/build-integrity.test.ts Update source path checked for PATH injection
packages/opencode/test/altimate/tracing.test.ts Update tracing fixtures/top-tools assertions
packages/opencode/test/altimate/tracing-thorough.test.ts Update tracing fixtures to terminal
packages/opencode/test/altimate/tracing-rename-race.test.ts Update trace race fixture tool name
packages/opencode/test/altimate/tracing-integration.test.ts Update integration fixtures to terminal
packages/opencode/test/altimate/tracing-final-audit.test.ts Update audit fixtures to terminal
packages/opencode/test/altimate/tracing-e2e.test.ts Update E2E tracing fixtures to terminal
packages/opencode/test/altimate/tracing-display-crash.test.ts Update crash recovery fixture tool name
packages/opencode/test/altimate/tracing-de-attributes.test.ts Update DE attribute fixture tool name
packages/opencode/test/altimate/tracing-adversarial.test.ts Update adversarial tracing fixtures to terminal
packages/opencode/test/altimate/tracing-adversarial-snapshot.test.ts Update snapshot isolation fixtures to terminal
packages/opencode/test/altimate/tracing-adversarial-final.test.ts Update final adversarial fixtures to terminal
packages/opencode/test/altimate/tracing-adversarial-2.test.ts Update additional adversarial fixtures to terminal
packages/opencode/test/altimate/trace-consumer.test.ts Update trace consumer fixture tool name
packages/opencode/test/altimate/carry-forward/agent-safety.test.ts Update agent safety assertions to terminal
packages/opencode/test/agent/plan-mode-subagent-bypass.test.ts Update permission assertions to terminal
packages/opencode/test/agent/agent.test.ts Update agent default permission assertions and copy
packages/opencode/test/acp/event.test.ts Update ACP event fixtures to terminal
packages/opencode/src/tool/terminal.ts Rename tool definition/id and metadata tag naming
packages/opencode/src/tool/shell/id.ts Update shell tool kind/id defaults to terminal
packages/opencode/src/tool/retrieval.ts Update core tool list to include terminal
packages/opencode/src/tool/registry.ts Register TerminalTool instead of BashTool
packages/opencode/src/session/prompt.ts Emit tool parts with tool: "terminal"
packages/opencode/src/permission/next.ts Remap legacy bash config key to terminal
packages/opencode/src/permission/index.ts Remap legacy bash config key to terminal
packages/opencode/src/cli/cmd/skill.ts Rename default tool template helper (bash → terminal)
packages/opencode/src/cli/cmd/run/tool.ts Rename tool rule wiring and scroll copy to terminal
packages/opencode/src/cli/cmd/run/session-replay.ts Add bash/terminal compatibility for replay detection
packages/opencode/src/cli/cmd/run/session-data.ts Update session reduction logic to terminal tool name
packages/opencode/src/cli/cmd/run/demo.ts Update demo emitter/tool kind to terminal
packages/opencode/src/cli/cmd/run.ts Render tool parts under terminal handler
packages/opencode/src/cli/cmd/agent.ts Update available permissions list (terminal)
packages/opencode/src/altimate/tool-source.ts Update native tool id set (terminal)
packages/opencode/src/altimate/telemetry/index.ts Update file-tool categorization list to terminal
packages/opencode/src/altimate/observability/viewer.ts Update viewer shell-tool detection to terminal
packages/opencode/src/agent/agent.ts Update agent default permission config from bashterminal
packages/opencode/src/acp/tool.ts Update ACP shell-tool detection logic to terminal
packages/opencode/src/acp/event.ts Update running-tool snapshot gating for terminal
packages/opencode/specs/v2/api.ts Update API spec tool name to terminal
packages/core/test/tool-terminal.test.ts Update core tool tests and permission assertions to terminal
packages/core/test/session-tool-progress.test.ts Update core session tool progress fixtures
packages/core/test/session-runner-tool-registry.test.ts Update registry materialization expectations
packages/core/test/config/agent.test.ts Update agent permission evaluation to terminal
packages/core/src/v1/config/permission.ts Add terminal config key and normalization logic
packages/core/src/tool/terminal.ts Rename core tool name constant to terminal
packages/core/src/tool/builtins.ts Wire built-in location layer to TerminalTool
Suppressed comments (4)

packages/opencode/src/cli/cmd/run/session-data.ts:930

  • Shell-claiming is now gated on part.tool === "terminal" only. That means older sessions containing tool: "bash" won’t be treated as shell calls (affecting replay formatting and any synthetic shell commits). Consider accepting both names here, consistent with session-replay’s compatibility check.
    if (part.type === "tool") {
      const view = syncPermission(data, part) ?? syncQuestion(data, part)
      if (part.tool === "terminal" && part.callID) {
        if (claimShell(data, part.callID, "tool", terminalCommand(part)).source === "shell") {
          return out(data, commits, view)

packages/opencode/src/cli/cmd/run/session-data.ts:664

  • terminalCommand() ignores legacy tool: "bash" parts, which prevents shell command extraction when replaying older sessions that were saved before the rename.
function terminalCommand(part: ToolPart): string | undefined {
  if (part.tool !== "terminal") {
    return undefined
  }

packages/opencode/src/tool/terminal.ts:56

  • The TODO comment says this tool should be renamed for other shells, but the rename to terminal has already happened in this PR. Leaving it in place is misleading.
    packages/tui/src/routes/session/index.tsx:2652
  • To keep historical sessions readable, consider treating the legacy tool name bash as a known display tool. Without this, toolDisplay("bash") will return generic, and older transcripts won’t get the shell renderer.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +41 to +48
const normalizeInput = (input: Schema.Schema.Type<typeof InputSchema>): Schema.Schema.Type<typeof InputObject> => {
if (typeof input === "string") return { "*": input }
const result = { ...input }
if (result.terminal !== undefined && result.bash !== undefined) {
delete (result as any).bash
}
return result
}
Comment on lines 297 to 300
function isShell(toolName: string) {
const tool = toolName.toLocaleLowerCase()
return tool === "bash" || tool === "shell"
return tool === "terminal" || tool === "shell"
}
<Show when={!shouldHide()}>
<Switch>
<Match when={display() === "bash"}>
<Match when={display() === "terminal"}>
Comment on lines +465 to 467
if (part.tool !== "terminal") {
return
}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/tui/test/util/transcript.test.ts (1)

170-181: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update all expected values that still use bash.

The fixtures now use terminal, but several expected values retain the old identifier.

  • packages/tui/test/util/transcript.test.ts#L170-L181: expect **Tool: terminal**.
  • packages/tui/test/util/transcript.test.ts#L195-L207: expect **Tool: terminal**.
  • packages/tui/test/util/transcript.test.ts#L220-L231: expect **Tool: terminal**.
  • packages/opencode/test/session/processor.test.ts#L446-L446: expect terminal in the doom-loop assertion.
  • packages/opencode/test/cli/run/stream.transport.test.ts#L713-L713: expect running terminal.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tui/test/util/transcript.test.ts` around lines 170 - 181, Update all
stale expected tool identifiers from bash to terminal: adjust the three
formatPart expectations in packages/tui/test/util/transcript.test.ts at lines
170-181, 195-207, and 220-231; update the doom-loop assertion in
packages/opencode/test/session/processor.test.ts at line 446; and update the
running-tool expectation in
packages/opencode/test/cli/run/stream.transport.test.ts at line 713.
🧹 Nitpick comments (3)
packages/opencode/test/skill/release-v0.8.0-adversarial.test.ts (1)

19-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Rename bashAction to match the permission category.

The helper now evaluates "terminal" but remains named bashAction. Rename it to terminalAction and update its call sites so the test does not retain a stale tool identifier.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/test/skill/release-v0.8.0-adversarial.test.ts` at line 19,
Rename the helper bashAction to terminalAction to match the "terminal"
permission category, and update every call site in the test to use the new name.
packages/opencode/test/session/prompt.test.ts (1)

342-342: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Align hasTerminal with the shell under test.

hasTerminal still checks Bun.which("bash"). If the configured shell is PowerShell or CMD, these guards can skip tests even when the terminal is available. Keep the name hasBash for Bash-only cases, or check the configured shell for cross-platform coverage.

Also applies to: 1485-1485, 1684-1684

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/test/session/prompt.test.ts` at line 342, Update the
terminal availability guards around hasTerminal to match the shell being tested:
retain a Bash-specific name and Bun.which("bash") check for Bash-only cases,
while cross-platform cases must check the configured shell rather than assuming
Bash. Apply the same correction to all corresponding occurrences.
packages/core/test/config/agent.test.ts (1)

84-85: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add regression coverage for legacy permission keys.

These assertions cover only direct terminal rules. Add cases for a legacy bash rule and for both keys, with the explicit terminal rule taking precedence. If equivalent coverage exists elsewhere, reference that test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/test/config/agent.test.ts` around lines 84 - 85, Extend the
permission evaluation tests around buildAgent.permissions with regression cases
for a legacy bash rule and for simultaneous bash and terminal rules. Verify
bash-only behavior is covered, and verify an explicit terminal rule takes
precedence when both keys are present, reusing existing permission fixtures or
assertions where applicable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/opencode/src/acp/tool.ts`:
- Around line 297-299: Update the toLocations() switch to handle the "terminal"
tool name and return the same working-directory ToolCallLocation as the existing
shell/bash handling. Preserve the "bash" case for legacy ACP messages.

In `@packages/opencode/test/altimate/tracing-adversarial-2.test.ts`:
- Line 830: Update the expected tool-name assertion in the tracing adversarial
test to use "terminal, read", matching the fixture’s tool value of "terminal"
and the existing "read" entry.

In `@packages/opencode/test/release-validation/session-transcript-941.test.ts`:
- Line 128: Update the session transcript fixture and related assertions to
consistently use "terminal" instead of "bash", including the values near the
referenced lines and the expected transcript checks. Preserve state.title as
"bash" only if it intentionally represents a separate legacy label; otherwise
update it too, and add a dedicated compatibility test if that legacy behavior
must remain.

---

Outside diff comments:
In `@packages/tui/test/util/transcript.test.ts`:
- Around line 170-181: Update all stale expected tool identifiers from bash to
terminal: adjust the three formatPart expectations in
packages/tui/test/util/transcript.test.ts at lines 170-181, 195-207, and
220-231; update the doom-loop assertion in
packages/opencode/test/session/processor.test.ts at line 446; and update the
running-tool expectation in
packages/opencode/test/cli/run/stream.transport.test.ts at line 713.

---

Nitpick comments:
In `@packages/core/test/config/agent.test.ts`:
- Around line 84-85: Extend the permission evaluation tests around
buildAgent.permissions with regression cases for a legacy bash rule and for
simultaneous bash and terminal rules. Verify bash-only behavior is covered, and
verify an explicit terminal rule takes precedence when both keys are present,
reusing existing permission fixtures or assertions where applicable.

In `@packages/opencode/test/session/prompt.test.ts`:
- Line 342: Update the terminal availability guards around hasTerminal to match
the shell being tested: retain a Bash-specific name and Bun.which("bash") check
for Bash-only cases, while cross-platform cases must check the configured shell
rather than assuming Bash. Apply the same correction to all corresponding
occurrences.

In `@packages/opencode/test/skill/release-v0.8.0-adversarial.test.ts`:
- Line 19: Rename the helper bashAction to terminalAction to match the
"terminal" permission category, and update every call site in the test to use
the new name.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e493ffa3-5d08-4851-a668-22b7198973ea

📥 Commits

Reviewing files that changed from the base of the PR and between 03b9459 and 5861452.

📒 Files selected for processing (95)
  • packages/core/src/tool/builtins.ts
  • packages/core/src/tool/terminal.ts
  • packages/core/src/v1/config/permission.ts
  • packages/core/test/config/agent.test.ts
  • packages/core/test/session-runner-tool-registry.test.ts
  • packages/core/test/session-tool-progress.test.ts
  • packages/core/test/tool-terminal.test.ts
  • packages/opencode/specs/v2/api.ts
  • packages/opencode/src/acp/event.ts
  • packages/opencode/src/acp/tool.ts
  • packages/opencode/src/agent/agent.ts
  • packages/opencode/src/altimate/observability/viewer.ts
  • packages/opencode/src/altimate/telemetry/index.ts
  • packages/opencode/src/altimate/tool-source.ts
  • packages/opencode/src/cli/cmd/agent.ts
  • packages/opencode/src/cli/cmd/run.ts
  • packages/opencode/src/cli/cmd/run/demo.ts
  • packages/opencode/src/cli/cmd/run/session-data.ts
  • packages/opencode/src/cli/cmd/run/session-replay.ts
  • packages/opencode/src/cli/cmd/run/tool.ts
  • packages/opencode/src/cli/cmd/skill.ts
  • packages/opencode/src/permission/index.ts
  • packages/opencode/src/permission/next.ts
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/src/tool/registry.ts
  • packages/opencode/src/tool/retrieval.ts
  • packages/opencode/src/tool/shell/id.ts
  • packages/opencode/src/tool/terminal.ts
  • packages/opencode/test/acp/event.test.ts
  • packages/opencode/test/agent/agent.test.ts
  • packages/opencode/test/agent/plan-mode-subagent-bypass.test.ts
  • packages/opencode/test/altimate/carry-forward/agent-safety.test.ts
  • packages/opencode/test/altimate/trace-consumer.test.ts
  • packages/opencode/test/altimate/tracing-adversarial-2.test.ts
  • packages/opencode/test/altimate/tracing-adversarial-final.test.ts
  • packages/opencode/test/altimate/tracing-adversarial-snapshot.test.ts
  • packages/opencode/test/altimate/tracing-adversarial.test.ts
  • packages/opencode/test/altimate/tracing-de-attributes.test.ts
  • packages/opencode/test/altimate/tracing-display-crash.test.ts
  • packages/opencode/test/altimate/tracing-e2e.test.ts
  • packages/opencode/test/altimate/tracing-final-audit.test.ts
  • packages/opencode/test/altimate/tracing-integration.test.ts
  • packages/opencode/test/altimate/tracing-rename-race.test.ts
  • packages/opencode/test/altimate/tracing-thorough.test.ts
  • packages/opencode/test/altimate/tracing.test.ts
  • packages/opencode/test/branding/build-integrity.test.ts
  • packages/opencode/test/cli/run/entry.body.test.ts
  • packages/opencode/test/cli/run/footer.view.test.tsx
  • packages/opencode/test/cli/run/permission.shared.test.ts
  • packages/opencode/test/cli/run/scrollback.surface.test.ts
  • packages/opencode/test/cli/run/session-data.test.ts
  • packages/opencode/test/cli/run/session-replay.test.ts
  • packages/opencode/test/cli/run/stream.transport.test.ts
  • packages/opencode/test/cli/run/subagent-data.test.ts
  • packages/opencode/test/config/config.test.ts
  • packages/opencode/test/file/security-e2e.test.ts
  • packages/opencode/test/permission-task.test.ts
  • packages/opencode/test/permission-yolo.test.ts
  • packages/opencode/test/permission/next.test.ts
  • packages/opencode/test/provider/transform.test.ts
  • packages/opencode/test/release-validation/question-937-codex.test.ts
  • packages/opencode/test/release-validation/question-937.test.ts
  • packages/opencode/test/release-validation/session-transcript-941.test.ts
  • packages/opencode/test/session/compaction-mask.test.ts
  • packages/opencode/test/session/compaction.test.ts
  • packages/opencode/test/session/llm-native.test.ts
  • packages/opencode/test/session/llm.test.ts
  • packages/opencode/test/session/message-v2.test.ts
  • packages/opencode/test/session/observation-mask.test.ts
  • packages/opencode/test/session/processor.test.ts
  • packages/opencode/test/session/prompt.test.ts
  • packages/opencode/test/session/regression.test.ts
  • packages/opencode/test/session/revert-compact.test.ts
  • packages/opencode/test/session/schema-decoding.test.ts
  • packages/opencode/test/skill/release-v0.6.0-adversarial.test.ts
  • packages/opencode/test/skill/release-v0.8.0-adversarial.test.ts
  • packages/opencode/test/skill/release-v0.8.6-adversarial.test.ts
  • packages/opencode/test/telemetry/telemetry.test.ts
  • packages/opencode/test/tool/parameters.test.ts
  • packages/opencode/test/tool/retrieval.test.ts
  • packages/opencode/test/tool/shell.test.ts
  • packages/opencode/test/tool/task.test.ts
  • packages/opencode/test/tool/terminal.test.ts
  • packages/opencode/test/tui-journeys/README.md
  • packages/opencode/test/tui-journeys/journeys.test.ts
  • packages/opencode/test/upstream/adversarial/upi-tool-api.test.ts
  • packages/opencode/test/upstream/altimate-features.test.ts
  • packages/opencode/test/upstream/v140-merge-fuzz.test.ts
  • packages/opencode/test/upstream/v140-permission-deadlock.test.ts
  • packages/opencode/test/v2/session-message-updater.test.ts
  • packages/tui/src/feature-plugins/home/tips-view.tsx
  • packages/tui/src/routes/session/index.tsx
  • packages/tui/test/cli/tui/data.test.tsx
  • packages/tui/test/cli/tui/inline-tool-wrap-snapshot.test.tsx
  • packages/tui/test/util/transcript.test.ts

Comment on lines 297 to +299
function isShell(toolName: string) {
const tool = toolName.toLocaleLowerCase()
return tool === "bash" || tool === "shell"
return tool === "terminal" || tool === "shell"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add terminal to toLocations().

isShell() now recognizes "terminal", but toLocations() still handles "bash" and "shell". A terminal call therefore reaches the default branch and returns no ToolCallLocation. ACP clients lose the terminal working-directory location.

Add case "terminal": to the toLocations() switch. Keep case "bash": if legacy ACP messages must remain supported.

Proposed fix
 switch (tool) {
+  case "terminal":
   case "bash":
   case "shell": {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/src/acp/tool.ts` around lines 297 - 299, Update the
toLocations() switch to handle the "terminal" tool name and return the same
working-directory ToolCallLocation as the existing shell/bash handling. Preserve
the "bash" case for legacy ACP messages.

tracer.logStepStart({ id: "1" })
tracer.logToolCall({
tool: "bash",
tool: "terminal",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Update the stale tool-name expectation.

Line 830 now records tool: "terminal", but the test still expects "bash, read". The fixture and assertion no longer describe the same tool list. Change the expected value to "terminal, read".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/test/altimate/tracing-adversarial-2.test.ts` at line 830,
Update the expected tool-name assertion in the tracing adversarial test to use
"terminal, read", matching the fixture’s tool value of "terminal" and the
existing "read" entry.

type: "tool",
callID: "call_completed",
tool: "bash",
tool: "terminal",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Update the transcript fixture and assertions to terminal.

Line 128 now uses tool: "terminal", but Line 133 and Lines 175 and 190 still use "bash". This leaves the fixture and expected transcript inconsistent with the rename. Update those values to terminal, unless state.title is intentionally a separate legacy label. In that case, add a separate compatibility test instead of keeping the main transcript test on bash.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/test/release-validation/session-transcript-941.test.ts` at
line 128, Update the session transcript fixture and related assertions to
consistently use "terminal" instead of "bash", including the values near the
referenced lines and the expected transcript checks. Preserve state.title as
"bash" only if it intentionally represents a separate legacy label; otherwise
update it too, and add a dedicated compatibility test if that legacy behavior
must remain.

@kilo-code-bot

kilo-code-bot Bot commented Aug 5, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

This PR is a large (~95-file), mostly mechanical bashterminal rename. The tool ID, exports, UI labels, permission config, telemetry, and trace handling are renamed consistently, and the backward-compat layer (permission/index.ts, permission/next.ts) correctly remaps legacy bashterminal (with terminal winning when both are present). Two rename gaps remain that other reviews did not surface.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
packages/opencode/src/acp/tool.ts 42, 77 toToolKind() and toLocations() switch on case "bash" / case "shell" only. The renamed "terminal" tool now falls through to default, so ACP clients receive kind: "other" (previously "execute") and the shell working-directory locations attachment is dropped. isShell() (line ~299) was updated to "terminal" but these two switch statements were missed — add a case "terminal": (keep case "bash": for legacy ACP clients). Lines are outside this PR's diff hunks, so noted here rather than as inline comments.

SUGGESTION

File Line Issue
packages/opencode/src/cli/cmd/run/demo.ts 28 The KINDS array still lists "bash", but emitFmt() now dispatches on kind === "terminal" (line 1044). As a result /fmt bash is advertised in the help text (line 1110) and passes validation, yet emitFmt returns false and emits nothing — a dead branch. Rename the entry to "terminal".
Files Reviewed (95 files — rename refactor)

Substantive source files reviewed:

  • packages/opencode/src/tool/terminal.ts, packages/opencode/src/tool/shell/id.ts, packages/opencode/src/tool/shell.ts
  • packages/opencode/src/tool/registry.ts, packages/opencode/src/tool/retrieval.ts, packages/opencode/src/tool/shell/prompt.ts
  • packages/opencode/src/permission/index.ts, packages/opencode/src/permission/next.ts
  • packages/opencode/src/acp/tool.ts, packages/opencode/src/acp/event.ts
  • packages/opencode/src/agent/agent.ts
  • packages/opencode/src/cli/cmd/run/{session-data,session-replay,run,tool,demo,skill}.ts
  • packages/opencode/src/altimate/{telemetry/index,observability/viewer,tool-source}.ts
  • packages/core/src/tool/{terminal,builtins}.ts, packages/core/src/v1/config/permission.ts
  • Test files spot-checked for rename consistency.

Notes:

  • The legacy bash persisted-session/trace handling gaps in session-data.ts, tui/.../session/index.tsx, and acp/tool.ts isShell were already raised by Copilot and are not duplicated here.
  • shell/id.ts Kind default rename (bashterminal) is functionally harmless: the value is only ever compared to "cmd" (shell.ts:401–404).
  • No leftover tool/bash imports remain, and no parser depends on the old <bash_metadata> tag.

Fix these issues in Kilo Cloud


Reviewed by glm-5.2 · Input: 149.4K · Output: 44.4K · Cached: 2.6M

Review guidance: REVIEW.md from base branch main

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

40 issues found across 95 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/core/test/session-runner-tool-registry.test.ts">

<violation number="1" location="packages/core/test/session-runner-tool-registry.test.ts:69">
P1: The test registers tools via `service.register({ question: make(), bash: make(), edit: ... })`, and registry names are the registration keys (materialize calls `definition(name, tool)` with `name` from the key), so the fake shell tool materializes as "bash", not "terminal". The renamed expectation `["terminal", "edit", "write", "apply_patch"]` (and the later `["question", "terminal"]`) will now fail because the registration key `bash:` was never renamed. Rename the register key to `terminal:` to match, or the test breaks.</violation>
</file>

<file name="packages/opencode/test/cli/run/stream.transport.test.ts">

<violation number="1" location="packages/opencode/test/cli/run/stream.transport.test.ts:713">
P1: This test will fail: the runningTool input was renamed to "terminal", but the assertion still expects status "running bash". Since toolStatus() builds the label as `running ${part.tool}`, the actual status is now "running terminal" and the expect.objectContaining won't match. Update the expected status to "running terminal".</violation>
</file>

<file name="packages/opencode/test/session/compaction-mask.test.ts">

<violation number="1" location="packages/opencode/test/session/compaction-mask.test.ts:51">
P1: The test inputs were renamed to "terminal" but the assertions still check for "bash(" / "bash()" / "bash([unserializable])", and createObservationMask echoes part.tool verbatim. Update those assertions to "terminal(" etc. so the tests pass and mirror the rename.</violation>
</file>

<file name="packages/opencode/test/session/processor.test.ts">

<violation number="1" location="packages/opencode/test/session/processor.test.ts:253">
P2: The 'shell tools' categorization test still asserts categorizeToolName("bash","standard") === "file", but bash was removed from FILE_TOOLS in this rename, so it now returns "standard" and the test fails. Update it to use "terminal" (or drop the stale case).</violation>

<violation number="2" location="packages/opencode/test/session/processor.test.ts:446">
P1: The doom_loop_detected test sets tool_name to "terminal" but still asserts it equals "bash", so this test now always fails. Update line 452 to expect "terminal".</violation>
</file>

<file name="packages/tui/test/util/transcript.test.ts">

<violation number="1" location="packages/tui/test/util/transcript.test.ts:170">
P1: The tool part inputs in these four transcript tests were renamed from 'bash' to 'terminal', but the assertions in the same describe block were not updated and still expect `**Tool: bash**` (lines 181, 207, 231). Since `formatPart` in `src/util/transcript.ts` builds the header directly from `part.tool` with no display-name mapping, the output is now `**Tool: terminal**`, so these assertions will fail. Update the expected labels to `terminal` so the tests pass and continue to verify the renamed tool.</violation>
</file>

<file name="packages/opencode/test/skill/release-v0.6.0-adversarial.test.ts">

<violation number="1" location="packages/opencode/test/skill/release-v0.6.0-adversarial.test.ts:196">
P1: This test now fails: the input is still `msg("bash")`, which produces a tool-call whose `toolName` is `"bash"`, and `LLM.toolNamesFromMessages` returns that name verbatim (`new Set(["bash"])`), not `"terminal"`. The bash->terminal rename updated the expected value but missed the argument passed to `msg(...)`, so the assertion compares `["bash"]` against `["terminal"]`. Change the input to `msg("terminal")` so the tool name and the expected set match.</violation>

<violation number="2" location="packages/opencode/test/skill/release-v0.6.0-adversarial.test.ts:270">
P1: This test also fails after the rename: the messages still come from `msg("bash")`, so `toolNamesFromMessages` returns `new Set(["bash", "read"])`, while the assertion now expects `new Set(["terminal", "read"])`. Update the `msg("bash")` inputs to `msg("terminal")` (in the `messages` array above this line) so the input tool name matches the expected set.</violation>
</file>

<file name="packages/opencode/src/tool/terminal.ts">

<violation number="1" location="packages/opencode/src/tool/terminal.ts:56">
P2: On Windows, the renamed terminal still presents the model with Bash-specific instructions, which can lead it to generate Bash syntax for the PowerShell/CMD shell selected by `Shell.acceptable()`. Use a shell-neutral description (or generate the instructions from the selected shell) instead of continuing to load `bash.txt`.</violation>

<violation number="2" location="packages/opencode/src/tool/terminal.ts:311">
P3: Timed-out terminal calls still report `bash tool terminated...` inside the new `<terminal_metadata>` wrapper, leaving the renamed tool visibly inconsistent. Rename that timeout message to `terminal tool ...` as part of the metadata rename.</violation>
</file>

<file name="packages/opencode/test/upstream/adversarial/upi-tool-api.test.ts">

<violation number="1" location="packages/opencode/test/upstream/adversarial/upi-tool-api.test.ts:153">
P2: The renamed ctx.ask permission ("terminal") no longer matches the test's assertion, which still expects an event containing "ask:bash:echo *:echo *". Since the ask callback serializes input.permission into the event string, this test will now fail; update the expected event to "ask:terminal:echo *:echo *".</violation>
</file>

<file name="packages/core/test/config/agent.test.ts">

<violation number="1" location="packages/core/test/config/agent.test.ts:84">
P1: The renamed assertion calls evaluate("terminal", ...) but the permission rules under test still carry action "bash", which PermissionV2.evaluate matches by exact wildcard with no bash→terminal remap. "git status" therefore never matches the "bash" allow rule and the first assertion expecting "allow" will fail with "ask". Update the permission rules (and the expected buildAgent.permissions/toMatchObject lists) to use action "terminal", or keep evaluating with "bash" — the test is currently internally inconsistent.</violation>
</file>

<file name="packages/opencode/src/tool/shell/id.ts">

<violation number="1" location="packages/opencode/src/tool/shell/id.ts:16">
P1: Existing integrations that invoke the legacy `bash` tool ID will no longer resolve because this changes the registered ID to `terminal` without an alias; the compatibility code only covers config permission keys. Preserve a `bash` alias/normalization for tool calls, or remove the compatibility claim and explicitly accept this breaking change.</violation>

<violation number="2" location="packages/opencode/src/tool/shell/id.ts:16">
P2: Persisted permission rules keyed by `bash` stop applying to terminal requests after this ID change, so users can unexpectedly receive prompts or lose stored denials. Normalize stored rules on load (with `terminal` taking precedence) or migrate the persisted permission rows alongside the config mapping.</violation>
</file>

<file name="packages/core/test/tool-terminal.test.ts">

<violation number="1" location="packages/core/test/tool-terminal.test.ts:284">
P2: The rename left `denyAction = "bash"` stale, so the deny branch never matches the tool's new `"terminal"` action and the tool executes, failing `expect(runs).toEqual([])` in the 'does not execute after external-directory or bash denial' test. Change it to `denyAction = "terminal"` so the renamed test still verifies the denial path.</violation>
</file>

<file name="packages/opencode/test/altimate/tracing-final-audit.test.ts">

<violation number="1" location="packages/opencode/test/altimate/tracing-final-audit.test.ts:190">
P2: The tool name was renamed to "terminal" here but the assertion 15 lines below still expects the generation input to contain "[bash]". Since tracing.ts (line 791) builds the input as `[${tool}] ...`, the input will be "[terminal] ..." and this `toContain("[bash]")` assertion will fail. Update it to "[terminal]".</violation>
</file>

<file name="packages/opencode/test/altimate/tracing-adversarial-snapshot.test.ts">

<violation number="1" location="packages/opencode/test/altimate/tracing-adversarial-snapshot.test.ts:287">
P2: The first tool call in this test was renamed to "terminal", but the span lookup still searches for `s.name === "bash"` (line 600). Since `logToolCall` sets the span name to the tool value, the find returns undefined and `tool.attributes!.normal` throws, so this test now fails. Update the lookup to `s.name === "terminal"`.</violation>
</file>

<file name="packages/opencode/test/altimate/tracing-adversarial-2.test.ts">

<violation number="1" location="packages/opencode/test/altimate/tracing-adversarial-2.test.ts:54">
P2: The renamed `tool: "terminal"` now makes the generation output `"[tool calls: terminal, read]"`, but the assertion at line 843 still expects `"[tool calls: bash, read]"`, so this test fails. Update the expected string to match the renamed tool.</violation>
</file>

<file name="packages/opencode/test/tool/parameters.test.ts">

<violation number="1" location="packages/opencode/test/tool/parameters.test.ts:77">
P2: Renaming the test from `bash` to `terminal` changes the snapshot key, but the snapshot file still only records `... wire shape) bash 1` and has no `terminal` entry. `bun test` in CI will fail: the new `terminal` snapshot is unmatched and the old `bash` snapshot is obsolete. Regenerate the snapshot (or rename the key in parameters.test.ts.snap) to `tool parameters JSON Schema (wire shape) terminal 1`.</violation>
</file>

<file name="packages/opencode/test/altimate/tracing-integration.test.ts">

<violation number="1" location="packages/opencode/test/altimate/tracing-integration.test.ts:110">
P2: The tool-call rename to "terminal" wasn't propagated to the span lookup: the roundtrip test still queries traceFile.spans.find((s) => s.name === "bash"), which now returns undefined and makes the subsequent dbtTool.attributes! throw, failing the test. Update the assertion to s.name === "terminal".</violation>
</file>

<file name="packages/opencode/src/cli/cmd/agent.ts">

<violation number="1" location="packages/opencode/src/cli/cmd/agent.ts:23">
P2: Existing `agent create --tools bash` invocations now generate agents with terminal access denied. Mapping the legacy `bash` value to `terminal` in `LEGACY_TOOL_PERMISSION` would preserve the CLI contract just as the existing `write` and `apply_patch` mappings do.</violation>
</file>

<file name="packages/opencode/test/altimate/tracing.test.ts">

<violation number="1" location="packages/opencode/test/altimate/tracing.test.ts:316">
P2: This test logs tool "terminal" but still asserts the loop records tool "bash" (lines 1009-1011). Loop detection stores the exact tool name passed in, so this now fails in CI. Update those assertions to "terminal".</violation>
</file>

<file name="packages/opencode/test/cli/run/session-replay.test.ts">

<violation number="1" location="packages/opencode/test/cli/run/session-replay.test.ts:172">
P2: The test "keeps the footer in a running state for resumed active tools" now builds a tool part with tool "terminal", but the assertion at line 368 still expects status "running bash". Since toolStatus() derives the status from part.tool (session-data.ts:401), replaying this message produces "running terminal", so the assertion is stale and the test will fail. Update the expectation to "running terminal".</violation>
</file>

<file name="packages/opencode/src/acp/tool.ts">

<violation number="1" location="packages/opencode/src/acp/tool.ts:299">
P2: This rename only updated isShell to detect "terminal", but the sibling functions in the same file — toToolKind and toLocations — still switch on "bash"/"shell". Since the tool ID is now "terminal" (Tool.define("terminal")), ACP tool calls for the terminal tool will be classified as kind "other" instead of "execute" and will lose their shell working-directory location. Add case "terminal" to both switches for consistency with the rename.</violation>
</file>

<file name="packages/opencode/test/tool/terminal.test.ts">

<violation number="1" location="packages/opencode/test/tool/terminal.test.ts:74">
P2: The permission-based tests in this file will fail after the rename. The tool now requests permission `"terminal"` (changed in `packages/opencode/src/tool/terminal.ts`), but the assertions in the `tool.bash permissions` block were not updated and still look for `"bash"` — e.g. `expect(requests[0].permission).toBe("bash")` (lines 108 and 132) and `requests.find((r) => r.permission === "bash")` followed by `expect(bashReq).toBeDefined()` (lines 304 and 322). Since no request with permission `"bash"` is emitted anymore, these expectations are now wrong and the tests will throw. The rename updated the tool import/usage but missed these permission assertions, which contradicts the PR's claim that the full suite passes. Please update the assertions to use `"terminal"` alongside the tool rename.</violation>
</file>

<file name="packages/opencode/test/release-validation/session-transcript-941.test.ts">

<violation number="1" location="packages/opencode/test/release-validation/session-transcript-941.test.ts:128">
P2: The tool part was renamed to "terminal" but the assertions still expect `**Tool: bash**`. `formatTranscript` renders the header from `part.tool`, so now it emits `**Tool: terminal**` and both `expect(...).toContain("**Tool: bash**")` assertions will fail. Update those assertions to `"**Tool: terminal**"`.</violation>
</file>

<file name="packages/opencode/src/cli/cmd/run/tool.ts">

<violation number="1" location="packages/opencode/src/cli/cmd/run/tool.ts:1046">
P2: Replaying sessions created before this rename now loses the bash tool rule: historical `bash` parts fall back to the generic formatter and emit a final completion that the previous rule intentionally suppressed. Keeping a legacy `bash` alias or normalizing `bash` to `terminal` in `rule()` would preserve existing session output.</violation>
</file>

<file name="packages/core/src/v1/config/permission.ts">

<violation number="1" location="packages/core/src/v1/config/permission.ts:44">
P2: When a user's config defines only the legacy `bash` permission key (the common backward-compat case, with no `terminal` key), the decoded `config.permission` object is returned unchanged with the `bash` key still present. The two updated config tests (''config parser preserves permission order...'' and ''agent markdown permission config preserves user key order'') both use only `bash` and assert the parsed keys are `["terminal", "*", "edit"]`, but since `normalizeInput` only deletes `bash` when `terminal` is *also* set, the object keeps `bash` and the tests fail. The runtime ruleset path in `Permission.fromConfig` does remap `bash`→`terminal`, so enforcement is correct, but the exposed `config.permission` stays inconsistent with the rename. Rename a lone `bash` key to `terminal` (and drop it only when `terminal` is also defined).</violation>
</file>

<file name="packages/opencode/src/cli/cmd/run/demo.ts">

<violation number="1" location="packages/opencode/src/cli/cmd/run/demo.ts:38">
P2: The built-in `/permission bash` example is now rejected because `permissionKind` accepts only the renamed `terminal` entry, so users following the displayed example get the picker error instead of a permission request; update the example to `/permission terminal`.</violation>

<violation number="2" location="packages/opencode/src/cli/cmd/run/demo.ts:797">
P3: The demo mode's bash→terminal rename is incomplete: the `/fmt` dispatcher was updated to match `kind === "terminal"`, but the `KINDS` array (and the `/permission bash` footer example) still list `bash`. As a result the documented `/fmt bash` slash command no longer produces any output (it silently returns false) while `/fmt terminal` works, and `/permission bash` points at a kind that `permissionKind`/`PERMISSIONS` no longer accept. Please also update the `KINDS` array entry and the footer examples to `terminal` so the demo help and the dispatcher stay in sync.</violation>
</file>

<file name="packages/opencode/test/session/llm-native.test.ts">

<violation number="1" location="packages/opencode/test/session/llm-native.test.ts:246">
P2: The renamed expectations (name: "terminal") don't match the still-`bash`-keyed tools map: native-request.ts derives each tool's name from the map key, so this tools block produces `name: "bash"` both in request.tools and as the definition for the tool-call, failing the assertion and breaking the message/definition name alignment. Rename the `tools` record key to `terminal` so the definition name matches the renamed tool-call and assertions.</violation>
</file>

<file name="packages/opencode/test/altimate/carry-forward/agent-safety.test.ts">

<violation number="1" location="packages/opencode/test/altimate/carry-forward/agent-safety.test.ts:89">
P2: The rename updated the bare Permission.evaluate(...,"terminal") calls but left the evalPerm(...,"bash") assertions in the same blocks stale. Since defaults/safetyDenials now register rules only under "terminal" and there is no "bash" rule anymore, evalPerm(builder,"bash") falls through to the default `<code>*: "allow"` catch-all and returns "allow" instead of the asserted "ask", so this guard test no longer asserts the intended behavior (and the first-block assertion fails). Update those helper calls to "terminal" (expectations stay "ask"/"allow") so the renamed safety rules are what actually get checked.</violation>
</file>

<file name="packages/opencode/src/cli/cmd/run.ts">

<violation number="1" location="packages/opencode/src/cli/cmd/run.ts:569">
P2: When `run --attach` talks to a pre-rename server, completed shell calls now fall through to the generic fallback, so users see the command input but not its output. Keeping `bash` as a legacy alias here (or normalizing incoming parts) would preserve cross-version rendering while using `terminal` for new events.</violation>
</file>

<file name="packages/opencode/test/acp/event.test.ts">

<violation number="1" location="packages/opencode/test/acp/event.test.ts:238">
P2: The rename was applied inconsistently within this test file: runningTool/errorTool now emit `tool: "terminal"`, while completedTool still defaults to `tool: "bash"` and all fixtures still set `title: "bash"`. Align completedTool's default and the title labels so the fixtures match production's `terminal` naming and stay consistent with the other helpers.</violation>
</file>

<file name="packages/tui/src/routes/session/index.tsx">

<violation number="1" location="packages/tui/src/routes/session/index.tsx:2652">
P2: Existing/peristed tool parts in session history still carry tool id "bash"; after this rename toolDisplay() returns "generic" for them, so resuming an old session renders those bash calls as GenericTool instead of the Shell block. The PR only added a bash→terminal compatibility layer for config permission keys, not for stored messages. Recommend keeping "bash" in toolDisplays (or mapping it to Shell) so legacy history still renders correctly.</violation>
</file>

<file name="packages/opencode/test/permission-yolo.test.ts">

<violation number="1" location="packages/opencode/test/permission-yolo.test.ts:250">
P3: Missed rename: the ruleset in the "DeniedError contains relevant ruleset info" test now uses permission "terminal", but this filter still matches "bash", so the DeniedError is constructed with an empty ruleset and carries no relevant rule info. The test passes only because it asserts the message contains "deny", silently defeating its intent. Update the filter to "terminal".</violation>
</file>

<file name="packages/opencode/src/altimate/observability/viewer.ts">

<violation number="1" location="packages/opencode/src/altimate/observability/viewer.ts:598">
P2: The viewer now only recognizes shell tools whose span name is `terminal` (or contains `shell`), which drops the legacy `bash` name it previously matched. Existing saved trace files recorded before this rename store shell-tool spans as `bash`, so after this change shell commands in those historical traces will silently stop being extracted: they will no longer appear in the shell-command list, dbt detection, command-outcome summaries, or the 'Ran N shell command(s)' line in the markdown summary. This is the same backward-compat concern the PR addressed for config permissions with a `bash`->`terminal` remap, so consider also accepting the legacy `bash` name when classifying spans here (e.g. `lname === 'terminal' || lname === 'bash' || lname.indexOf('shell') >= 0` in all three branches), so historical traces keep rendering correctly.</violation>
</file>

<file name="packages/opencode/test/permission/next.test.ts">

<violation number="1" location="packages/opencode/test/permission/next.test.ts:142">
P3: The backward-compat precedence behavior added in this PR (when both `bash` and `terminal` are configured, `terminal` wins) is not covered by any test. The renames here keep the bash-input cases but never assert the documented both-keys-defined case or a plain `terminal` input key, so a regression in that new precedence logic would pass CI. Consider adding a fromConfig test that supplies both keys and expects only the terminal rule (plus a `terminal`-only input test).</violation>
</file>

<file name="packages/opencode/src/cli/cmd/run/session-data.ts">

<violation number="1" location="packages/opencode/src/cli/cmd/run/session-data.ts:928">
P2: When a session saved before this rename (whose tool parts still carry `tool: "bash"`) is replayed, `reduceSessionData` no longer treats those parts as shell: echo-stripping and the direct-shell source claim are skipped. This conflicts with `isShellSyntheticAssistant` in session-replay.ts, which — in the same batch — explicitly kept matching `"bash"` for those very transcripts, so the same old session is classified as shell in one place and not shell in another. Consider keeping the legacy `"bash"` name in these runtime matches (as the config backend-compat layer and session-replay already do) so replayed legacy sessions behave consistently.</violation>
</file>

<file name="packages/opencode/src/session/prompt.ts">

<violation number="1" location="packages/opencode/src/session/prompt.ts:2664">
P3: This fixture now records `tool: "terminal"`, so any expectation that still checks for `bash` in the tool list is stale. Updating the expected string to `terminal, read` keeps the test aligned with the renamed tool IDs.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic


expect(yield* names([{ action: "question", resource: "*", effect: "deny" }])).toEqual([
"bash",
expect(yield* names([{ action: "question", resource: "*", effect: "deny" }])).toEqual(["terminal",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The test registers tools via service.register({ question: make(), bash: make(), edit: ... }), and registry names are the registration keys (materialize calls definition(name, tool) with name from the key), so the fake shell tool materializes as "bash", not "terminal". The renamed expectation ["terminal", "edit", "write", "apply_patch"] (and the later ["question", "terminal"]) will now fail because the registration key bash: was never renamed. Rename the register key to terminal: to match, or the test breaks.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/test/session-runner-tool-registry.test.ts, line 69:

<comment>The test registers tools via `service.register({ question: make(), bash: make(), edit: ... })`, and registry names are the registration keys (materialize calls `definition(name, tool)` with `name` from the key), so the fake shell tool materializes as "bash", not "terminal". The renamed expectation `["terminal", "edit", "write", "apply_patch"]` (and the later `["question", "terminal"]`) will now fail because the registration key `bash:` was never renamed. Rename the register key to `terminal:` to match, or the test breaks.</comment>

<file context>
@@ -66,8 +66,7 @@ describe("ToolRegistry", () => {
 
-      expect(yield* names([{ action: "question", resource: "*", effect: "deny" }])).toEqual([
-        "bash",
+      expect(yield* names([{ action: "question", resource: "*", effect: "deny" }])).toEqual(["terminal",
         "edit",
         "write",
</file context>

id: "bash-1",
callID: "call-1",
tool: "bash",
tool: "terminal",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This test will fail: the runningTool input was renamed to "terminal", but the assertion still expects status "running bash". Since toolStatus() builds the label as running ${part.tool}, the actual status is now "running terminal" and the expect.objectContaining won't match. Update the expected status to "running terminal".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/cli/run/stream.transport.test.ts, line 713:

<comment>This test will fail: the runningTool input was renamed to "terminal", but the assertion still expects status "running bash". Since toolStatus() builds the label as `running ${part.tool}`, the actual status is now "running terminal" and the expect.objectContaining won't match. Update the expected status to "running terminal".</comment>

<file context>
@@ -710,7 +710,7 @@ describe("run stream transport", () => {
                       id: "bash-1",
                       callID: "call-1",
-                      tool: "bash",
+                      tool: "terminal",
                       body: {
                         command: "pwd",
</file context>

test("includes tool name, args, line count, byte size, and fingerprint for completed part", () => {
const part = makeCompletedPart({
tool: "bash",
tool: "terminal",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The test inputs were renamed to "terminal" but the assertions still check for "bash(" / "bash()" / "bash([unserializable])", and createObservationMask echoes part.tool verbatim. Update those assertions to "terminal(" etc. so the tests pass and mirror the rename.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/session/compaction-mask.test.ts, line 51:

<comment>The test inputs were renamed to "terminal" but the assertions still check for "bash(" / "bash()" / "bash([unserializable])", and createObservationMask echoes part.tool verbatim. Update those assertions to "terminal(" etc. so the tests pass and mirror the rename.</comment>

<file context>
@@ -48,7 +48,7 @@ function makePendingPart(overrides?: { tool?: string }): MessageV2.ToolPart {
   test("includes tool name, args, line count, byte size, and fingerprint for completed part", () => {
     const part = makeCompletedPart({
-      tool: "bash",
+      tool: "terminal",
       input: { command: "git status" },
       output: "On branch main\nnothing to commit, working tree clean\n",
</file context>

timestamp: Date.now(),
session_id: "sess-1",
tool_name: "bash",
tool_name: "terminal",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The doom_loop_detected test sets tool_name to "terminal" but still asserts it equals "bash", so this test now always fails. Update line 452 to expect "terminal".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/session/processor.test.ts, line 446:

<comment>The doom_loop_detected test sets tool_name to "terminal" but still asserts it equals "bash", so this test now always fails. Update line 452 to expect "terminal".</comment>

<file context>
@@ -443,7 +443,7 @@ describe("doom loop detection telemetry", () => {
       timestamp: Date.now(),
       session_id: "sess-1",
-      tool_name: "bash",
+      tool_name: "terminal",
       repeat_count: DOOM_LOOP_THRESHOLD,
     }
</file context>

type: "tool",
callID: "call_1",
tool: "bash",
tool: "terminal",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The tool part inputs in these four transcript tests were renamed from 'bash' to 'terminal', but the assertions in the same describe block were not updated and still expect **Tool: bash** (lines 181, 207, 231). Since formatPart in src/util/transcript.ts builds the header directly from part.tool with no display-name mapping, the output is now **Tool: terminal**, so these assertions will fail. Update the expected labels to terminal so the tests pass and continue to verify the renamed tool.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/tui/test/util/transcript.test.ts, line 170:

<comment>The tool part inputs in these four transcript tests were renamed from 'bash' to 'terminal', but the assertions in the same describe block were not updated and still expect `**Tool: bash**` (lines 181, 207, 231). Since `formatPart` in `src/util/transcript.ts` builds the header directly from `part.tool` with no display-name mapping, the output is now `**Tool: terminal**`, so these assertions will fail. Update the expected labels to `terminal` so the tests pass and continue to verify the renamed tool.</comment>

<file context>
@@ -167,7 +167,7 @@ describe("transcript", () => {
         type: "tool",
         callID: "call_1",
-        tool: "bash",
+        tool: "terminal",
         state: {
           status: "completed",
</file context>


if (resultMetadata.length > 0) {
output += "\n\n<bash_metadata>\n" + resultMetadata.join("\n") + "\n</bash_metadata>"
output += "\n\n<terminal_metadata>\n" + resultMetadata.join("\n") + "\n</terminal_metadata>"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Timed-out terminal calls still report bash tool terminated... inside the new <terminal_metadata> wrapper, leaving the renamed tool visibly inconsistent. Rename that timeout message to terminal tool ... as part of the metadata rename.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/tool/terminal.ts, line 311:

<comment>Timed-out terminal calls still report `bash tool terminated...` inside the new `<terminal_metadata>` wrapper, leaving the renamed tool visibly inconsistent. Rename that timeout message to `terminal tool ...` as part of the metadata rename.</comment>

<file context>
@@ -308,7 +308,7 @@ export const BashTool = Tool.define("bash", async () => {
 
       if (resultMetadata.length > 0) {
-        output += "\n\n<bash_metadata>\n" + resultMetadata.join("\n") + "\n</bash_metadata>"
+        output += "\n\n<terminal_metadata>\n" + resultMetadata.join("\n") + "\n</terminal_metadata>"
       }
 
</file context>

try {
// Simulate what ask() does when it encounters deny
const result = PermissionNext.evaluate("bash", "DROP TABLE users", rules)
const result = PermissionNext.evaluate("terminal", "DROP TABLE users", rules)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Missed rename: the ruleset in the "DeniedError contains relevant ruleset info" test now uses permission "terminal", but this filter still matches "bash", so the DeniedError is constructed with an empty ruleset and carries no relevant rule info. The test passes only because it asserts the message contains "deny", silently defeating its intent. Update the filter to "terminal".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/permission-yolo.test.ts, line 250:

<comment>Missed rename: the ruleset in the "DeniedError contains relevant ruleset info" test now uses permission "terminal", but this filter still matches "bash", so the DeniedError is constructed with an empty ruleset and carries no relevant rule info. The test passes only because it asserts the message contains "deny", silently defeating its intent. Update the filter to "terminal".</comment>

<file context>
@@ -206,48 +206,48 @@ describe("yolo mode: permission evaluation is unchanged", () => {
     try {
       // Simulate what ask() does when it encounters deny
-      const result = PermissionNext.evaluate("bash", "DROP TABLE users", rules)
+      const result = PermissionNext.evaluate("terminal", "DROP TABLE users", rules)
       if (result.action === "deny") {
         throw new PermissionNext.DeniedError(rules.filter((r) => r.permission === "bash"))
</file context>


expect(wildcardFirst.map((r) => r.permission)).toEqual(["*", "bash"])
expect(specificFirst.map((r) => r.permission)).toEqual(["bash", "*"])
expect(wildcardFirst.map((r) => r.permission)).toEqual(["*", "terminal"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The backward-compat precedence behavior added in this PR (when both bash and terminal are configured, terminal wins) is not covered by any test. The renames here keep the bash-input cases but never assert the documented both-keys-defined case or a plain terminal input key, so a regression in that new precedence logic would pass CI. Consider adding a fromConfig test that supplies both keys and expects only the terminal rule (plus a terminal-only input test).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/permission/next.test.ts, line 142:

<comment>The backward-compat precedence behavior added in this PR (when both `bash` and `terminal` are configured, `terminal` wins) is not covered by any test. The renames here keep the bash-input cases but never assert the documented both-keys-defined case or a plain `terminal` input key, so a regression in that new precedence logic would pass CI. Consider adding a fromConfig test that supplies both keys and expects only the terminal rule (plus a `terminal`-only input test).</comment>

<file context>
@@ -139,17 +139,17 @@ test("fromConfig - preserves top-level config key order", () => {
 
-  expect(wildcardFirst.map((r) => r.permission)).toEqual(["*", "bash"])
-  expect(specificFirst.map((r) => r.permission)).toEqual(["bash", "*"])
+  expect(wildcardFirst.map((r) => r.permission)).toEqual(["*", "terminal"])
+  expect(specificFirst.map((r) => r.permission)).toEqual(["terminal", "*"])
 
</file context>

messageID: msg.id,
sessionID: input.sessionID,
tool: "bash",
tool: "terminal",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This fixture now records tool: "terminal", so any expectation that still checks for bash in the tool list is stale. Updating the expected string to terminal, read keeps the test aligned with the renamed tool IDs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/session/prompt.ts, line 2664:

<comment>This fixture now records `tool: "terminal"`, so any expectation that still checks for `bash` in the tool list is stale. Updating the expected string to `terminal, read` keeps the test aligned with the renamed tool IDs.</comment>

<file context>
@@ -2661,7 +2661,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
       messageID: msg.id,
       sessionID: input.sessionID,
-      tool: "bash",
+      tool: "terminal",
       callID: ulid(),
       state: {
</file context>

const file = path.join(root, "src", "demo-format.ts")

if (kind === "bash") {
if (kind === "terminal") {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The demo mode's bash→terminal rename is incomplete: the /fmt dispatcher was updated to match kind === "terminal", but the KINDS array (and the /permission bash footer example) still list bash. As a result the documented /fmt bash slash command no longer produces any output (it silently returns false) while /fmt terminal works, and /permission bash points at a kind that permissionKind/PERMISSIONS no longer accept. Please also update the KINDS array entry and the footer examples to terminal so the demo help and the dispatcher stay in sync.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/cli/cmd/run/demo.ts, line 797:

<comment>The demo mode's bash→terminal rename is incomplete: the `/fmt` dispatcher was updated to match `kind === "terminal"`, but the `KINDS` array (and the `/permission bash` footer example) still list `bash`. As a result the documented `/fmt bash` slash command no longer produces any output (it silently returns false) while `/fmt terminal` works, and `/permission bash` points at a kind that `permissionKind`/`PERMISSIONS` no longer accept. Please also update the `KINDS` array entry and the footer examples to `terminal` so the demo help and the dispatcher stay in sync.</comment>

<file context>
@@ -794,16 +794,16 @@ function emitPermission(state: State, kind: PermissionKind = "edit"): void {
   const file = path.join(root, "src", "demo-format.ts")
 
-  if (kind === "bash") {
+  if (kind === "terminal") {
     const command = "git status --short"
-    const ref = make(state, "bash", {
</file context>

@ainaanraza

Copy link
Copy Markdown
Author

Thanks for the thorough bot reviews! We've completed the core rename across 90+ files and handled backward compatibility, but there are still several edge-case tests and legacy identifiers left to fix.

Because this refactor touches so many foundational files, it’s a bit too large for me to tackle alone. I’d love for other contributors to jump in and collaborate to help get this over the finish line. Please feel free to push directly to this branch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Rename internal bash tool to shell for cross-platform accuracy

2 participants