Preface¶
DeepSeek Harness (referred to as dsh for short) is an Agent runtime open-sourced by DeepSeek. Its core philosophy is “Everything is a plugin”: models, tools, sessions, sandboxes, scheduling, and interfaces can all be replaced or combined via plugins. The official repository is still in developer preview, so its interfaces are subject to change. A community member has compiled various plugins into the independent site DeepSeek Harness Plugin Repository, which has no official affiliation with DeepSeek / FangTian. Please refer to the original text on the directory page for installation commands.
When using dsh for daily coding work, the time-consuming part is often not opening a session, but manually transferring pre-sorted tickets from Linear, GitHub Issues, or Jira one by one to the agent, then waiting for it to finish, retrying on failures, and switching workspaces. OpenAI’s open-sourced Symphony solves exactly this problem: polling task sources, creating isolated workspaces for each ticket, dispatching agents according to WORKFLOW.md, and backing off and retrying on failures. dsh-dashboard connects this scheduling contract to DeepSeek Harness, and the dashboard is embedded directly in the native sidebar, eliminating the need to open a separate console.
Below is an introduction to what this plugin is, what it can do, how to install it, how to write WORKFLOW.md, and the boundary conditions you must pay attention to when using it.
What is this¶
dsh-dashboard is a workflow and automation plugin maintained by Uddoo, with its repository address at Uddoo/dsh-dashboard, licensed under MIT, and its main language is TypeScript. It was added to the directory page on 2026-08-15, and as of 2026-08-18, it has 3 GitHub stars. The current version of the npm package is 0.7.0, and the repository is compiled and tested for DeepSeek Harness Web profile 0.1.0-rc.6.
One-sentence positioning: It converts tasks from Linear, GitHub Issues, Jira Cloud, Asana, GitLab, or local Host tasks into isolated Harness Agent runs, while retaining the native shell, sidebar, sessions, tools, model selection, and permission system.
It reimplements Symphony’s scheduling contract, rather than embedding the Elixir/OTP implementation into dsh. The README clearly states: TaskSource is responsible for the Provider boundary, HarnessAgentRunner maps execution and resumption to the Harness native session, and the dashboard turns runtime observation signals into a Linear-style Board. The upstream reference is openai/symphony.
Core Features¶
The plugin’s capabilities can be divided into four sections: task sources, scheduling, workspaces, and the dashboard.
- Multi-task sources, but only one active
WORKFLOW.mdat a time. Supports Linear project Issues, GitHub repository Issues (Pull Requests are explicitly excluded), Jira Cloud project Issues, Asana project Tasks, GitLab project Issues, and Local tasks that do not require credentials. After switchingtracker.kind, the dashboard context and scheduling source will only update after a new workflow has passed full validation and hot reload successfully. Invalid hot reloads will be rejected, and the last valid definition will remain in effect. - Deterministic scheduling. Eligible tasks are sorted by priority, creation time, and identifier; required labels can be specified; global concurrency can be set, or concurrency can be configured per status. Failed runs use capped exponential backoff, and the task source status will be rechecked before each dispatch. Linear’s
blocksrelationship and Jira’s “is blocked by” will be projected as blockers when available. Temporarily missing tasks in query results will pause running but not be treated as terminal states, avoiding accidental deletion of workspaces during a transient query. - One persistent workspace per task, with lifecycle hooks.
after_create,before_run,after_run, andbefore_removecan be configured. Git projects use detached worktrees, while non-Git projects use controlled directories. Automatic task claiming is always disabled: registering or scanning other projects only writes to the Catalog, and will not automatically claim tickets across projects. - Dashboard in the native sidebar. It is attached via
sidebar.footer.actionandshell.overlay, and does not replace the existing sidebar. The four views are Board (columns, filters, task details), Runtime (run/retry/blocked status, turn, token, worker host), Projects (persistent Catalog, scan confirmation), and Configuration (last valid workflow, credential health, concurrency and turn limits). TheProvider · Projectnext to the title is dynamic context, such asLinear · ENG,GitHub · openai/example,Local · Personal.
There are also several hard implementation constraints that cannot be omitted in this article: External credentials always remain on the trusted Host, and will not enter the Dashboard’s RPC payload or browser state; the browser only receives constrained state projections, and the operation surface includes Pause/Resume, Stop, Refresh, Catalog, and local task maintenance; agentProfile.permissionPreset must be explicitly filled in, the default packaged preset uses the existing workspace-write, and unattended scheduling will not silently elevate permissions.
Installation and Enablement¶
The runtime environment follows the repository README: Node.js 22.19+ or 24+; pnpm 11.19+ when building from source; DeepSeek Harness Web profile 0.1.0-rc.6; and an existing Harness permission preset is required. Corresponding credentials are needed for remote Providers, while Local tasks do not require them.
The installation command given on the directory page is as follows, run it in the DeepSeek Harness terminal:
dsh plugin add github:Uddoo/dsh-dashboard
The directory page also reminds you that the plugin runs with the permissions of the current dsh process, and may execute code during installation. Please check the source code repository and license before installing. If you need a reproducible installation, fix the commit hash as instructed on the page:
dsh plugin add github:Uddoo/dsh-dashboard#commit
Replace commit above with the actual commit hash in the repository, do not use the literal commit.
The GitHub README also provides the npm package installation method, and explicitly specifies the Web profile and version 0.7.0. The npm package includes pre-built Host and browser entry points, and does not require granting installation build permissions:
dsh plugin --profile web add dsh-dashboard@0.7.0
dsh web --dump-config
dsh web
If you do not have a global CLI, you can use the official package to run the same commands:
npx --yes @deepseek-ai/dsh@0.1.0-rc.6 plugin --profile web add dsh-dashboard@0.7.0
npx --yes @deepseek-ai/dsh@0.1.0-rc.6 web --dump-config
npx --yes @deepseek-ai/dsh@0.1.0-rc.6 web
Open the address printed by dsh web, and select Dashboard in the native sidebar. To uninstall:
dsh plugin --profile web remove dsh-dashboard
The plugin’s default configuration is in cordis.patch.yml inside the package. At minimum, you need to configure the current project root directory, the WORKFLOW.md path, and an explicit permission preset in the Web profile. Below is the override example from the README (paths follow the repository original, the development verification host is Windows):
- id: dsh-dashboard
config:
currentProject:
root: C:\work\my-project
policyPath: WORKFLOW.md
registerInCatalog: true
agentProfile:
id: default
permissionPreset: workspace-write
workerHost: workstation-01
policyDefaults:
pollingIntervalMs: 5000
workspaceRoot: .dsh-dashboard/workspaces
hookTimeoutMs: 60000
maxConcurrentAgents: 10
maxTurns: 20
maxRetryBackoffMs: 300000
currentProject.root is the project root selected by Harness; relative paths are resolved from the Harness process working directory. agentProfile.id must exactly match project.agent_profile in WORKFLOW.md. discovery.roots can specify restricted scan root directories for the Catalog, each requiring an absolute path, with maxDepth ranging from 1 to 8; scanned candidates will not be written to the Catalog without confirmation.
Typical Usage¶
First decide on a task source. The repository provides complete examples: the default WORKFLOW.example.md is for Linear, and there are also separate versions for GitHub, Jira, Asana, GitLab, and Local. The version must currently be 1.
If you do not want to connect to an external Tracker, using Local mode is the most straightforward. Below is an excerpt from the official examples/WORKFLOW.local.md:
---
version: 1
project:
name: personal
agent_profile: default
tracker:
kind: local
provider:
project_id: personal
context_label: Personal
required_labels: []
active_states: [Todo, In Progress, Human Review]
terminal_states: [Done, Canceled]
policy:
polling:
interval_ms: 5000
workspace:
root: .dsh-dashboard/workspaces
hooks:
timeout_ms: 60000
agent:
max_concurrent_agents: 3
max_turns: 20
max_retry_backoff_ms: 300000
dashboard:
visible_states: [Backlog, Todo, In Progress, Human Review]
---
Work on {{ issue.identifier }}: {{ issue.title }}.
{{ issue.description }}
In Local mode, a Linear-style + will appear next to each visible column header, allowing you to directly create tasks, edit titles and descriptions, change statuses, set priorities, and delete tasks. Tasks are saved as JSON files on the Host side, with the default path being ~/.dsh-dashboard/tasks.json, and do not use browser localStorage. Writes are executed serially, using a temporary file in the same directory before atomic rename. Edits carry the version at the time of opening, and will be rejected if the Agent or another editor has already made changes. Deleting via the Dashboard only removes the task record, and existing Agent workspaces will remain.
If your tasks are already in GitHub Issues, replace tracker.kind with github and fill in owner and repo. Below is an excerpt from the official examples/WORKFLOW.github.md:
tracker:
kind: github
provider:
owner: your-org
repo: your-repository
context_label: ENG
state_labels:
Backlog: status:backlog
Todo: status:todo
In Progress: status:in-progress
Human Review: status:review
Done: status:done
required_labels: []
active_states: [Todo, In Progress, Human Review]
terminal_states: [Done, Canceled]
GitHub and GitLab use state_labels to map workflow status names to repository labels. Labels with names exactly matching a declared status will also be recognized. Open Issues with no matching labels will fall back to the first active state, and closed Issues with no matching terminal state labels will fall back to the first terminal state. Jira uses native status names directly; Asana uses the Section where the task is located, and completed tasks use the first terminal state.
Only the credentials for the currently used remote Provider need to be set. The environment variable names given in the README are:
- Linear: LINEAR_API_KEY
- GitHub: GITHUB_TOKEN
- Jira Cloud: JIRA_EMAIL, JIRA_API_TOKEN
- Asana: ASANA_ACCESS_TOKEN
- GitLab: GITLAB_TOKEN
You can also write the same-name references into $DSH_HOME/.credentials.yaml. Do not commit this file, and do not write real tokens into logs. The Configuration view only displays the reference name, whether it is configured, and the credential source, and will not send secrets to the browser.
The Prompt section uses Liquid templates. You can reference issue.identifier, issue.title, issue.description, issue.state, issue.labels, issue.url, and the retry count attempt. The Agent will resume the same Harness session within the configured max_turns; when attempt has a value, the official example will require continuing from the current workspace and session, rather than redoing completed investigations.
Lifecycle hooks run as trusted local commands in the task workspace, and the review standard should be the same as for build and deployment scripts. When the current project is a Git repository, the workspace is already a detached worktree before after_create is executed, do not clone again in the hook. Non-Git projects receive a controlled empty directory, and any required initialization should be written in after_create. A failed after_create will delete the incomplete workspace to facilitate reinitialization on the next run; before_remove will reparse the deletion target after it finishes, and if the root or target changes during the hook, the cleanup will not proceed.
Applicable Scenarios and Notes¶
This plugin is suitable for users who are already using the DeepSeek Harness Web UI and wish to automatically dispatch Agents based on task source status. There are three typical usage categories:
1. Team tickets are in Linear / Jira / Asana / GitLab, and you want to hand “eligible tickets” to Agents in isolated workspaces according to status columns, and view turn, token, and blocking reasons in the same Harness interface.
2. The repository uses GitHub Issues as a task board (note: Pull Requests are not within the task scope), using labels to map Todo / In Progress / Review states.
3. Do not connect to external systems first, use the Local dashboard to create tickets yourself, and verify WORKFLOW.md, hooks, and concurrency limits.
There are several boundary conditions you must review carefully before use.
The plugin runs with the permissions of the current dsh process. Both the directory page and the README require you to check the source code and license before installation. Hooks can execute local commands in the workspace, and the permission model should be reviewed as if “this script will appear in the build pipeline”.
The compatibility statement is stricter than the installation command. The range for most Harness peers in package.json is >=0.1.0-rc.5 <0.2.0, but dsh-storage / dsh-storage-domain required by Project Catalog has a range of >=0.1.0-rc.6 <0.2.0, and the full runtime baseline is Web profile 0.1.0-rc.6. The repository clearly states: You cannot assume compatibility with rc.7 or subsequent 0.1.x versions just based on semver; you need to re-typecheck, test, package, and perform an installation and smoke test in an isolated DSH_HOME. Compatibility with versions <rc.6 or >=0.2.0 is not claimed.
The development and verification host is Windows. The compatibility document states: It is not claimed that hooks, symbolic links, and path cleanup have been tested on Linux / macOS; cross-platform path logic is retained in the implementation, but real-world testing evidence is currently limited to Windows. The workspace root and task directories must be real directories, not symbolic links.
The remote Provider’s automated tests use mock APIs. The repository does not claim to have performed write or long-term unattended burn-in tests with real GitHub, Jira, Asana, or GitLab credentials, and deployers must validate real credentials themselves. The scope of GitHub tasks is limited to Issues, excluding Pull Requests.
The execution surface is always bound to the selected currentProject in Harness. The Catalog can register multiple Projects, but automatic task claiming remains disabled, and it will not automatically claim tickets across Projects. This is different from “opening the dashboard can feed multiple repositories at once”.
Summary¶
dsh-dashboard solves the problem of manually feeding tickets one by one in dsh: use WORKFLOW.md to describe task sources, states, concurrency, and Prompts, and the Host-side scheduler dispatches isolated Harness Agents according to the rules, while the dashboard remains in the native sidebar. It is inspired by Symphony, but runs on Harness’s own sessions, permissions, and UI slots, rather than another Elixir runtime.
Community plugin directory page: https://deepseek-harness-plugin.com/zh-CN/plugins/dsh-dashboard/
Source code and complete configuration instructions: https://github.com/Uddoo/dsh-dashboard
Before installation, review the license and source code. For a reproducible environment, fix the commit or npm version 0.7.0, and align the Harness version to 0.1.0-rc.6 as declared in the repository.