Introduction

The philosophy of DeepSeek Harness (DSH) is “everything is a plugin.” Once you want an agent to help you move logs or sync files, you can’t avoid remote storage: S3, Xiaomi Galaxy FDS, or a running FTP server. The common approach is to write keys directly into configuration and let the model call command-line tools in the shell—keys enter configuration and session logs, and there is no interception for deletion or overwriting. dsh-webfile addresses this problem: encapsulates three types of storage into 8 agent tools, read operations don’t need approval, change operations request approval one by one, large file transfers run in background tasks and can be cancelled at any time. Below is an introduction to this plugin.

What is it

dsh-webfile is a file plugin for DeepSeek Harness, maintained by modestoma, released under the MIT license. Current package version is 0.0.0, and the Node engine requires ^22.19.0 || >=24.0.0.

It supports three types of storage: S3 (including MinIO and compatible object storage), Xiaomi Galaxy FDS, and FTP/FTPS, providing 8 tools: webfile_list, webfile_stat, webfile_mkdir, webfile_delete, webfile_move, webfile_copy, webfile_download, and webfile_upload. Agents can browse and manage files on these storage backends directly within a session without you having to expose credentials openly.

Core Features

8 Tools: No approval for reads, sequential approval for changes

Among the 8 tools, webfile_list and webfile_stat are pure read-only, and calling them does not require approval; the other 6 (including webfile_download / webfile_upload) are change-type tools, requiring user approval before each call. Refusing an approval results in zero side effects.

The maxEntries for webfile_list defaults to 200 and has an upper limit of 1000; when the result is truncated, truncated: true and nextToken are returned, which can be passed back to continue pagination. nextToken is a passthrough of S3 ContinuationToken / FDS marker; FTP does not have server-side pagination, so retry with a larger maxEntries is required when truncation is encountered.

Change-type tools have two layers of default protection:

  1. webfile_move / webfile_copy / webfile_upload have overwrite defaulting to false, reporting WEBBUF_EXISTS if the target already exists;
  2. webfile_delete reports WEBBUF_DIR_NOT_EMPTY when encountering a non-empty directory; only by explicitly passing recursive: true will the entire subtree be deleted.

Transfers run in background tasks, cancellable at any time

webfile_download / webfile_upload run in background tasks, with progress flowing into the Jobs panel, and can be cancelled at any time. When cancelled, the stream is aborted, local partial files are deleted, and the task is marked as killed.

There is an upper limit check before transfer: maxTransferBytes defaults to 2 GiB, and exceeding this reports WEBBUF_TOO_LARGE with zero remote side effects. For large file uploads on S3/FDS, when the size reaches multipartThresholdBytes (default 64 MiB), multipart upload is used.

Credentials configured by reference name, keys don’t enter session

Only the credential reference name (i.e., the environment variable name) is written in the configuration; the key value does not enter the configuration or session logs; after rotating keys, the next call takes effect. The priority consists of four layers from high to low: Process Environment > Credential File > Project .env > User .env.

The credential file is $DSH_HOME/.credentials.yaml, with 100ms debounce hot reload, and takes effect on the next call after external editing.

Directories are synthetic: S3/FDS have no real directories

S3 and FDS have no real directories; a directory is just an aggregation of key prefixes: webfile_mkdir actually writes a zero-byte key/ marker object; webfile_stat synthesizes a directory result for prefixes that have child objects. Understanding this helps avoid misjudgment during directory-related operations.

Installation and Usage

  1. Install the plugin:
dsh plugin --profile <name> add dsh-webfile

The package declares dsh.bundle, so it automatically mounts to the profile layer stack during installation, requiring no manual mounting line.

  1. Subsequent upgrades:
dsh plugin --profile <name> update

Typical Configuration

After the steps above, the plugin is mounted to the profile layer stack; next, configure the connections.

Override plugin configuration by id

First, locate id: dsh-webfile in the profile’s $DSH_HOME/profiles/<name>/cordis.patch.yml, then write a config override. Below is an example defining S3, FTP, and FDS connections:

- id: dsh-webfile
  config:
    connections:
      prod-logs:
        protocol: s3
        endpoint: https://oss.example.com   # Custom endpoint (MinIO, etc.); omit for AWS public cloud
        region: cn-north-1
        bucket: prod-logs
        pathStyle: true                     # Required for MinIO
        accessKeyRef: OSS_ACCESS_KEY
        secretKeyRef: OSS_SECRET_KEY
      legacy-ftp:
        protocol: ftp
        host: ftp.example.com
        port: 21                            # Default 21; implicit FTPS uses 990
        userRef: FTP_USER
        passwordRef: FTP_PASSWORD
        tls: explicit                       # none | explicit | implicit, required
      mi-fds:
        protocol: fds
        endpoint: https://cnbj2.fds.api.xiaomi.com
        bucket: mi-bucket
        accessKeyRef: FDS_ACCESS_KEY        # FDS has no env credential chain, ak/sk required
        secretKeyRef: FDS_SECRET_KEY
    maxTransferBytes: 2147483648            # Single file transfer limit, default 2 GiB
    multipartThresholdBytes: 67108864       # S3/FDS multipart threshold, default 64 MiB

Note the protocol differences: FDS has no environment credential chain, so accessKeyRef / secretKeyRef are required; FTP only supports passive mode (passive defaults to true), and tls is required.

Credentials File

The accessKeyRef in connections is just a reference name; the key values are written in $DSH_HOME/.credentials.yaml. The format is a strict reference: string value mapping (not dotenv syntax), the value must be non-empty, and file permissions must be 0600:

OSS_ACCESS_KEY: AKIAxxxxxxxx
OSS_SECRET_KEY: xxxxxxxxxxxx
FDS_ACCESS_KEY: your FDS access key
FDS_SECRET_KEY: your FDS secret key
FTP_USER: logbot
FTP_PASSWORD: xxxxxxxx

Patch Semantics and Hot Reload

When overriding configuration by id, three semantic rules must be known:

  1. Patch lines without an id will be skipped with a warning;
  2. config performs a shallow replacement of the entire value, and omitted fields fall back to schema defaults;
  3. Do not re-mount by inserting a line with the same name in the user layer; override uniformly by id.

To temporarily disable the plugin, simply set the corresponding patch line to disabled: true:

- id: dsh-webfile
  disabled: true

The configuration supports hot reload: after saving cordis.patch.yml, the patch is replayed transactionally via HMR, and a restart is not required.

Use Cases and Notes

Suitable scenarios: you need to let the DSH agent browse and move S3 / FDS / FTP files within a session while being concerned about key exposure and accidental operations—no approval for reads, sequential approval for changes, and cancellable transfers; this gating is designed for this purpose.

Notes before use:

  1. The plugin runs with the permissions of the current dsh process; please check the source code and license before installing (this project is MIT);
  2. Credential file permissions must be set to 0600;
  3. webfile_list returns a maximum of 1000 entries per time; retry with a larger maxEntries on truncation for FTP;
  4. The default values for change operations are conservative (overwrite: false, recursive: false); you must explicitly pass parameters if you need to overwrite or recurse.

Conclusion

What dsh-webfile does is not complex: wrapping S3, FDS, and FTP into 8 tools, using approval gating and credential references to contain risks, and using background tasks to make large file transfers controllable and stoppable. If your DSH workflow involves remote file operations, it is worth a try.

  • Plugin Directory Page: https://www.skillhub.cn/plugins/modestoma/dsh-webfile
  • GitHub Repository: https://github.com/modestoma/dsh-webfile

Note: The directory page is from the community plugin directory, which operates independently and has no official affiliation with DeepSeek / Xiaofang.