Open-source project
FSMargoo/dsh-at-file avatar
FSMargoo/dsh-at-file

dsh-at-file: @file mentions for the DeepSeek Harness web composer

Codex-style @file mentions for DeepSeek Harness: search workspace files in the composer and attach their path to prompts.

511 stars27 forksJavaScriptMIT

At a glance

What is it?
A DeepSeek Harness plugin that searches your workspace from the composer and attaches a path, not the file contents. It is a path picker with a narrow job, and the README now points new installs elsewhere.
Who is it for?
Adopt dsh-at-file if you already run the DeepSeek Harness web profile and want @-mention path selection without the plugin reading file bodies into your prompts. Skip it for new installations, because the README states the latest official Harness release ships built-in @file and @session references and tells readers to prefer that implementation.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem dsh-at-file solves, and who it is for

Referring to a file in an agent prompt usually means one of two bad options: paste the contents, which spends context on material the agent may never need, or type the path by hand and risk a typo the agent cannot resolve. dsh-at-file sits in the DeepSeek Harness web composer and offers a third route. Typing `@` opens a searchable menu of workspace paths, and the selection becomes a short reference the agent can follow with its own tools.

The audience is narrow by design. This is a plugin for the DeepSeek Harness web interface, installed through the `dsh plugin` command against a profile named `web`. If you drive Harness from a terminal or another client, the package metadata lists a `web` client platform and the README describes composer behaviour, so there is nothing here for you. The repository topics are `dsh` and `dsh-plugin`, which matches that scope.

The README opens with a warning that changes the calculation. The latest official DeepSeek Harness release now includes built-in `@file` and `@session` reference features, and the project says to prefer the official implementation for new installations. The plugin remains available for existing setups and is described as maintained occasionally on a best-effort basis. That is an unusually direct statement from a maintainer, and it should shape how much you invest in configuring it.

How the reference mechanism works

The plugin does not read files. That is the single most important design decision, and the README repeats it in several places. When you pick a path and submit, the plugin confirms the path exists inside the active workspace, then adds a reference message shaped like this:

xml
<workspace-reference path="docs/spec.pdf" kind="file" />

The marker carries the workspace-relative path and whether the entry is a file or a directory. It carries nothing else. The README states plainly that the plugin does not open the referenced file or list the contents of a referenced directory, and that the agent inspects the path with whatever tools the current session provides. A PDF therefore follows exactly the same flow as a text file, because format and size never enter the picture.

This is a reversal of the plugin's earlier behaviour. According to the README, releases before 0.3.0 read file content during submission and enforced file-size limits. If you have notes from an older deployment describing content injection, they describe a version that no longer exists.

Pasted text is treated as plain text by default. An `@path` copied from another application does not open the picker, does not appear in the reference bar, and does not produce a marker. The README attributes this to an Ignore @ mentions in pasted text setting under Settings -> File mentions, which can be turned off to restore the older behaviour. The reference dock renders only tokens present in the current session's settled workspace index, so an `@text` that matches nothing stays ordinary text.

Inside the path picker: ranking, traversal and what gets indexed

The picker is where most of the engineering lives. A plain query matches filenames, with exact names, prefixes and compact matches ranked ahead of looser hits. The README is explicit that letters scattered across a long directory path are not treated as a match, which is the failure mode that makes fuzzy file finders annoying on large trees.

With an empty query the menu favours shallow paths, and directories sort before files at the same depth. The menu holds up to 50 candidates, a cap the README justifies as preventing root-level files from being displaced by deeply nested directories. A query containing `/` matches path segments in order, so `src/view` can find `src/client/view.ts`, and a trailing slash such as `src/` searches within that path.

Keyboard behaviour differs by target. Highlighting a directory and pressing `ArrowRight` enters it: the draft becomes `@path/` with no trailing space and the menu stays open for the next pick. `Enter` and pointer selection finish the directory reference instead. That split is worth knowing before you build muscle memory.

