deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
Neofetch for DeepSeek Harness.
English | 简体中文
A DeepSeek Harness (dsh) plugin that injects a neofetch-style device info block into every brand-new session — OS distro, kernel, architecture, hostname, CPU, memory, uptime, timezone, locale, shell/terminal, and Node version. It is injected exactly once, when a new session takes its first step, and then persists in that session's own history; existing sessions are completely untouched.
| Scenario | Behavior |
|---|---|
| Brand-new session (first message after creation) | a device-info user message is injected; the model sees it at the start of the conversation and it persists until compaction |
| Existing sessions (created before a restart, resumed, or continued) | the system prompt is byte-identical and no message is appended — the request prefix and its KV cache are fully preserved |
| Later steps of the same session | never re-injected (the message is already durable history) |
| Subagent sessions (ephemeral workers spawned by the subagent/workflow tools) | skipped by default (avoids repeating per fan-out); opt in with includeSubagents: true |
Install into a dsh profile (once published, by package name):
dsh plugin --profile web add "@gausszhou/dsh-where-am-i"
For local development use a link dependency (same pattern as
dsh-opencode-session-id): add "@gausszhou/dsh-where-am-i": "link:/home/gauss/Code/gausszhou/dsh-where-am-i" to
~/.dsh/profiles/web/package.json dependencies and list it in
dsh.profile.bundles; the plugin's own cordis.patch.yml (via
dsh.bundle.patch) performs the insert.
After installing, restart dsh web (systemctl --user restart dsh-web) so
the bundle takes effect. Zero configuration needed.
System info (the machine this dsh session runs on; sampled at session start):
host: gauss-KP
user: gauss
os: Ubuntu 26.04 LTS
kernel: 7.0.0-29-generic
arch: x86_64
cpu: 6 × Intel(R) Core(TM) i5-8400 CPU @ 2.80GHz
memory: 7.9 GiB used / 15.0 GiB total
uptime: 1d 4h 3m
timezone: Asia/Shanghai (GMT+08:00)
locale: zh_CN.UTF-8
shell: /bin/bash
term: dumb
node: v24.19.0
All options are optional, with the defaults shown:
| Key | Default | Meaning |
|---|---|---|
fields |
all 13 | emit only the listed field lines, in the default order, e.g. [os, arch, timezone]; unknown names are dropped; an empty-after-filter list falls back to all |
includeSubagents |
false |
when true, also inject into subagent sessions (skipped by default to avoid repeating per fan-out) |
verbose |
false |
print the injected snapshot to stdout (visible via journalctl -u dsh-web on a web deployment) |
Field list (emission order): host user os kernel arch cpu
memory uptime timezone locale shell term node. Fields that
cannot be sampled (e.g. shell on Windows without a SHELL variable) are
omitted automatically.
# ~/.dsh/profiles/web/cordis.patch.yml
- id: where-am-i
config:
fields: [os, kernel, arch, cpu, memory, timezone]
Before implementing, the existing prompt surface was surveyed
(dsh-system-prompt section/variable registration, dsh-agent-loop variable
providers, the runtime-context packages). Existing facts are listed below;
this plugin only fills the gaps and never duplicates:
| Existing fact | Source | Location |
|---|---|---|
You are an AI agent powered by DeepSeek Harness. |
dsh-system-prompt |
system prompt section harness:identity, order −100 |
| DSH source checkout path | dsh-app-boot / dsh-web-app |
section harness:source, order −99 |
| Web GUI URL | dsh-web-app (web profile only) |
section app:web-surface, order −98 |
| Deployment persona | config | section deployment:persona, order 0 |
| Tool guidance (read/write/edit/bash/web_search…) | each dsh-tool-* |
sections tool:*, orders 100–199 |
{{provider}} {{model}} {{cwd}} (session cwd, evaluated per assembly) |
dsh-agent-loop |
prompt variables |
| File sandbox policy, approval policy | dsh-sandbox-policy / dsh-user-approval |
runtime context (user-role snapshots) |
| Timestamp + browser timezone + elapsed duration | dsh-time-context (not enabled in the default composition) |
runtime context |
| tmux session/window/pane location | dsh-tmux-context (not in the web composition) |
runtime context |
AGENTS.md / CLAUDE.md workspace instructions |
dsh-agent-instructions |
durable user message |
Completely missing (what this plugin adds): OS/distro name, kernel release, CPU architecture, hostname, CPU model and core count, total/free memory, uptime, host locale, shell/terminal, Node version, and the host process timezone.
cwd — already provided live by the {{cwd}} prompt variable, and the
harness explicitly warns against inferring it from the checkout path.dsh-time-context per request when
enabled.The first version contributed a systemPrompt.section(), but that renders on
every step of every session once mounted — it can never be "once", and it
rewrites the shared system-prompt prefix of already-running sessions (KV
cache invalidated from the first changed token).
The current implementation uses the same seam as dsh-time-context /
dsh-tmux-context: a prepended agent/pre-step waterfall listener that
first delegates downstream (await next()) and, only when the step enters,
appends one durable, source-attributed user message to the batch. The
agent loop persists every message in the batch
(session.append("user/message", …)) after step/start, so:
"Brand-new session" is decided from the session log alone: at pre-step time,
agent.session.events holds no user/message, assistant/message, or
tool/result event yet (the in-flight prompt of step 1 is persisted only
after the step enters — dsh-time-context's README states this explicitly).
Any resumed, continued, or already-injected session has at least one such
event and is skipped, forever. A batch with no user-sourced message at all
(plugin-only runtime-context or scheduled turns) is also never injected into.
Device facts are sampled at injection time (the new session's first step), so uptime/memory are as fresh as possible; the message is per-session history, so byte-level differences between sessions cost nothing.
renderPrompt output
for existing sessions is identical to before installation (asserted by the
integration test).sw_vers, no uname — everything comes from
node:os, one synchronous /etc/os-release read (Linux/WSL: PRETTY_NAME,
falling back to ID VERSION_ID), and Intl.x64→x86_64,
arm64→aarch64, ia32→i386, arm→armv7l.dsh-time-context's browser zone.assertMessageEventShape: non-empty id, role: "user", source.kind,
content array); its source mirrors time-context's plugin-snapshot shape
({ kind: 'plugin', plugin: 'where-am-i', form: 'snapshot', sections: [...] })
so UI/trajectory attribution is consistent.inject: ["agents"] (same as time-context): the plugin does not load in a
tree without the agents registry.node test/verify.mjs # unit: os-release parsing / arch mapping / macOS naming / byte & uptime formatting / timezone offset / config normalization / render subset / decision gates (user source, history, subagent) / message shape / no-cwd-no-date invariants + real-machine snapshot
node test/smoke-apply.mjs # wiring: new session injects once, existing session zero injection, same session never re-injects, no-user-source batches skipped, reject/abort passthrough, subagent gate, fields subset
node test/integration-real.mjs # real cordis + dsh-system-prompt + dsh-session: system prompt untouched, injected message persisted by a real Session and visible in derived history, no re-injection
/etc/os-release on non-Windows/macOS systems, the os line falls
back to os.version()/os.type() and may be less friendly than a distro
name.user line is not redacted — the model can see the local username
running dsh (like neofetch). Drop user/host via fields if you care
about privacy.CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。