Back to marketplace

dsh-session-sync

Agent & Workflow

PerryLink/dsh-session-sync

Cross-device session sync for DeepSeek Harness using a dedicated git mirror with append-only conflict resolution, /sync command, and sync tools.

  • cordis
  • cross-device
  • deepseek
  • deepseek-harness
  • dsh
  • dsh-plugin
  • git
  • session
  • session-sync
  • sync
GitHub Stars
20GitHub
Views
4DSH Plugin Hub
Forks
5GitHub
Open issues
2GitHub Issues
Manifest version
0.2.0dsh-session-sync
Latest push
Oct 9, 2026GitHub
License
Apache-2.0JavaScript
Plugin type
HostRuns in the DSH Host

Verification and compatibility

This section shows evidence collected by the catalog. Undeclared information is labeled as unknown.

Static checked
01Exact source: npm · dsh-session-sync@0.2.002Validated: Aug 26, 202603Verified Harness: 0.1.0-rc.7
Current-version compatibility
Verified on the catalog Harness version
Declared Harness range
Not declared
Declared platforms
Not declared
Profiles
web
Build approval
Unknown
Permissions
Not declared
External services
Not declared
Telemetry
Unknown
No known risk flags found

This is not a security endorsement. Review source, permissions, and configuration before installing.

View evidence and scope

Verification covers only the named source, version, and Harness environment. It does not guarantee future compatibility.

  • dsh-session-sync@0.2.0
  • The manifest and static structure passed checks; a runtime load check has not completed.

README

View source

🔄 dsh-session-sync

  • 1024 store channel: npm i -g dsh1024 once, then dsh1024 plugin --profile web add dsh-session-sync (counts toward the deepseek1024.com install ranking). Gitee dshfind OpenSSF Scorecard

Cross-device session sync for DeepSeek Harness — a dedicated git mirror of your session store.

Sync your sessions between devices, keep both sides on any conflict, never lose a turn.

Official repository. This is the only official repository of dsh-session-sync, maintained by PerryLink. Same-name repositories under other accounts are not affiliated.

License DSH plugin dsh-doctor DSH Market Node CI Version npm version npm downloads

English · 简体中文 · Español · Português · हिन्दी


📖 Ecosystem knowledge base — measured data, not marketing: plugin development guide · plugin-selection data · maintenance criteria.

⭐ 如果它帮到了你

这个插件是 DSH 插件家族的一员(40+ 个,全部 Apache-2.0)。如果你在用,给个 star —— 它不会解锁任何功能,但会让下一个人在搜索里更容易找到它。

English: part of a 40+ plugin family for DeepSeek Harness. If it is useful, a star helps the next person find it — nothing is gated behind it.

What is dsh-session-sync?

Cross-device session sync for DeepSeek Harness — a dedicated git mirror of your session store.

Sync your sessions between devices, keep both sides on any conflict, never lose a turn.

Terminal demo of dsh-session-sync: dsh-session-sync — mirror the session store, then /sync

Animated terminal demo of dsh-session-sync

The same run, animated.

Compatibility