Indexing has its own rules. The default walk skips version-control directories, IDE metadata, dependency trees, caches and build output, covering a long list of toolchains: VS Code, Visual Studio, JetBrains IDEs, Fleet, Eclipse, Android and Gradle, Xcode, CMake, Flutter, .NET, Unity, Unreal, and common JavaScript and Python output directories. OS metadata files `desktop.ini`, `Thumbs.db` and `.DS_Store` are excluded too. Symbolic links are indexed; directory links are traversed through their workspace-relative alias, and links pointing back to an ancestor stay visible without being re-entered, which prevents a loop.

Installing dsh-at-file and making your first reference

The README gives one command, used for both install and update. It targets a profile called `web` and pulls a tagged tarball:

sh
dsh plugin --profile web add https://github.com/omdsh-dev/dsh-at-file/archive/refs/tags/v0.7.0.tar.gz

After it completes, restart `dsh web`. The README says the restart is what causes the Host and the browser client to load version 0.7.0, so skipping it leaves you on whatever was loaded before.

With the interface back up, open the composer and type `@`. You should see a scrollable menu of workspace entries with icons for folders, source files, text, PDFs, images, data and configuration files, archives, and other files. Each row shows the complete filename first with its parent directory underneath. Pick an entry and it stays visible in the draft and in the reference bar, where it can be opened or removed. Submitting a prompt that contains `Review @docs/spec.pdf` should produce the workspace-reference marker rather than the file body.

If you need to change what the index skips, the configuration lives in the selected profile's `cordis.patch.yml`, usually at `~/.dsh/profiles/web/cordis.patch.yml`. The README shows the block in this shape:

yaml
- id: dsh-at-file
  config:
    maxIndexedFiles: 10000

`maxIndexedFiles` caps how many workspace entries are indexed. `ignoreDirs` replaces the built-in directory exclusion list, so setting it to `[]` indexes every directory, and providing any list means you must include every directory name you want excluded. Omitting the key keeps the built-in list. This is a replace-not-merge design, and it is the easiest way to accidentally index `node_modules`.

Where dsh-at-file gets in the way

The biggest limitation is stated by the project itself. The README tells new installations to prefer the official built-in `@file` and `@session` references, and describes the plugin's own maintenance as occasional and best-effort. A last push on 2026-09-01 is recent enough that the repository is not abandoned, but the stated intent matters more than the date. If you are starting fresh, this plugin is a detour.

The second limitation is the reference model. Because the plugin attaches a path and never content, an agent that lacks a file-reading tool in the current session cannot act on the reference at all. In that situation the marker is decoration. You would be better off pasting the file, or using a tool that injects content, and the README does not offer a fallback for this case.

Indexing is also bounded. The picker indexes up to `maxIndexedFiles` entries and caches the index per session for 30 seconds, so a file created seconds ago may not appear until the cache turns over. Filter rules run during the Host index walk, before entries count toward that cap, which means a restrictive filter buys you index headroom rather than just tidier results. On a very large monorepo, a low cap combined with default directory exclusions can hide the file you want with no indication that it was skipped.

Path handling is deliberately strict: the Host accepts workspace-relative paths and ignores absolute paths or paths that escape the workspace. An `@path` token cannot contain whitespace or another `@` character. Filenames with spaces are therefore awkward to reference by typing, though picker selection sidesteps the problem by inserting the token for you.

dsh-at-file compared with pasting file contents

The obvious alternative is not another plugin. It is the behaviour most people already have: copy the file, paste it into the composer, and let the content sit in the prompt. The difference is where the bytes go. Pasting puts the entire file into the conversation immediately, whether or not the agent needs it, and it works with any agent that can read a prompt. dsh-at-file puts a path into the conversation and defers the read to the agent's own tools, which keeps the prompt small but makes the reference useless when no such tool is available.

