Skip to content

[Feature]:Open a new terminal block at a specified directory via external invocation (CLI arg / URL scheme) #3329

@big100

Description

@big100

Feature description

Allow Wave Terminal to be invoked from outside the app — e.g. Windows Explorer right-click, macOS Finder Services, Linux file managers, shell scripts, IDE "Open in Terminal" actions — with a directory path, so that Wave opens a new terminal block at that path, whether Wave is already running or not.

Why this matters

Right-click a folder → "Open in Terminal" is a baseline workflow in essentially every modern terminal: Windows Terminal, iTerm2, VS Code, Hyper, Tabby, Alacritty (--working-directory), Kitty (--directory), WezTerm (--cwd). Wave is currently the odd one out.

Why it can't be done today

  1. Wave.exe <path> ignores the argument — Wave just launches without changing cwd.
  2. wsh term is the only documented way to create a new terminal block, but it requires WAVETERM_TABID and WAVETERM_JWT env vars that are injected only inside Wave-managed shells. Calling wsh term from an externally-spawned process (e.g. a Windows context-menu wrapper script) fails with exit code 1:

    WAVETERM_TABID environment variable not set

  3. There is no URL scheme (e.g. waveterm://), so deep-linking is also impossible.

The best workaround a user can put together today is: launch Wave, copy cd "<path>" to the clipboard via a wrapper script, then manually paste it inside Wave. This is significantly worse UX than every competitor.

Related but distinct issues

Acceptance criteria

  • A documented way to invoke Wave from any external process with an absolute folder path, resulting in a new terminal block at that path.
  • Works whether Wave is already running or not.
  • Works on Windows, macOS, and Linux.
  • Existing wsh term behavior inside Wave shells remains unchanged.

② Implementation Suggestion (선택 — 여기에 해결방법 옵션들)

Any one of the following would solve it. Listed in order of UX preference / implementation simplicity.

Option A — CLI argument on Wave.exe (preferred)

Wave.exe --open-dir "C:\path\to\folder"

Behavior:

  • No instance running → launch Wave, then create a terminal block at the given path.
  • Instance already running → Electron's second-instance event fires; the existing instance creates a new terminal block (or new tab) at that path and focuses the window.

Electron already provides app.requestSingleInstanceLock() + second-instance event for exactly this pattern; the heavy lifting is in wavesrv (creating the block via the same internal RPC wsh term uses) — so most of the logic already exists.

Option B — Custom URL scheme waveterm://

Register a protocol handler so external callers can do:

waveterm://open?path=C%3A%5Cpath%5Cto%5Cfolder
waveterm://new-tab?cwd=...

Same behavior as Option A. Precedent: VS Code (vscode://), Cursor, JetBrains tools all do this.

Option C — Make wsh usable without WAVETERM_TABID / WAVETERM_JWT

Allow wsh term --workspace <id> --cwd <path> (and wsh tab create, see #3285) to authenticate via a stable client token persisted at ~/.config/waveterm/ or %LOCALAPPDATA%\waveterm\Data\ instead of requiring the env-injected JWT. The token would be created on first Wave launch and read by any wsh invocation system-wide.

This is the most architecturally interesting option because it would also unblock scripting use cases (#3285) — but it's also the most invasive change.

Suggested combination

Implement Option A first (smallest surface, immediate user benefit, no new auth model) and Option C later for power users / scripting.

Implementation Suggestion

Any one of the following would solve it. Listed in order of UX preference / implementation simplicity.

Option A — CLI argument on Wave.exe (preferred)

Wave.exe --open-dir "C:\path\to\folder"

Behavior:

  • No instance running → launch Wave, then create a terminal block at the given path.
  • Instance already running → Electron's second-instance event fires; the existing instance creates a new terminal block (or new tab) at that path and focuses the window.

Electron already provides app.requestSingleInstanceLock() + second-instance event for exactly this pattern; the heavy lifting is in wavesrv (creating the block via the same internal RPC wsh term uses) — so most of the logic already exists.

Option B — Custom URL scheme waveterm://

Register a protocol handler so external callers can do:

waveterm://open?path=C%3A%5Cpath%5Cto%5Cfolder
waveterm://new-tab?cwd=...

Same behavior as Option A. Precedent: VS Code (vscode://), Cursor, JetBrains tools all do this.

Option C — Make wsh usable without WAVETERM_TABID / WAVETERM_JWT

Allow wsh term --workspace <id> --cwd <path> (and wsh tab create, see #3285) to authenticate via a stable client token persisted at ~/.config/waveterm/ or %LOCALAPPDATA%\waveterm\Data\ instead of requiring the env-injected JWT. The token would be created on first Wave launch and read by any wsh invocation system-wide.

This is the most architecturally interesting option because it would also unblock scripting use cases (#3285) — but it's also the most invasive change.

Suggested combination

Implement Option A first (smallest surface, immediate user benefit, no new auth model) and Option C later for power users / scripting.


③ Anything else? (선택)

Prior art (CLI / URL flags for "open at path")

Terminal Flag / Mechanism
Windows Terminal wt.exe -d "<path>" + Explorer integration
iTerm2 open -a iTerm "<path>" + Services menu
VS Code code "<path>" + vscode:// URL scheme
Alacritty --working-directory <path>
Kitty --directory <path>
WezTerm --cwd <path>
Hyper, Tabby similar CLI / first-arg-as-path

Environment

  • Wave version: 0.14.5
  • OS tested: Windows 11 (issue applies cross-platform)

Workaround currently in use

Registry-based context menu entry that runs a PowerShell wrapper which copies cd "<path>" to the clipboard and launches Wave. User must then Ctrl+V + Enter inside Wave. Functional but clunky.

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesttriageNeeds triage

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions