If you've recently come across the command-line tool open-sourced by DeepSeek in tech circles, you've probably been struck by two contrasting facts: on one hand, it surged to over 50,000 stars within a single day of being open-sourced on August 13th; on the other, the README is only about 1,700 words long, with no screenshots, no feature list, and not even a clear explanation of "what this thing actually is"—the entire document drops just one line: Everything is a Plugin. The project is called deepseek-harness, with the command-line shorthand dsh. It's not an ordinary chat client, but a programmable scaffold that mounts models, tools, plugins, and Agent presets all onto the same runtime. And precisely because "everything is a plugin," its installation and configuration paths branch off in more directions than typical tools: some people just want to try it out, some want to use it daily, some want to track the mainline code, and some need to hook it up to domestic models' Coding Plan. This article follows the order of "get it installed first, then use it smoothly, and finally configure it fully," breaking down the complete workflow on macOS into copy-pasteable steps. This section first covers installation and environment verification, then explains the three things to do when first entering the Web UI, and finally lays out the trade-offs among the four model modes, so that before you even start a conversation, you already have a clear map in your head.

dsh --version returns 0.1.1-rc.2: First, Confirm Whether Your Environment Actually Has It Installed

A bad habit many beginners pick up right after installing a tool is to jump straight into running the core features, and only when things fail do they start questioning their life choices. For a command-line tool like dsh that needs to spin up a local service and mount plugins at runtime, the very first thing is always to confirm "is it installed, and which version is installed". The official way to verify this is very plain: a single version query command. The current version number returned is 0.1.1-rc.2. Note that this number carries an rc suffix, meaning release candidate, which indicates the project is still in a phase of rapid iteration, and both its interfaces and default behaviors may change. If what you get on your own machine isn't this number, don't panic: either the official team had already released a newer rc by the time you installed it, or you installed an earlier snapshot. As long as it can print out a version string normally, that means the executable has made it into your PATH, and the command resolution chain is working.

dsh --version
# 0.1.1-rc.2

This command looks simple, but it helps you rule out a whole category of problems. The typical symptom of dsh failing to install is the terminal directly reporting command not found, which usually means one of three situations: the global install didn't succeed, npm's global bin directory isn't in your PATH, or you switched Node versions using something like nvm, causing global packages to land in a different directory. When you hit command not found, first use npm root -g and npm bin -g (newer npm versions use npm prefix -g) to confirm where the global directory is, then check whether that directory appears in the output of echo $PATH. This is a common ailment of all Node command-line tools, not a pitfall unique to dsh. Knowing this in advance can save you half an hour of troubleshooting.

Before getting hands-on, it's worth clarifying dsh's positioning first, because it determines all the configuration logic that follows. This project was open-sourced by DeepSeek on August 13th, and within a single day its star count surpassed fifty thousand, yet the README is extremely restrained—about seventeen hundred words, not a single screenshot, no feature list. The most central statement is that phrase: Everything is a Plugin. This sentence isn't a marketing slogan; it's an architectural fact: model providers are plugins, tools are plugins, and even your custom Agent presets are plugins. The official description of "creation mode" in the source code is very blunt—treat it as a session with a Shell, because cordis_mount executes JavaScript written by the model on a live runtime. Once you understand this, you won't find it scattered when you later see "model providers can be added arbitrarily," "modes can be switched," or "third parties can even install sidebar plugins"—they're all different facets of the same plugin mechanism.

So the conclusion of this section is clear: after installing, run dsh --version first, and only proceed once you see the version number. This step costs less than ten seconds, yet it pulls you straight out of the fog of "features not working." Once you've confirmed the environment is usable, we'll choose an installation route. The official team offers three paths: temporary execution via npx, global installation via npm, and building from source. These three paths correspond to three types of people, and we'll go through them one by one below.

npx @deepseek-ai/dsh web: A no-install, try-it-out route

In the official documentation, the npx approach is labeled "temporary run," and it's the first method the official docs recommend. Its defining trait is that it doesn't write to disk—you don't need to install anything globally ahead of time; npx fetches the package from the npm registry and runs it on its own. For anyone who just wants to see what this tool looks like and doesn't plan to use it long-term, this is the lowest-cost path.

# Method one: temporary run (officially recommended)
npx @deepseek-ai/dsh web

After you run this command, the installation process pauses to ask for your confirmation—the terminal will prompt you with something like "do you want to continue," and you just type y and press Enter. This step is standard behavior in the npm ecosystem, because you're temporarily downloading and executing a remote package, and npm needs your explicit authorization. Once confirmed, the package is pulled down and launched directly; you'll see the terminal start printing logs, and eventually it starts a local service listening at http://127.0.0.1:3080. Copy that address into your browser and you're in the Web UI, ready to try it out.

There are three engineering details here worth unpacking. First, the use of 127.0.0.1 rather than localhost means the service binds only to the local loopback address, so other devices on the LAN can't reach it by default—a safe default for a personal development environment. If you genuinely need to access it from your phone or another machine, you'll have to check the binding configuration yourself rather than just changing the address to 0.0.0.0 and calling it done, since that would expose your API Key to everyone on the same network segment. Second, port 3080 is a hardcoded default; if something else on your machine is already using 3080, startup will fail or behave abnormally. In that case, either stop the process occupying the port first, or specify a different port in the command (for the exact parameters, rely on the live output of dsh web --help, since rc-version parameters may change). Third, npx's caching behavior: npx places the downloaded package in npm's cache directory, so the second run is usually faster, but it may still check for versions each time. This means that if you ever notice inconsistent behavior, it's likely because a new version landed in the cache—running npx @deepseek-ai/dsh --version to compare which version was actually pulled will explain most "it was working fine yesterday" problems.

Using npx also carries a hidden cost: it goes through a resolution and fetch process every time, so startup speed isn't as stable as a global install, and it tends to hang or fail in network-restricted environments. That's why the official positioning is spot on—"suited to those trying it out." Once you're sure you'll use it regularly, it's time to switch to a global install.