The other alternative is the official implementation that the README points to. The DeepSeek Harness release now ships built-in `@file` and `@session` references, and the README's recommendation is to use those for new installations. The plugin's own description of its remaining role is compatibility with existing setups. What the README does not do is compare the two feature sets, so anyone migrating from the plugin to the built-in references has no published mapping of settings to settings, or of filter rules to whatever the official version offers.

A third path is simply typing the relative path by hand. It costs nothing to install and cannot break on a Harness client upgrade, but it gives up the ranked search, the directory traversal keys, and the existence check that runs before a step starts.

Maintenance cost, configuration surface and licence

The maintenance picture is mixed and the README is honest about it. Version 0.7.0 supports both the 0.1.1 and 0.1.2 Harness client package layouts, which tells you the plugin has already absorbed at least one client-side change. The same release restores default file ignores for installations that had persisted an empty legacy list, and the README notes that clearing the list again in 0.7.0 remains an explicit choice. If you upgrade and suddenly see build directories in the picker, that restoration is why.

The plugin's `package.json` declares a long list of peer dependencies on `@deepseek-ai` packages, including `@deepseek-ai/cordis` at `^4.0.1-rc.1`, `@deepseek-ai/dsh-agent`, the client runtime and store packages, and several UI packages, plus `react` at `^18.2.0`. That is the real upgrade cost: every Harness client release is a chance that one of those peer ranges drifts. The repository ships tests and a `check` script that runs typecheck, tests and build, which is the kind of thing that makes peer-range drift survivable, but it does not remove the coupling.

Configuration is small and lives in two places. Index options go in the profile's `cordis.patch.yml`. File-name filters live in Settings -> File mentions, split into a Global list shared by every workspace and a per-workspace list that shows the global rules it inherits. Each rule is Exact or Regex, with an independent case-sensitivity toggle that defaults to off. Regex rules run against the complete basename only, not the parent directory or workspace path, which is a meaningful constraint if you were hoping to filter by folder. Invalid expressions are flagged before saving and rejected by the Host. Existing string values in `ignoreFiles` and workspace lists keep working as case-insensitive Exact rules, so older configurations do not need rewriting. Saving a rule clears the affected index cache.

The licence is MIT, which permits commercial use, modification and redistribution with the copyright notice and permission notice preserved. That is a statement about the licence text, not advice about your situation; if you vendor the plugin into a product, have someone qualified check the notice requirements.

Editorial conclusion

Adopt dsh-at-file if you already run the DeepSeek Harness web profile and want @-mention path selection without the plugin reading file bodies into your prompts. Skip it for new installations, because the README states the latest official Harness release ships built-in @file and @session references and tells readers to prefer that implementation. Before installing, confirm your Harness client package layout is 0.1.1 or 0.1.2, since version 0.7.0 is the release that supports both, and check whether your profile's cordis.patch.yml already sets ignoreDirs, because supplying that key replaces the built-in exclusion list rather than extending it.

Frequently asked questions

What does DSH mean in dsh-at-file?

The repository topics are `dsh` and `dsh-plugin`, and the plugin installs into a DeepSeek Harness profile, so DSH stands for DeepSeek Harness. The README does not expand the acronym anywhere.

What is the full meaning of DSH?

The README links to the DeepSeek Harness repository and the package targets the Harness web interface, which is what DSH abbreviates. The README itself never spells out the expansion.

Does dsh-at-file send the contents of the file to the agent?

No. The README states that the plugin does not open the referenced file or list the contents of a referenced directory, and that it adds only a workspace-reference marker containing the relative path and its kind.

How do I install dsh-at-file?

The README gives a single command, `dsh plugin --profile web add https://github.com/omdsh-dev/dsh-at-file/archive/refs/tags/v0.7.0.tar.gz`, followed by a restart of `dsh web` so the Host and browser client load version 0.7.0.

Official sources

  1. FSMargoo/dsh-at-file on GitHub
  2. Issues
  3. License: MIT
  4. README
Community notes

Community notes