SurfaceStatus
HarnessDeepSeek Harness dsh-v0.2.1-alpha.1 (GitHub tag, verified 2026-09-25: full gate chain against the pinned 0.1.7-rc.2 peers). npm dependency line 0.1.7-rc.2, peers `>=0.1.2-rc.1 <0.2.0
Node^22.19.0 || >=24.0.0
PlatformsAnywhere git and DSH run (git-based mirror; no platform-specific code)
ModelText-only models fully supported; no vision or extra model capability required

What you get

dsh-session-sync mirrors your DSH session store into a dedicated git worktree and syncs it to a remote you control — no cloud service, no third-party storage:

  • /sync command — status (branch, sanitized remote, ahead/behind, dirty files, forks), diff, log, pull, push, help.
  • sync_status / sync_pull / sync_push tools — the same surface for the model, inside a turn.
  • Append-only conflict resolution — session logs are append-only; on any divergence the plugin keeps both sides (local version kept, remote version preserved as fork files) and never silently overwrites. Diverged sessions can also fork at the session level.
  • Auto modes — pull on start, push after every closed turn, and periodic pull, all configurable and all reversible.
  • Confirmation-gated writes — pull/push ask first (through userQuestions or approval); read-only surfaces never ask; with no answerer the operation fails closed.
device A                              remote (your git repo)                  device B
$DSH_HOME/sessions ──mirror──▶ commit ──push──▶ [sessions] ──pull──▶ merge (keep-both + fork)

Quick start

dsh plugin --profile web add github:PerryLink/dsh-session-sync
# 1. install the bundle into your profile
dsh plugin --profile web add github:PerryLink/dsh-session-sync

# or from npm (published releases)
dsh plugin --profile web add dsh-session-sync

# 2. point it at a private git remote and verify the row
dsh --profile web --dump-config | grep -A2 'id: session-sync'

Then set the remote in your profile patch (a private repository is the baseline) and sync:

- insert:
    - id: session-sync
      name: dsh-session-sync
      config:
        remote: git@github.com:you/your-dsh-sessions.git
> /sync status
> /sync pull
> /sync push

Install & uninstall

  • git channel (latest main): dsh plugin --profile web add github:PerryLink/dsh-session-sync (equivalent to installing from git+https://github.com/PerryLink/dsh-session-sync.git). No build step — index.mjs and lib/ are the shipped artifacts.
  • npm channel (published releases): dsh plugin --profile web add dsh-session-sync.
  • tarball channel: pnpm pack in this repo, then dsh plugin --profile web add ./dsh-session-sync-<version>.tgz.
  • uninstall: dsh plugin --profile web remove dsh-session-sync (or remove the row from the profile patch).

Configuration

All tunables are Schemastery Config fields (changeable from cordis.yml). An id-targeted override replaces the whole row — restate every key you need. cordis.patch.yml documents each key inline.

KeyDefaultMeaning
enabledtrueMaster switch; false unregisters the command, tools, listeners, and auto modes
backendgitSync backend: git (plaintext mirror) or encrypted (age-encrypted mirror content)
sessionRoot''Session store root; empty = $DSH_HOME/sessions (both missing fails load)
repoDir''Sync worktree root; empty = $DSH_HOME/dsh-session-sync/repo
remote''Remote address (required before pull/push; status/diff work without one)
branchmainRemote branch name
gitBingitgit executable path
ageBinageage executable path (probed for backend: encrypted; missing degrades to plaintext)
ageRecipient''age recipient (public key or identity string); empty = cannot encrypt, degrades to plaintext
ageIdentity''Path to a passphrase-less age secret key for decryption; empty = cannot decrypt, degrades to plaintext
autoPullOnStartfalsePull once when the plugin mounts (config is the grant; no re-confirm)
autoPushOnTurnEndfalsePush after every closed turn
pullIntervalMinutes0Periodic pull every N minutes (0 = off, max 10080)
confirmViaautoConfirmation channel: auto (userQuestions first, then approval), userQuestions, approval
graceMs10000Grace period for git kills (ms)
commandTimeoutMs120000Per-command timeout (ms)
maxOutputBytes262144Per-stream collected-output cap (bytes)
commitNamedsh-session-syncCommit author name
commitEmaildsh-session-sync@localhostCommit author email
registerCommandtrueRegister the /sync command
registerToolstrueRegister the sync_* tools when the tools service is present

Example override in your profile patch:

- insert:
    - id: session-sync
      name: dsh-session-sync
      config:
        remote: git@github.com:you/your-dsh-sessions.git
        branch: main
        autoPushOnTurnEnd: true
        pullIntervalMinutes: 30
        confirmVia: userQuestions

Tools & surfaces

SurfaceRead-onlyNeeds confirmationNotes
/sync status✅—Branch, sanitized remote, ahead/behind, dirty files, fork files, last pull/push
/sync diff✅—Uncommitted changes + HEAD..remote stat (read-only)
/sync log✅—Last commits in the sync repository
/sync pull✅Fetch + merge with keep-both semantics; local kept, remote preserved as forks
/sync push✅Mirror + commit + push; never force-pushes, reconciles and retries once on rejection
sync_status✅—Same facts as /sync status for the model
sync_pull✅Model-callable pull
sync_push✅Model-callable push

Permissions & data

  • Permissions: mutating operations cross the confirmation gate (confirmVia); the plugin never re-implements or bypasses the harness's userQuestions/approval services. Auto modes are covered by the config grant and never re-confirm.
  • Data: sync metadata (device id, last pull/push, last push head, last error) lives in the session-sync storage domain. Session files are copied as opaque bytes — the plugin never parses them. The device id is also written to device.txt in the sync repository for cross-device fork attribution.
  • Session log: sync/push, sync/pull, and sync/conflict are declared in types.d.ts; they are appended only when the host records the types (see Known limitations). Everything written or shown is sanitized. The one durable message the plugin writes — the conflict fork notice — carries the plugin's own producer-owned source kind (dsh-session-sync); the harness retired the shared plugin kind and refuses it when a session is read back.

Security boundaries

  • Never silently overwrite. The append-only three-way merge keeps both sides on any divergence; fork files are never deleted, and git never force-pushes, resets, rebases, or switches branches.
  • Path containment. Files are mirrored as opaque bytes with symlinks refused and every joined path containment-checked (PATH_UNSAFE fails loud).
  • Sanitized output. Remote-URL credentials, tokens, and key=value secrets are redacted before reaching the model or the log; path display refuses anything outside its root.
  • No credential storage. The plugin stores no credentials; git credentials live in your normal git credential helper. age keys are read from paths you configure (ageIdentity); keys never enter the sync repository.
  • Git hardening. Git runs with GIT_TERMINAL_PROMPT=0 and GIT_OPTIONAL_LOCKS=0, deadline- and signal-bounded, with a per-stream output cap.
  • Fail closed. A missing confirmation answerer, a missing remote, or an unsafe path refuses the operation loudly.

Encryption & threat model

backend: encrypted adds an optional age layer above the mirror: session bytes are encrypted into encrypted/**/*.age files before they are committed and pushed, and decrypted back to the local plaintext mirror before merging. The three-way merge always runs on plaintext locally, so the append-only keep-both semantics are unchanged.

What the encryption protects:

  • Mirror content at rest in the remote. The session files you push are age ciphertext; the remote host, its operators, and anyone who clones the repository do not see plaintext session bytes without the private key.

What it does not protect (the boundary):

  • Keys and age identities are yours to manage. The recipient/identity files are never shipped, stored, or rotated by the plugin. If a key leaks, the mirror content it protects is exposed. Use a passphrase-less identity and keep it out of the repository.
  • The remote is still a private repository in practice. git metadata — commit messages, the .gitignore, the encrypted/ path structure, branch names, and push/fetch activity — remains visible to the remote host. Encryption hides the content, not the fact that you sync, nor the shape of your session tree.
  • Plaintext still exists locally. The mirror at <repoDir>/sessions/ is plaintext on disk; encryption protects the transmitted/remote copy, not local disk encryption or the live session store.
  • graceful degradation means plaintext. With backend: encrypted, if age is missing, or ageRecipient/ageIdentity is empty, the plugin falls back to the plaintext git path and warns explicitly in the status/log — it never silently pretends to encrypt. Check /sync status for the warning before trusting the remote as encrypted.

Baseline: with backend: git (the default), session bytes are stored unencrypted in your git remote — use a private repository.

Known limitations

  • Object storage backend reserved. object-storage is an interface placeholder and fails loudly at load; only git and encrypted are implemented.
  • git required. The plugin needs the git executable and the subprocess service; without them, sync operations fail with a clear reason (profiles keep booting).
  • age is optional, external. Encryption depends on the age binary on PATH (or ageBin). No age → plaintext fallback with a warning; a passphrase-protected identity cannot be used (decryption would block on a TTY prompt, so it fails closed).
  • One repoDir per backend. Switching between git and encrypted on the same repoDir is not supported; use a fresh worktree per backend.
  • Session events on 0.1.0-rc.6/0.1.0-rc.8/0.1.1-rc.2/0.1.2-alpha.2/0.1.2-alpha.3/0.1.2-rc.1/0.1.7-alpha.2. The harness does not record sync/* event types, so the session-log appends are skipped (sessions keep loading); the plugin enables them automatically once a host records the types or exposes the ignorable envelope on Session.append.
  • approval between turns. /sync runs between turns, where the approval channel has no open turn to attach to; use confirmVia: userQuestions for command-driven sync, or drive sync through the tools inside a turn. The open-turn check reads the host turnBoundary session projection: a composition without @deepseek-ai/dsh-session-projection cannot verify the turn state and fails closed with that reason.
  • Host-private artifacts stay host-private. session.lock (the harness session lease) and session.migration.*.tmp staging files are never mirrored or deleted — they are runtime state, not syncable content. Session logs (session.jsonl, session.v[1-9]*.jsonl[.zstd]) remain the mirrored payload.

Development

pnpm install                                       # node ^22.19 || >=24
pnpm run typecheck && pnpm run typecheck:ci        # tsc --checkJs against the published 0.1.7-alpha.2 peers
pnpm test                                          # node --test (13 test files; the engine git suite skips without git)
pnpm run verify:self-contained                     # dependency specs resolve from the registry
pnpm run verify:artifacts                          # shipped files present + index.mjs importable
pnpm run check:readmes                             # five-language README consistency
pnpm pack                                          # the published tarball

There is no build step: pure ESM, index.mjs and lib/ are the shipped artifacts.

Topics

dsh, dsh-plugin, deepseek-harness, deepseek, cordis, session-sync, session, git, sync, cross-device

Contributors

  • @PerryLink — creator and maintainer: git mirror engine, append-only keep-both merge, /sync command and sync_* tools, auto modes, sanitizers, and the five-language docs.

PerryLink DSH Plugin Family

This project is one of the 33 actively maintained DeepSeek Harness plugins from PerryLink — the roster is 42, of which 6 are frozen and 3 retired; every one keeps its row below, with the reason in the Status column. If this one helps you, the others likely will too:

PluginOne-linerStatus
dsh-auto-reviewSecond-model auto-review on the approval chain, fail-closed by default
dsh-autotierAutomatic strong/cheap model-tier routing with deterministic risk guards and a /tier command
dsh-background-agentsDurable background child agents with a Web UI sidebar, messaging and interrupt🚫 RETIRED — see the note above
dsh-budgetCost governance for DeepSeek Harness: budgets, carbon, and latency in one panel.🧊 FROZEN — see the repo README
dsh-catalogDSH Desktop Market standard catalog source for the PerryLink family
dsh-cert-mcpRead-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence
dsh-checkpoint-rewindClaude Code /rewind-equivalent: snapshots, session forks, one-shot restore
dsh-claude-moveMigrate Claude Code sessions, memory, skills and CLAUDE.md into DSH🧊 FROZEN — see the repo README
dsh-clickCross-platform native desktop control for DeepSeek Harness — Windows first.
dsh-composer-historyTerminal-style input history for the web composer: arrows, Ctrl+R search
dsh-data-qualityDataset quality checks and citation cross-checks (the optional numeric bridge consumed here)
dsh-defendPrompt-injection, jailbreak, and secret-leak defense for DeepSeek Harness.🧊 FROZEN — see the repo README
dsh-doublecheckEngineering-discipline guard: requirements grill, test gates, adversary review
dsh-drawUnified static-image generation routing for DeepSeek Harness.🧊 FROZEN — see the repo README
dsh-fastRead-only performance diagnostics for DeepSeek Harness.
dsh-fund-researchDeterministic research reports for Chinese public mutual funds
dsh-githubGitHub PR/issues integration for DSH, every write gated by approval
dsh-industry-researchIndustry research orchestration that seals its deliverables through this plugin's ctx.researchReport.assemble
dsh-layaLaya typed decisions (noul/choice/score) as a first-class Cordis service and model-visible tools
dsh-libraryLocal document knowledge base for DeepSeek Harness.
dsh-local-aiLocal-model (Ollama) integration for DeepSeek Harness.
dsh-lsp-actionsLSP diagnostics, formatting, completion, code actions and rename over language servers
dsh-maskPII masking middleware: anonymize at the model boundary, restore at the display layer
dsh-mcp-panelRead-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors
dsh-mementoApproval-gated cross-session memory: ctx.memory seam + SQLite + memory tool🧊 FROZEN — see the repo README
dsh-observeOpenTelemetry and Langfuse observability exporter for DeepSeek Harness.
dsh-output-stylesClaude Code outputStyles-equivalent runtime style switching
dsh-permission-rulesClaude Code-style declarative allow/deny/ask permission rules with audit
dsh-plugin-certificationCommunity certification registry with repro-checkable grades and badges
dsh-plugin-doctorZero-dependency static + sandbox smoke detector for DSH plugins
dsh-plugin-guidePlugin-development knowledge base as an on-demand agent skill
dsh-plugin-kitShared zero-runtime-dependency toolkit for the PerryLink DSH plugins
dsh-plugin-upgradeOne-package, one-corridor-index plugin upgrade skill: routes a repository to the matching closed corridor card
dsh-plugin-upgrade-015Merged 0.1.3-alpha.1 → 0.1.5-rc.1 upgrade corridor card plus a zero-dependency seam scanner🚫 RETIRED — corridors carried by dsh-plugin-upgrade
dsh-reachMulti-channel approval/question bridge: WeChat/Telegram/Feishu, session console🧊 FROZEN — see the repo README
dsh-research-reportVerifiable research-report engine: content-addressed evidence ledger and sealed versions
dsh-scoreMulti-dimensional quality scoring for DeepSeek Harness plugins.
dsh-session-pinPin sessions in the Web sidebar with durable ordering🚫 RETIRED — see the note above
dsh-session-syncCross-device session sync for DeepSeek Harness — a dedicated git mirror of your session store.
dsh-skill-pack-securitySecurity-audit skill pack: secret scan, dependency and supply-chain review
dsh-talkVoice-first session loop for DeepSeek Harness: talk to it, hear it answer.
dsh-team-roomsCross-session team rooms: shared message bus, task board and timeline🚫 RETIRED — see the note above
dsh-test-driveIsolated install-and-smoke test drives for DeepSeek Harness plugins.
dsh-ticktickTickTick/Dida365 task bridge: session-header panel + 11 tools
dsh-translateVendor parameter translation and deterministic JSON repair for DeepSeek Harness.

Install from the DSH Desktop Market

All PerryLink plugins are browsable in the built-in DSH Desktop Market: Market → Sources → add source → paste https://perrylink-dsh-catalog.perrylink.workers.dev/catalog-source.json → select it. Installation still goes through the Market's npm-identity verification and your confirmation.

License

LICENSE (Apache License 2.0) © 2026 dsh-session-sync contributors

Comments

0
Newest first