Daily usage of dsh web after global installation via npm install -g @deepseek-ai/dsh

If you plan to use dsh as a daily tool, a global installation is the only sensible choice. The essential difference from npx is this: the package is actually installed into your global node_modules, and a stable dsh executable entry point is generated in the global bin directory. From then on, startup no longer incurs the overhead of fetching each time, nor does it depend on npm's temporary cache—the startup path is fixed and behavior is predictable.

# Option two: after global installation, you can use dsh web directly
npm install -g @deepseek-ai/dsh
dsh web # launches the Web UI, default port 3080

Once installed, every subsequent use only requires running dsh web to launch the Web UI, still on the default port 3080. The advantage of this command is that it completely decouples "installation" from "running": installation is one-time, running is high-frequency, and in your daily work you only need to remember dsh web. The dsh --version verification mentioned earlier is especially meaningful in the global installation scenario, because global packages can be affected by Node version switching, permission issues, and registry mirror issues—and the version number is the fastest health check.

There are two common pitfalls with global installation, and it's worth clarifying them upfront. The first is permission issues: if you installed Node using the system's built-in version, the global directory may be in a location like /usr/local that requires sudo, and running npm install -g directly will throw EACCES. The correct approach is not to blindly add sudo (that messes up file ownership and leads to all kinds of bizarre errors during subsequent upgrades), but to switch to nvm or fnm for managing Node so that the global directory falls under your user directory. The second is registry mirror issues: if installation hangs on domestic networks, you can temporarily switch to a domestic mirror to install, then switch back to the official registry afterward—but note that mirrors may lag in synchronization, and rc versions in particular tend to fall behind by one or two minor versions, which is exactly why you must verify with dsh --version after installation. To let you see the trade-offs between the two approaches at a glance, the table below aligns the key dimensions.

Comparison dimensionnpx temporary runnpm global installation
Typical commandnpx @deepseek-ai/dsh webnpm install -g @deepseek-ai/dsh, then dsh web
Persisted to diskNot persisted globally, uses npm cachePersisted to global node_modules and generates a dsh entry point
Install-time interactionAsks you to confirm, enter yInstalls directly, no extra confirmation
Startup speedSlower, depends on cache and networkFast and stable, fixed path
Best forThose who just want a taste or a quick lookThose who use it often, as a daily tool
Default listeninghttp://127.0.0.1:3080http://127.0.0.1:3080
Version checknpx @deepseek-ai/dsh --versiondsh --version

In one sentence: use npx for a taste, use global installation for long-term use. Both ultimately land on the same Web UI, with identical ports and interactions—the only difference is the startup method and stability. And if you're the kind of person who "must keep up with the mainline and wants to try new plugin mechanisms at the earliest opportunity," there's a third path—building from source.

Building from Source: Four Steps—clone, pnpm install, pnpm run build, pnpm dsh web

The third method officially provided is a one-shot installation from source. The reason this path exists is that dsh's plugin mechanism is open by design: if you want to write your own plugins, modify runtime behavior, or verify a new feature that hasn't been released yet, you have to get the source and build it yourself. The steps follow a standard frontend monorepo workflow—four steps in total, and none of them can be skipped.

git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web

Let's break these four steps down. Step one, git clone—the repository URL is https://github.com/deepseek-ai/deepseek-harness.git. It's worth bookmarking this address directly, because you'll keep coming back here to study the plugin mechanism, read the pattern source code, and file issues. Step two, cd into the repository directory—there's nothing technical about this step, but it's extremely important, since all subsequent pnpm commands must be run from the repository root. Step three, pnpm install—note that this is pnpm, not npm. The project uses pnpm as its package manager, so if you don't have pnpm installed locally, you'll need to install it globally via corepack or npm first. Using npm install on a pnpm project easily leads to the tricky "it installed but the build fails" class of problems caused by different dependency hoisting strategies—this is one of the most common source-build pitfalls. Step four, pnpm run build—this step compiles the TypeScript source into runnable artifacts and is the most time-consuming part of the whole process. Build errors midway are usually caused by a Node version that's too old or missing system-level dependencies. Look at the first line of the error, not the last—the first line is usually the root cause. Step five, pnpm dsh web—note that here you don't type dsh directly; instead, you go through pnpm to forward to the repository's local dsh entry point. This way, what starts up is the code you just built, not the globally installed version.

The source-build route suits three kinds of people: developers who want to write plugins for dsh, researchers who want to debug runtime mounting behavior, and teams that need to pin a specific commit for internal deployment. The trade-off is high maintenance cost—every time you pull upstream updates, you have to reinstall and rebuild, and dependencies may change along with them. So if your goal is simply to "use it," a global install is enough; only when you need to "modify it" or "see how it runs" is the source route worth it. The applicable scenarios for the three installation routes can be summed up in one phrase: npx for trying it out, global for daily use, source for customization. Once it's installed, the real main event begins—entering the Web UI for the first time.

Entering the Web UI for the first time: the order of API Key, interface language, and workspace

Assume you have already seen the local service startup logs in the terminal, and now you enter http://127.0.0.1:3080 in the browser to open the page. On your first visit, the interface will guide you through three things, and the order matters: first fill in the API Key, then switch the interface language, and finally add a workspace. Getting the order wrong will not make it impossible, but it will make you take a few extra detours in the English interface.

The first step is to enter the deepseek API key as guided. Those who do not have a Key need to generate one on the official website first, at platform.deepseek.com/api_keys. The key insight here is: the harness itself does not provide model capabilities; it is only an orchestration layer, and all inference is forwarded through the provider and Key you configure. Therefore, the validity of the Key directly determines whether you can converse later. When filling in the Key, note that the input box usually displays it only once or masks it, so when pasting, confirm that you have not brought in leading or trailing spaces. For issues like "the Key is clearly correct but authentication fails," nine out of ten are caused by extra whitespace characters or missing characters when copying.

The second step is to switch the interface language (optional). If you are not comfortable with the English interface, click the "Settings" page in the lower left corner and switch the language to Chinese. This step is optional, but for beginner readers it is strongly recommended to do it first, because later when adding workspaces, selecting models, and configuring providers, you will need to jump back and forth in the settings page, and operating in your native language can significantly reduce the cost of understanding. Switching the language only affects UI text and does not affect any runtime behavior, and you can switch back at any time.

The third step is to add a workspace. A so-called workspace is essentially "adding a project," and you need to select a local project directory. The engineering semantics of this step are: dsh will perform file reads and writes, terminal commands, and plugin mounting within the scope of this directory, so the directory choice determines which files the model can touch. At the beginner stage, it is recommended to choose a dedicated test directory or an independent git repository. Do not start by throwing your entire user home directory or a directory containing sensitive configuration into it, because the runtime has Shell capabilities and file modification capabilities, and the broader the scope you give, the greater the impact of accidental operations. After choosing the directory, you also need to select a model. At this point, the minimal configuration loop is complete, and you can enter the chat interface to test connectivity.

Putting these three steps together, it is actually a minimal usable path: fill in the Key → switch to Chinese → add a workspace and select a model. The first two steps are done once in the settings page, while the third step may need to be repeated every time you start a new project, so later we will return to the complete approach to model configuration. For now, let us clarify the fork in the road for model selection.

Flash or Pro: Trade-offs When Choosing a Model in a Workspace

After adding a workspace, the interface will prompt you to choose a model. The two tiers explicitly provided in the materials are flash and pro. The official guidance on choosing is remarkably restrained—just one line: "It depends on your task"—and the documentation does not list the specific parameters for these two tiers. This must be stated honestly: this article does not fabricate any parameters that were not provided, such as context length, price per token, or rate limits per minute. If the materials don't include these numbers, we won't make them up. What you can rely on for judgment is the general semantics of the tiers: flash leans toward lightweight and fast, while pro leans toward stronger capability and higher cost.

Based on this semantics, here is practical advice for beginners: if you're doing things like fixing a small bug, writing a standalone function, explaining a piece of code, or running a simple Q&A, flash is enough—it responds quickly, has low trial-and-error cost, and is well suited for getting the workflow running first. If you're dealing with repository-level changes spanning multiple files, tasks that require understanding the structure of a larger codebase, or scenarios with higher demands on result quality, then switch to pro. This trade-off logic is consistent with most dual-tier models: first determine task complexity, then decide the tier—rather than defaulting to always using the strongest one. Because the harness is an executor that continuously calls tools and goes back and forth over multiple rounds, a single conversation may trigger many model calls, and choosing a higher tier will amplify the consumption of the entire task.

It's worth noting that model selection is not a one-time decision. It can be adjusted at the workspace level, and later, after connecting more providers on the model configuration page, you can choose models such as GLM, Tongyi Qianwen, Xiaomi, and Volcano Ark beyond the officially preset deepseek. In other words, flash and pro are the first fork in the road you encounter within the "official presets," while the entire model configuration system is far richer than these two options. This complete configuration system is the highlight of Part 2 of this tutorial. For now, here's a teaser: as long as the Key is valid, the officially preset models will automatically fetch the model list after being added—no need for you to manually fill in a bunch of parameters.

Standard / PTC / Minimal / Creation: Who Each of the Four Model Modes Is For

After choosing a model, there's a deeper choice: the mode in the model configuration. The official recommendation from the source material is "beginners can just stick with the default Standard mode," and it also lays out the positioning of the four modes. These four modes are not model tiers, but rather runtime configurations that determine which tools the model can call and how it calls them. Once you understand them, you'll understand why dsh dares to say "Everything is a Plugin"—even "how the model uses tools" is itself a configurable plugin composition.

1️⃣ Standard Mode: Positioned as "writing code and modifying repositories normally." This is the steady, well-rounded default tier, with a complete toolset and behavior that matches most people's intuition, making it suitable as a daily workhorse. Beginners can pick it without thinking and first build up a feel for the rhythm of tool calls.

2️⃣ PTC Mode: PTC stands for Programmatic Tool Calling. This is the most unusual mechanism among the four modes, and the one most worth elaborating on. Its core change is: the model no longer calls tools back and forth one at a time, but instead writes a piece of TypeScript that composes multiple steps at once through the Code Mode SDK, and the system executes it with run_code. Translated into engineering terms—traditional tool calling is "the model says call A, the system executes A, returns the result to the model, the model then says call B," where every tool call is a complete model round trip; PTC compresses this chain of round trips into a single piece of code, where the model first orchestrates the steps in its head, writes them as TypeScript, and hands them to the runtime for one-shot execution. The source material gives a very concrete quantitative description: five round trips can be collapsed into one. This means that for complex tasks requiring consecutive operations across multiple tools, PTC can significantly reduce round-trip overhead, making "chaining many tools in a single step" a reality.

But note the implicit premise of PTC: since the model has to write TypeScript and hand it to run_code for execution, this capability is inherently more powerful than Standard mode and demands a stronger trust boundary. It suits scenarios where you already know the task steps clearly and want the model to execute them efficiently in bulk—for example, a typical pipeline operation like "read three config files, compare the differences, modify two files according to rules, then run a validation pass." The more fixed and repetitive the workflow, the more obvious PTC's payoff.

3️⃣ Minimal Mode: The source material describes it in just a few words—"just a terminal + file editing." It keeps only two things: a persistent bash, and str_replace_editor for editing files by absolute path. This is a mode that deliberately subtracts, narrowing the tool surface to a minimal set. It suits lightweight tasks, or when you just want to give the model a minimal environment where it can run commands and edit specified files. Its details are covered separately in the next section.

