deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:BorisLoveDev/dsh-plugin-ponytail
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
ponytail — "lazy senior dev mode" — as a native DeepSeek Harness plugin.
Upstream ponytail ships adapters for Claude Code, Codex, Cursor, OpenCode, Kiro,
Windsurf and others, and none for DSH: its always-on layer is a UserPromptSubmit
lifecycle hook, which DSH agents do not have. This package rebuilds that layer on
the DSH extension points that do exist, so you get the reference behaviour without
patching upstream and without planting generated files in your repositories.
| Contribution | DSH extension point |
|---|---|
| The always-on rules, recomputed for every prompt | systemPrompt.context() |
The six ponytail* skills, listed only while the mode is on |
skills.registerProvider() |
/ponytail lite\|full\|ultra\|off\|status |
commands.register() |
Nothing is written into your project: no AGENTS.local.md, no symlinks in
.agents/skills. The only artifact is the .ponytail/ directory you already have.
Two other ports already exist, and they cover different slices:
dsh-ponytail (ccll) vendors
@dietrichgebert/ponytail as a dependency, injects the ruleset as a global
system-prompt section (reaching subagents too), adds the six skills as runtime
skills, and detects the "stop ponytail" / "normal mode" deactivation. Global and
per-session.dsh-ponytail-skills
(gongyijie85, repository gongyijie85/dsh-ponytail) ships the six skills inside
the package and registers only a ctx.skills provider. Skills only: it
injects no rules, so the style is adopted when the model chooses to load the
skill rather than being enforced on every prompt..ponytail/.dsh-ponytail |
dsh-ponytail-skills |
this package | |
|---|---|---|---|
| Always-on rules | yes (system-prompt section) | no | yes (runtime context, or a section) |
| Skills | 6, registered at mount | 6, provider from the package | whatever is in .ponytail/skills/ |
/ponytail command |
yes | no | yes |
| Deactivation gesture | yes | no | yes |
| Which projects get it | all | all | only those with a .ponytail/ above the cwd |
| Mode storage | in-process, per session | n/a | .ponytail/state, on disk, per project |
| Mode after resuming a session | back to the default | n/a | preserved |
| Upstream text | required at runtime |
shipped in the package | vendored into .ponytail/ by your own tooling |
| Name/invocation frontmatter rules | n/a | follows the built-in provider | follows the built-in provider |
Ideas borrowed from dsh-ponytail, because they were right: optional per-feature
injection instead of a hard inject (a profile without a command surface must not
lose the rules), loud rejection of unknown config keys, the whole-message
deactivation gesture, a /ponytail default command, and shipped types.
Ideas taken from dsh-ponytail-skills: honouring the built-in provider's
frontmatter contract — the disable-model-invocation / user-invocable invocation
policy and the kebab-case name grammar, so a skill placed in .ponytail/skills/
behaves exactly as it would in .agents/skills/.
Ideas this package contributes: per-project opt-in by walking up from the cwd
(which crosses nested repository roots), mode state on disk so it survives resume
and restart, and systemPrompt.context as the default placement so a level change
does not perturb the system-prompt prefix.
Install any one of them, not two: dsh-ponytail and this package each register a
/ponytail command, and the second registration fails.
If you want ponytail everywhere with no per-project setup, use dsh-ponytail. If
you only want the skills available and are happy for the model to decide when to
use them, dsh-ponytail-skills is the smaller install. If you want to opt in per
project, enforce the rules on every prompt, and keep the mode next to the code,
use this.
dsh plugin --profile web add dsh-plugin-ponytail
The manifest declares dsh.bundle.patch, so the package also joins
dsh.profile.bundles and the loader applies its patch as one more layer. Restart
the profile so the new layer boots.
For a checkout instead of the registry:
dsh plugin --profile web add /path/to/dsh-plugin-ponytail
DSH reads dsh.profile.bundles from the profile's package.json at boot, so a
bundle normally takes effect on the next start. A profile with
patchReload: live does watch its patch files continuously, so a running host can
pick the row up without a restart. Leave the package in dependencies, remove it
from dsh.profile.bundles, and add a pure insert to the profile's own patch layer
(~/.dsh/profiles/web/cordis.patch.yml):
- insert:
- id: ponytail
name: dsh-plugin-ponytail
Keep it out of dsh.profile.bundles while that insert exists.
applyEntryPatches does not deduplicate inserts by id, so the row would mount
twice — once from the bundle patch and once from the profile layer.
The plugin contributes nothing until it finds a .ponytail/ directory. Presence is
the opt-in.
mkdir -p .ponytail/skills
# rules.md — the static rules (upstream AGENTS.md)
# skills/*/SKILL.md — the vendor skills
# state — off | lite | full | ultra
printf 'full\n' > .ponytail/state
Copying upstream's skills/ and AGENTS.md into .ponytail/ is enough:
git clone --depth 1 https://github.com/DietrichGebert/ponytail /tmp/ponytail
mkdir -p .ponytail/skills
cp /tmp/ponytail/AGENTS.md .ponytail/rules.md
cp -R /tmp/ponytail/skills/. .ponytail/skills/
printf 'full\n' > .ponytail/state
Skills you add yourself follow the built-in filesystem provider's contract, so they
behave exactly as they would in .agents/skills/: name must be kebab-case, and
disable-model-invocation: true / user-invocable: false control who may invoke
them. A skill whose name or invocation frontmatter is invalid is skipped rather
than half-registered.
The plugin walks up from the session's working directory until it finds
.ponytail/, and stops at the filesystem root.
That one rule is the whole scoping model, and it behaves differently from a file planted in a single project tree:
.ponytail/. If the
tree holding .ponytail/ contains a checkout that is itself a git repository, a
session started inside that checkout is covered too, because the walk crosses
project roots instead of stopping at the nearest one..ponytail/ above them means no rules and no
skills./ponytail # show the current level, directory and skill count
/ponytail lite # name the lazier alternative in one line
/ponytail full # the ladder enforced (default)
/ponytail ultra # YAGNI extremist, deletion before addition
/ponytail off # withdraw the rules and the skills
/ponytail default lite # persist the user-level default across projects
/ponytail <level> writes .ponytail/state. The rules are recomputed on the next
prompt, so off takes effect immediately and nothing has to be regenerated.
Upstream's whole-message deactivation gesture also works: a message that is exactly
stop ponytail or normal mode switches that project to off. A message that merely
mentions the phrase ("add a normal mode toggle") does not.
/ponytail default <mode> writes upstream's own
$XDG_CONFIG_HOME/ponytail/config.json (or ~/.config/ponytail/config.json,
%APPDATA%\ponytail\config.json), which is the same file the reference adapters
and this plugin's own resolution order read. It is the level used when no
.ponytail/state exists.
The level is resolved exactly as upstream resolves it: PONYTAIL_DEFAULT_MODE,
then defaultMode from that config file, then this row's defaultMode, then
full. A per-project .ponytail/state wins over all of them.
ponytail-review is a skill, not a level; /ponytail review says so.
Upstream's own payload, byte for byte:
PONYTAIL MODE ACTIVE — level: <mode>
<the mode-filtered body of skills/ponytail/SKILL.md>
filterSkillBodyForMode is a faithful port of upstream
hooks/ponytail-instructions.js, including its two subtleties: only the intensity
table rows and the quoted worked examples are level-specific, and an ordinary
rule bullet whose label happens to start with a level word survives verbatim. When
skills/ponytail/SKILL.md is missing, .ponytail/rules.md is used instead.
Verified against upstream on the vendored SKILL.md: identical for lite, full
and ultra, modulo a trailing newline.
The rules are recomputed for every prompt, so it is fair to ask whether that churns the prompt prefix and costs cache hits. Measured:
placement: context is a
durable user-role snapshot, not a system-prompt section. The cacheable prefix —
system prompt and tool schemas — contains no ponytail text.readdirSync, whose order is not
guaranteed, but ctx.skills.snapshot() sorts, and the catalog digest is a hash of
[name, description] pairs only, so neither order nor metadata can trigger a
re-emit.full)
plus six skill-catalog entries (2368 characters, each description capped at 500) —
roughly 2.1k tokens, cached from then on. /ponytail adds nothing to the model
context; commands are human-facing and never enter the prompt.The only thing that moves the text is a change you make:
/ponytail lite|full|ultra (or editing .ponytail/state) changes it once; the
prefix up to that point stays cached, so it is one ordinary cache miss.payload: rules uses rules.md (2590 characters) instead of upstream's
mode-filtered SKILL.md body (5228) for about half the always-on text, at the
cost of the per-level filtering.bash .ponytail/switch on) delivers the rules a
second time as workspace instructions, doubling the text.That last configuration is the one real trap, so the plugin detects it. When an
AGENTS.md, CLAUDE.md, AGENTS.local.md, or CLAUDE.local.md anywhere from the
ponytail root down to the session cwd carries an upstream ponytail marker, the
agent is warned in the prompt, and /ponytail status reports it:
duplicate : /path/to/AGENTS.local.md — rules also arrive as workspace instructions
The warning is its own prompt entry, so a healthy project contributes nothing and
the rules payload stays byte-identical to upstream's. It requires an upstream phrase
(PONYTAIL MODE ACTIVE, "lazy senior dev", "best code is the code never written"),
not merely the word "ponytail", so a project that mentions the name is not flagged.
Set warnOnDuplicateInstructions: false to turn it off.
The row takes an optional config. Every field is optional.
- insert:
- id: ponytail
name: dsh-plugin-ponytail
config:
dirName: .ponytail # directory searched for, upward from the cwd
placement: context # context (default) | section
payload: skill # skill (default, upstream payload) | rules
skills: true # serve .ponytail/skills/
skillRank: 260 # precedence vs the built-in roots (project 100/200, custom 300)
command: true # register /ponytail
commandName: ponytail
contextOrder: 130 # placement after the harness policy contexts (110-120)
contextName: ponytail
defaultMode: full # used when state is absent and upstream resolves nothing
warnOnDuplicateInstructions: true # warn the agent when the rules arrive twice
placement: section registers a system-prompt section instead of a runtime
context. Use it only if you need the rules pinned into the system prompt: it
changes the prompt prefix whenever the level changes, and the default context
placement is the same durable user-role snapshot shape the harness uses for
workspace instructions.
minimal agent preset calls suppressRuntimeContext(), which switches off
every dynamic context in that scope. With the default placement: context the
rules are silent there; use placement: section if you need them on minimal..ponytail/skills/. Keeping that directory
current is upstream's problem, not this package's.If you had ponytail wired through a generated AGENTS.local.md plus symlinks in
.agents/skills/, turn that layer off and leave .ponytail/ in place:
bash .ponytail/switch off # removes AGENTS.local.md and the symlinks
The plugin reads the same .ponytail/rules.md, .ponytail/skills/ and
.ponytail/state, so nothing else has to move. Leaving both layers on would show
the rules twice.
DSH has no first-party plugin registry: dsh plugin forwards to pnpm inside the
profile, so npm is the distribution channel. The community catalog is
DSH Plugin Hub, which indexes plugins by the npm keyword
dsh-plugin and the GitHub topic dsh-plugin.
npm search dsh-plugindsh-find-plugin and search the dsh-plugin topicdsh plugin --profile web add dsh-plugin adds a plugin marketplace
to SettingsTo list a plugin: publish to npm with the dsh-plugin keyword, give the repository
the dsh-plugin topic, then submit it at https://dsh-plugin.org for review.
pnpm install
pnpm test
test/selfcheck.test.mjs drives the plugin against stubs of the three host
registries, so discovery, level resolution, mode filtering, the skills provider and
the /ponytail handler are all exercised without a running harness.
MIT. ponytail itself is a separate project by Dietrich Gebert, under its own license; this package only adapts it.
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。