Hmbown/CodeWhale · error

dsh is not on PATH; install the official DeepSeek Harness fi

Error message

dsh is not on PATH; install the official DeepSeek Harness first (npm i -g @deepseek-ai/dsh)

What it means

`ensure_launchable_dsh` gates every mutating dsh subcommand (connect, update, launch, install-bundle) on the integration state. `NotInstalled` means detection found no `dsh` executable anywhere on PATH, and the message points at the official DeepSeek Harness npm package as the install source. The check runs before any file is read or written.

Source

Thrown at crates/tui/src/integrations/cli.rs:510

                    println!("  {}", path.display());
                }
            }
            println!(
                "  (receipt history is kept at {}; $DSH_HOME is never touched)",
                paths.receipt.display()
            );
            confirm(yes, "Remove the DSH integration files?")?;
            let removed = dsh::remove(&paths)?;
            println!("removed {} file(s)", removed.len());
            Ok(())
        }
    }
}

fn ensure_launchable_dsh(report: &DshStatusReport) -> Result<()> {
    match &report.state {
        DshIntegrationState::NotInstalled => {
            anyhow::bail!(
                "dsh is not on PATH; install the official DeepSeek Harness first (npm i -g @deepseek-ai/dsh)"
            )
        }
        DshIntegrationState::Offline { reason } => anyhow::bail!("dsh is offline: {reason}"),
        DshIntegrationState::Incompatible { reason, .. } => {
            anyhow::bail!("installed dsh is incompatible with this integration: {reason}")
        }
        _ => Ok(()),
    }
}

View on GitHub (pinned to 8880682c63)

Solutions

  1. Install dsh: `npm i -g @deepseek-ai/dsh`
  2. Verify with `which dsh` and `dsh --version` in the same shell you run Codewhale from
  3. If installed but not found, add your npm global bin directory to PATH (`npm config get prefix` shows the prefix)
  4. Re-run `codewhale integrations dsh status`; the `dsh binary:` line must show a path instead of 'not on PATH'
Defensive patterns

Strategy: validation

Validate before calling

if which::global("dsh").is_err() {
    eprintln!("install dsh first: npm i -g @deepseek-ai/dsh");
    return Ok(());
}

Type guard

fn dsh_installed(report: &DshStatusReport) -> bool {
    !matches!(report.state, DshIntegrationState::NotInstalled)
}

Prevention

When it happens

Trigger: Any of `connect`, `update`, `launch`, or `install-bundle` on a machine where `dsh` is not on PATH — never installed, installed in a different user's npm prefix, or installed via an nvm/asdf shim that the invoking shell has not loaded.

Common situations: Fresh machines; dsh installed under a different Node version manager than the active one; CI containers without dsh; macOS .zprofile PATH entries missing in non-login shells; local bins directory (`npm config get prefix`/bin) not on PATH.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/d6e225c6909375e0. Report an issue: GitHub.