4️⃣ Creation Mode: Positioned as "building your own Agent presets." It has the full capabilities of Standard mode, plus the ability to modify the Harness itself: inspecting the runtime, trying plugins, and writing new Agent presets. Custom presets land in the ~/.dsh/.agent-presets/ directory. The source material quotes its source-code comment very bluntly: treat it as a session with a Shell, because cordis_mount executes model-written JavaScript on the live runtime. This is not a figure of speech but a security warning—Creation mode means the model can modify the running runtime and mount plugins it wrote itself, a level of power that requires you to know exactly what you're doing. It's intended for plugin authors and Agent preset developers, not the default option for everyday coding.

To let you see the differences among these four modes at a glance, the table below aligns their key characteristics.

ModeOfficial PositioningTool Capability ScopeWho It's For
Standard ModeWriting code and modifying repositories normallyComplete standard toolsetBeginner default, daily workhorse
PTC ModeProgrammatic Tool CallingModel writes TypeScript, composes multiple steps via Code Mode SDK, executes with run_code; five round trips can collapse into onePipeline tasks requiring bulk, consecutive tool calls
Minimal ModeJust a terminal + file editingOnly persistent bash and str_replace_editor for editing files by absolute pathLightweight tasks, minimal environment
Creation ModeBuilding your own Agent presetsFull Standard mode capabilities, plus inspecting the runtime, trying plugins, and writing new Agent presets; presets land in ~/.dsh/.agent-presets/Plugin authors, Agent preset developers

After reading this table, the logic for choosing among the four modes becomes clear: when unsure, go with Standard; when the workflow is fixed and you want more speed, go with PTC; when you just want to type commands and edit files, go with Minimal; and when you need to touch the runtime and plugins, go with Create. Note that the modes are not a simple ranking of increasing capability, but rather tailored to different task shapes—Minimal is subtraction, PTC is a paradigm shift, and Create is adding permissions. This is also the manifestation of "Everything is a Plugin" at the model layer: the same runtime, by swapping in different sets of tool plugins, yields completely different ways of working. The third-party plugin DSH-better-sidebar that appears in the materials is an extension of this idea at the UI layer—it expands the right sidebar plus bottom panel into a dual workbench, and the configuration section later will explain how to install it.

Minimal Mode Keeps Only Two Things: Persistent bash and str_replace_editor

I'm calling out Minimal Mode separately because its design philosophy is completely different from the other three modes. Standard Mode pursues "can do everything," PTC pursues "does it faster," and Creation Mode pursues "maximum capability," while Minimal Mode pursues a minimal usable tool surface. The source material describes it very precisely: keep only two things—persistent bash and str_replace_editor for editing files by absolute path.

First, persistent bash. The key word is "persistent"—this means it's a continuously existing terminal session, not a new shell for every command. The benefit of a persistent session is that state carries over: after you cd into a directory, subsequent commands are still in that directory; environment variables you export are still readable by subsequent commands; background processes you start are still running. For tasks that require continuous operations in the same environment, this is far more natural than starting from a clean shell every time. It also means the model can "pick up where it left off" in the terminal just like a human.

Next, str_replace_editor. Its key qualifier is editing files by absolute path. This reveals two important things: first, its core operation is replacement-based precise editing rather than rewriting the entire file, which is a safer way to modify code—the scope of changes is controllable and the diff is clear; second, it requires absolute paths rather than relative paths, which is an easy pitfall for beginners—if you habitually provide relative paths, you may run into file-not-found errors or edit the wrong location, especially when the working directory of persistent bash and the path resolution base of the editor are inconsistent. Absolute paths eliminate this kind of ambiguity. Using absolute paths is the most hassle-free way to use this toolset—don't cut corners by writing relative paths.

Why have Minimal Mode? Because it compresses "what the model can do" to the bare minimum, and the direct benefits are more predictable behavior, less context usage, and a smaller surface for mistakes. When you just want the model to type a few commands in a directory and tweak a file along the way, using the full toolset is actually a distraction. Minimal Mode is essentially a scalpel prepared for these lightweight scenarios, not a Swiss Army knife. Its existence also reaffirms the relationship among the four modes—they are not different intensities of the same thing, but different tool combinations tailored for different tasks.

At this point, you've completed the full onboarding chain from "is it installed or not" to "getting into the Web UI" to "choosing a model and a mode." The minimal closed loop is this: run dsh --version to confirm the version is 0.1.1-rc.2, install it with npx or npm install -g, open http://127.0.0.1:3080 in your browser, enter your deepseek API Key, switch to Chinese via Settings in the bottom-left corner, add a workspace directory, choose between flash and pro based on your task, and finally pick one of the four modes—Standard, PTC, Minimal, or Creation—to get started. If this chain works end to end, it means your environment, Key, directory permissions, and runtime mounts are all fine, and you can move on to the next stage of formal configuration. And as you followed the steps above, you may well have noticed that the model provider column looks like it has far more than just deepseek—preset providers like GLM CodePlan, Alibaba's qwen-token-plan-cn, and Xiaomi's xiaomi, as well as providers requiring custom protocols like Volcano Ark, are all waiting to be connected. How to configure them, where the Keys come from, how to choose protocols, and how to pull model lists—that's exactly the full model configuration workflow that Part 2 of this tutorial will cover.

In the previous section, we took dsh from a global npm install all the way to running in the Web UI, and completed workspace addition and selection of the four modes. This section continues from there: first, we'll thoroughly explain "Creation Mode" and the custom preset directory it writes to disk, then return to the chat interface for a connectivity check, then get all three official preset providers, two tested models, and Volcano Ark custom integration working one by one, and finally cover the desktop client and third-party plugins, wrapping up with an actionable operations checklist.

Creation Mode and ~/.dsh/.agent-presets/: Where Custom Agent Presets Are Stored on Disk

Let's first clarify the relationships among the four modes, otherwise when configuring models later you won't know who you're configuring for. Standard Mode is the default tier, and its capability boundary is simply "write code and modify repositories normally": read and write files, run commands, inspect results, then keep iterating—this is a conventional Agent loop. The first tier above it is PTC Mode, short for Programmatic Tool Calling. Its difference from Standard Mode lies not in the number of tools, but in the calling pattern—in Standard Mode, the model calls tools one at a time in a back-and-forth fashion, advancing only a small step per round trip; in PTC Mode, the model no longer calls tools one by one, but instead writes a piece of TypeScript directly, composing multiple steps together through the Code Mode SDK, which the system executes via run_code. The source material puts it intuitively: five round trips can be collapsed into one. For chained tasks like "search for files first, then modify three places, then run tests, then revise based on errors," the payoff of PTC is very pronounced.

The second tier is Minimal Mode, which does subtraction rather than addition: it keeps only two things—a persistent bash, and a str_replace_editor that modifies files by absolute path. The tool surface is pared down to the minimum, and the model has fewer "hands" at its disposal, but controllability is actually higher, making it suitable for scenarios where you only want it to make small, incremental modifications within a controlled directory.

The third tier is the protagonist of this section: Creation Mode. It is not "the opposite of Minimal Mode," but rather the full capabilities of Standard Mode plus an additional layer that lets it modify the Harness itself. This sentence needs to be read piece by piece: everything Standard Mode can do, it can do too; beyond that, it can also inspect the runtime, try plugins, and write new Agent presets. In other words, the model is not just a user of this tool—it simultaneously gains modification rights over the tool.

The storage location for custom presets is fixed: ~/.dsh/.agent-presets/. The Agent presets you have dsh generate in Creation Mode will ultimately all be written into this directory. Understanding this is important, because it means presets are versionable assets in file form, rather than black-box configurations locked inside some UI state. You can put them under git management, back them up, copy them directly when switching machines, or simply delete a directory to return to a clean state when problems arise.

The risk points must be stated up front here. cordis_mount executes model-written JavaScript on the live runtime. The original wording in the source material is "treat it as a session with a Shell," and I suggest you take that sentence directly as a security principle. This sentence carries two layers of meaning: first, the capabilities granted by Creation Mode are equivalent to a session with a Shell, and the reach of the model far exceeds "just modifying code"; second, cordis_mount executes JavaScript on the live runtime, not static configuration in a sandbox—it genuinely runs inside the current process. So before configuring a Key for Creation Mode, think through three things clearly:

  • Directory boundary: whichever project directory the workspace points to, Creation Mode's radius of activity will most likely be in that vicinity. Don't casually point it at your home directory or the entire disk root.
  • Credential boundary: the API Keys and environment variables visible to Creation Mode are equivalent to those it has the right to use. Don't mix production credentials with a sandbox environment.
  • Rollback cost: presets land in ~/.dsh/.agent-presets/, and the upside is that deleting them restores things; but actions it has executed on the live runtime (such as files it modified or commands it ran) cannot necessarily be rolled back by deleting presets. Develop the habit of trying things on a clean project first.

Lay the four modes out in a table for comparison—just refer to it when choosing:

ModeCore MechanismTool SurfaceSuitable ScenariosRisk Level
Standard ModeConventional Agent loop, calling tools one at a time, back and forthFull (file read/write + commands + repository operations)Default tier for beginners, everyday coding and repository modificationMedium
PTC ModeProgrammatic Tool Calling: the model writes TypeScript, composes multiple steps via the Code Mode SDK, executed by run_codeFull, but invoked in batches through code compositionLong chained tasks, merging multiple round trips into oneMedium-High
Minimal ModeKeeps only persistent bash and str_replace_editor for modifying files by absolute pathMinimal (two items)Small, incremental refinements within a controlled directoryLow
Creation ModeFull capabilities of Standard Mode + modifying the Harness itself: inspecting the runtime, trying plugins, writing Agent presetsAdds "modification rights"; presets stored in ~/.dsh/.agent-presets/Building your own Agent presets, extending the toolchainHigh (cordis_mount executes model-written JavaScript on the live runtime)

A very common practice path looks like this: first use Minimal Mode on a clean small project to confirm the basic pipeline works, switch to Standard Mode to run through one or two real tasks to build trust, then decide based on the task shape whether to use PTC Mode to save round trips. Once all of these run smoothly and you have a clear picture, only then open Creation Mode to write your own preset. Reversing the order is equivalent to handing over modification rights before you understand the tool's boundaries, and when problems arise it becomes very difficult to pinpoint which link went wrong.

Run a prompt first after installation: conversation test to verify connectivity

After the workspace is added and the model is selected, do not directly throw a real project task into it. The correct approach is to return to the conversation interface and first send the simplest possible prompt to perform a connectivity verification. The value of this step lies in splitting the problem domain: if a simple prompt throws an error, then it is a problem with the Key, protocol, network, or provider configuration, and has nothing to do with your project code; if this step passes, then if errors occur later, the troubleshooting scope automatically narrows to the workspace or the specific task.

Connectivity verification is recommended in the following order, with each step consuming only minimal cost:

  1. First confirm the service is running: accessing http://127.0.0.1:3080 in the browser opens the interface, indicating the local service is normal. Also run a version query in the terminal to confirm the CLI is properly installed.
  2. Send a plain text prompt: for example, ask it to simply say hello, or describe the currently selected model, without involving file reading or writing. This step verifies the link from API Key to model.
  3. Send a prompt involving one tool call: for example, ask it to list the files in the current workspace root directory. This step verifies the workspace mounting and tool execution pipeline.
  4. Observe the return: if content is returned normally, it means the KKey is valid, the protocol matches, and the provider configuration is correct; if it hangs on loading or directly reports an authentication error, go back to the provider configuration page and check the Key and protocol type.

The second command can be used directly:

# 确认 CLI 已正确安装,并查看当前版本
dsh --version
# 0.1.1-rc.2

# 确认本地 Web 服务可访问(返回 200 即服务正常)
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3080

Note that the version number 0.1.1-rc.2 is an rc (release candidate) pre-release version. This information is meaningful for operations: the features of a pre-release version may change rapidly with versions, and when encountering inconsistent behavior, the first thing to do is confirm whether both parties' version numbers match, rather than rushing to change the configuration.

Official preset providers: how to add zai-coding-cn, qwen-token-plan-cn, and xiaomi

Once connectivity is established, you can formally configure models. The entry point for model configuration in dsh follows a unified path. Get this path down first—the three presets and one custom setup below all follow the same main trunk, differing only in the "provider" selected along the way:

"Settings" → "Models" → "Add Provider" → select the corresponding identifier under "Provider" → enter the API-KEY → save

The identifiers for the three official preset providers are as follows:

  • GLM CodePlan: select zai-coding-cn as the provider, enter the API-KEY, and save.
  • Alibaba Qwen personal tokenplan: select qwen-token-plan-cn as the provider, enter the API-KEY, and save.
  • Xiaomi personal API-Key: select xiaomi as the provider, enter the API-KEY, and save.

These three share one key behavior: the model lists for these official presets do not require manual configuration. As long as the API Key is valid and the configuration is added successfully, the model list is fetched automatically. This stands in sharp contrast to the custom integration for Volcano Ark described later—with a preset provider, you only need to supply a Key and dsh handles the rest; with a custom provider, you have to fill in the protocol, fill in the endpoint, and manually pick out the models yourself.

Why can presets be fetched automatically while custom setups require manual work? The essential difference lies in whether the meta-information is already known. For preset providers, the protocol type, access endpoint, and model list are already built into dsh; the API Key you provide is just the final piece of the puzzle, and once it is in place, dsh can go fetch the list. In a custom scenario, both the protocol and the endpoint must be entered by hand, and the model list is only known after issuing a real list request, so an extra "fetch available models" interaction is required to confirm whether the configuration is correct.

Here is a small operational tip: do not configure all three providers at once. Configure one first, verify it works, confirm it is usable, and then configure the next. The reason is simple—if you configure all three at the same time and then hit an error, you are facing a multi-variable problem, and it becomes very difficult to tell whether the issue is the Key, the provider's service, or the local network. Introducing variables one at a time is the lowest-cost approach to troubleshooting.

GLM-5.2 and Qwen3.8-Max-Preview Hands-On: Select Preset Models Directly from the Home Page

Once the preset providers are configured, the usage path is very short: go back to the home page and select the corresponding model from the model list to use it directly. No further manual configuration at the model level is needed.

The hands-on conclusions provided in the source material include two points that can serve directly as selection references:

  • The GLM-5.2 model in GLM's Coding Plan tested successfully.
  • The Qwen3.8-Max-Preview model in Alibaba Qwen's Coding Plan tested successfully. The API Key acquisition address for Alibaba Coding Plan is platform.qianwenai.com/home/api-keys.
  • In addition, Xiaomi's API Key also works normally.

Looking at these three points together, we can draw a conclusion that is very useful for beginners: the officially preset integration path is a verified, stable primary path. You don't need to study protocol details, don't need to hand-write addresses, and don't need to pick models one by one. As long as you have a valid API Key, enter it, go back to the home page and select a model, and you're good to go. For the need of "I just want to get it running quickly," this path is the optimal solution.

Conversely, when do you need to go the custom route? The answer is: when the provider you want to connect is not in the official preset list. For example, scenarios like Volcano Ark that require you to specify the integration address yourself must go through the process in the next section. So the criterion is very clear — first look in the preset list, and only go custom if you can't find it there. By all means avoid forcing the custom route when a preset already supports it, as that amounts to voluntarily adding two fields that could go wrong.

Also, a reminder about an easily overlooked point: Coding Plan type Keys and pay-as-you-go API Keys are semantically different. In the source material, these two categories are described separately — pay-as-you-go API Keys were configured with deepseek and xiaomi as model providers; Alibaba Qwen and Zhipu were configured via Coding Plan API Keys using the standard template; and Volcano Engine was configured via a Coding Plan API Key using the custom approach. This classification itself is an operational clue: first confirm which category your Key belongs to, then configure it in the corresponding path. This can save you a lot of confusion about "why can't I pull any models after entering the Key."

Volcano Ark Custom Integration: openai-completions / openai-responses Protocols and Fetching Available Models

Now let's take the custom path. Using Volcano Ark's Coding Plan as an example, it isn't in the official preset list, so you have to fill in the protocol and endpoint yourself. The configuration documentation for Volcano Ark is located at console.volcengine.com/ark/region:. There are four key fields in this whole process, so let's go through them one by one:

  1. Protocol selection: Choose a tool that is compatible with the OpenAI interface protocol, that is, openai-completions or openai-responses. Which one to pick depends on which interface form the model you intend to use follows.
  2. API endpoint: Fill in the coding access endpoint ark.cn-beijing.volces.com/api/coding/….
  3. API Key: Enter your own Volcano Ark Key.
  4. Model selection: Click "Fetch Available Models" and check the ones you want from the returned list.

The "Fetch Available Models" step is the verification anchor of the entire custom process: if you can fetch the model list, the configuration is correct. This statement carries a lot of weight—it answers three questions at once: "Is the protocol right, is the endpoint right, and does the Key have permission?" If clicking it returns no models at all, don't doubt the models themselves; the problem is definitely in these three fields. So the correct troubleshooting order is: first confirm the protocol selected is OpenAI-compatible, then verify the endpoint spelling, and finally confirm the permission scope of the Key.

Next comes the most easily overlooked pitfall in this process: Volcano's model list has over 100 entries. The complaint in the source material is very true to life—"Just pick a few you commonly use, otherwise the list is too big to look at," and it explicitly points out that "the official team should add an invert-selection feature, otherwise for a model list like this with so many entries, clicking them one by one is a real pain." This statement deserves to be called out separately in the tutorial as engineering experience:

  • Don't select all after fetching a large list. Adding all 100-plus models will make the subsequent model selection list so long it becomes unusable.
  • Decide which few you need before you start selecting. A common approach is to first determine which model this task will use, check only that one, and come back to add a second one when you actually have a second need.
  • Look forward to an invert-selection feature: The source material explicitly mentions the current lack of invert-selection capability. If you run into the same pain point, this is an improvement you can feed back to the project. Before an invert-selection feature appears, controlling the number of initial selections is the most pragmatic strategy.

After selecting, delete the useless models, then click "Create Provider." This "streamline first, then create" order cannot be reversed—cleaning up after creation is equivalent to doing the work twice for nothing. Once creation is complete, pick a Volcano model and test it; if it works normally, you're good.

Putting the preset path and the custom path side by side, the differences become immediately clear:

Comparison ItemOfficial Preset ProviderCustom Provider (e.g., Volcano Ark)
Representative identifier / namezai-coding-cn, qwen-token-plan-cn, xiaomiVolcano Ark Coding Plan
Fields requiring manual entryAPI-KEY onlyProtocol type + API endpoint + API Key
ProtocolBuilt in, no selection neededMust select an OpenAI-compatible interface protocol: openai-completions or openai-responses
EndpointBuilt inark.cn-beijing.volces.com/api/coding/…
Model list retrievalAutomatically fetched after adding configuration with a valid API KeyMust manually click "Fetch Available Models" to verify configuration
Model count riskNo handling neededOver 100 entries, requires careful selection, currently no invert-selection feature
Final stepsAfter saving, return to the home page and select a model directlyDelete useless models → Create Provider → Pick a model and test

There is one more process detail worth codifying: the source material says "pick a Volcano model and test it, and if it works normally, that's fine." That phrase "test it" is the final gate for the entire custom integration. Many people finish configuring and jump straight into real work, only to have their first real task fail, and then they can't tell whether the integration was misconfigured or the task itself is just hard. After configuration is complete, first verify with a lightweight request—this discipline holds for both the preset path and the custom path.

Don't want to keep a browser tab open? DSH Desktop automatically launches the local dsh web

All the operations above are built on the premise of "having a tab open in the browser." If you don't want to keep a tab hanging around, or your machine doesn't have a Node environment, the community already has a ready-made alternative: an open-source desktop client built on DeepSeek Harness, DSH Desktop, which currently has nearly 20,000 stars, with its official website at www.dshdesktop.cn.

The problem it solves is very specific: letting dsh break free from the browser and run directly in a native window. In terms of features, there are three points that help daily use the most:

  • Multiple windows: you can open multiple windows at the same time to run different workspaces or different tasks, without switching back and forth between browser tabs.
  • Resident in the system tray: closing the window does not mean stopping the service; you can bring it back from the tray at any time.
  • Automatically launching the local service: it automatically launches the dsh web local service on startup. This means you don't need to manually execute those CLI commands from earlier at all.

The installation method is extremely beginner-friendly: the official website provides packaged installers, with one-click installation supported on both Mac and Windows, ready to use out of the box—once installed, you can open it and use it directly. Note that there is a switch in usage path here—if you go with DSH Desktop, you don't need to manually run dsh web in the terminal first; the client will bring up the local service, and you can go straight to the interface.

So when should you choose the browser, and when should you choose the desktop client? You can judge it like this:

  • Trying it out temporarily, wanting to first see what this thing looks like: the browser approach is enough; running temporarily with npx does not require a global installation.
  • Your machine has a Node environment, you're used to the command line, and you want the sense of control closest to the source code: install globally with npm install -g @deepseek-ai/dsh, then run dsh web.
  • You don't have a Node environment, or you don't want to keep a browser tab open all the time, and you want multiple windows and a resident tray: just use DSH Desktop, and the one-click installer solves the problem.

Looking at the three ways of running together makes it clearer: temporary running with npx is suitable for one-off trials; global installation + dsh web is suitable for developers who need to use it frequently; DSH Desktop is suitable for users who want to break free from the browser and have it ready to use out of the box. All three paths ultimately point to the same local service, just with different entry points.

Revisiting DSH-better-sidebar in September 2026: Plugin-Based Extension of the Sidebar and Bottom Panel

DSH Desktop solves the problem of "where to use it," while third-party plugins solve the problem of "what's on the interface." The plugin in question here is DSH-better-sidebar, which does one thing: extending the right sidebar + bottom panel into a dual workbench. Its GitHub project address is github.com/omdsh-dev/D…. Installation is extremely simple, just one command:

# 安装 DSH-better-sidebar 插件
curl -fsSL https://raw.githubusercontent.com/omdsh-dev/DSH-better-sidebar/main/scripts/install.sh | bash

After installation, there are two mandatory steps—skip either one and you won't see any effect:

  1. Restart DSH. Plugins are loaded at runtime, so they won't take effect without a restart.
  2. Hard-refresh the browser: Cmd/Ctrl+Shift+R. A normal refresh may hit the cache, leaving the interface stale, so a hard refresh is required.

Once these two steps are done, the sidebar will appear. The "restart + hard refresh" combination may look like a minor trick, but it's actually a general rule of plugin-based architectures: the server needs to reload plugins, and the client needs to discard its cache and re-fetch resources. Only when both sides are refreshed does it fully take effect. Going forward, this same routine applies to installing any dsh plugin.

The reason this plugin is worth revisiting in September 2026 is that it confirms the project's most core declaration—Everything is a Plugin. Looking back at the full text, you'll find this principle runs throughout:

  • Capability layer: The four modes are essentially different combinations of capabilities. Minimal mode keeps only two, while Creation mode layers on the ability to modify Harness itself.
  • Model layer: Official preset providers (zai-coding-cn, qwen-token-plan-cn, xiaomi) follow standard templates, while Volcano Ark uses a custom protocol. Both paths coexist, making model configuration equally flexible.
  • Interface layer: DSH-better-sidebar uses a single curl command to inject new workbenches into the sidebar and bottom panel.

Viewed from the vantage point of September 2026, the significance of the plugin ecosystem lies in this: the core repository can stay very thin, with capabilities growing out of plugins. As mentioned earlier, the original README was only about 1,700 characters long, with no screenshots and no feature list—just the line "Everything is a Plugin." At the time it seemed to say nothing, but in hindsight, it was actually describing the entire project's extension model. That said, from an operations perspective, one must stay clear-headed: the more powerful the plugin capabilities, the more important the trustworthiness of the installation script's source becomes. For installation methods like the curl | bash above, you should at least confirm before executing that the source is an official or community-recognized project address—don't casually copy scripts of unknown origin.

Summary and Best Practices

Condense this entire article into a checklist you can follow step by step. Execute in order, and if you run into problems, just trace back through the items.

  1. Choose an installation method: For a quick trial, use npx @deepseek-ai/dsh web (it will ask for confirmation during the process; type y); for regular use, install globally with npm install -g @deepseek-ai/dsh, then simply run dsh web, with the default port 3080; you can also use the one-click source installation (clone → cd → pnpm install → pnpm run build → pnpm dsh web).
  2. Confirm the installation succeeded: Run dsh --version. Seeing output like 0.1.1-rc.2 means it's working correctly. Note that the rc label means a pre-release version, so double-check the version number first when troubleshooting.
  3. Open the interface and complete three initial configurations: Visit http://127.0.0.1:3080 in your browser; follow the prompts to enter your deepseek API key (generate one at platform.deepseek.com/api_keys); optionally switch the interface language to Chinese under "Settings" in the bottom-left corner.
  4. Add a workspace and choose a model: Add a project directory as a workspace, then choose flash or pro depending on the task.
  5. Upgrade the model mode as needed: Beginners should start with standard mode; when you need to merge multiple round trips into a single code execution, switch to PTC mode; for controlled small-step refinement within a directory, use minimal mode; only enable creation mode when you want to write your own Agent preset.
  6. Safety discipline for creation mode: Custom presets go in ~/.dsh/.agent-presets/; keep in mind that cordis_mount executes model-written JavaScript on a live runtime, so treat it as a session with Shell access, and never point the workspace at your home directory or disk root.
  7. Verify connectivity before configuring: Go back to the chat interface and send a simple prompt. Once it works, move on to real tasks, keeping configuration issues and task issues completely separate.
  8. Prefer official presets: The unified path is "Settings → Models → Add Provider → Select Provider → Enter API-KEY and save." The three identifiers are zai-coding-cn (GLM CodePlan), qwen-token-plan-cn (Alibaba Qwen personal tokenplan), and xiaomi (Xiaomi personal API-Key); once a valid API Key is added and configured, the model list will be pulled automatically.
  9. After presets are configured, just select directly on the home page: GLM-5.2 (GLM Coding Plan) and Qwen3.8-Max-Preview (Alibaba Qwen Coding Plan) both tested fine, and the Xiaomi API Key also works normally.
  10. If no preset is found, go custom: Taking Volcano Ark as an example, choose openai-completions or openai-responses as the protocol (compatible with the OpenAI interface protocol), fill in the API address as ark.cn-beijing.volces.com/api/coding/…, enter the Key, and click "Fetch Available Models"—if it can pull the list, the configuration is correct.
  11. Handle large model lists: Volcano has over 100 models, so pick only a few commonly used ones to avoid the list being too large to view; there is currently no deselect feature, so limiting the number selected initially is the most practical strategy; delete the useless models first, then click "Create Provider", and finally select a model to test—if it works, you're good.
  12. If you don't want to open a browser tab, use the desktop client: DSH Desktop (about 20k stars, www.dshdesktop.cn) supports one-click installation on Mac/Windows, with multiple windows + system tray persistence, and automatically starts the local dsh web service on launch, so you don't need to run CLI commands manually.
  13. Install plugins as needed and refresh properly: After installing DSH-better-sidebar with a one-line curl, restart DSH and hard refresh with Cmd/Ctrl+Shift+R to see the dual workbench with sidebar and bottom panel.
  14. Reference for total configuration: By this point, you can configure 5 model providers in total—configure deepseek and xiaomi with pay-as-you-go API Keys; configure Alibaba Qwen and Zhipu with Coding Plan API Keys via standard templates; configure Volcano Engine with a Coding Plan API Key via custom setup.
  • Core mental model: Everything is a Plugin. Capabilities, models, and the interface—all three layers—are extended through a "preset + plugin" approach. Once you grasp this, you'll be able to quickly find the corresponding integration path for any new provider or plugin you encounter later.
  • Troubleshooting mantra: UI won't open → check whether the service is running on 3080; a single prompt throws an error → check the Key and protocol; can't pull models → check the protocol, address, and Key permissions; plugin installed but nothing happens → restart + hard refresh.
  • Security bottom line: Both Creation Mode and plugin installation require extra caution—the former involves executing model code in a live runtime, and the latter involves running third-party install scripts. You must vet the trustworthiness of sources yourself.

At this point, the entire chain—from installation and initial configuration to model integration, the desktop client, and plugin extensions—is complete. Looking back at that project from the beginning, the one with "a README of only about 1,700 words and no feature list," it shifted complexity out of the documentation and into the extension mechanism. What this checklist sets out to do is walk you through that extension path step by step, in order. Next, it's time to connect it to your own workspace and get to work.