dsh-sooyo: Combine multiple information sources into a bento homepage

Preface

Creating a personal homepage in DSH usually involves writing a fixed page or using Markdown notes as the home page. The former requires writing frontend code and scraping logic yourself; changing a source requires editing the code again. The latter can only display already organized content and cannot place external information sources into cards.

The dsh-sooyo introduced below takes a different approach: the plugin adds a “sooyo daily” to the sidebar; the page is a bento grid where each cell is a Widget, and each Widget can host different information sources. The maintainer is CaiZongyuan, license MIT, GitHub repository CaiZongyuan/dsh-sooyo currently has 0 stars, it is a client-side plugin.

The problem it solves is: daily information sources (AI news, papers, Product Hunt, YouTube channels) and local tasks, notes, and habits are scattered everywhere. When opening DSH, you can’t see “what to do today, what is worth reading, how the project is progressing.”

One-sentence Positioning

sooyo daily is a composable, local-first personal space: Board holds Widgets, Widgets are instances placed by the user, Sources only provide content.

The model is only this sentence, the rest is its expansion.

Core Design

This plugin splits the interface into three layers to avoid the coupling of “one source corresponds to one fixed card”:

Layer Responsibility
Board Page segmentation, with ready-to-use sections for Overview, Work, Life, and Reading; custom ones can also be created
Widget An instance placed by the user; the same Widget Type can be placed multiple times, each selecting its own source, presentation, and size
Source Only provides Items, plus a “suggestion” for default presentation; does not declare cards

Size is represented by S / M / L / Wide, indicating four information levels, not stretching a single card. Each Widget only declares the sizes it truly supports.

The Subscription Widget type includes five presentations: Image + Text, List, Papers, Products, and Video. Adding a source does not require writing client code.

The card stream (Deck) shows one item at a time and is draggable: swipe right to save for later, swipe left to skip; paper cards can be flipped to view the summary; S size items auto-rotate; arrow keys can also be used.

Items where keywords match the title, summary, one-sentence summary, or recommendation reason will be tagged. With “Follow Priority” sorting enabled, they are moved to the front.

Widget Library

Widget Size Description
Tasks S / M / L Things to do today, directly check off as complete; can filter to view only one Project
Subscription S / M / L / Wide Latest content from one or more sources, optional five presentations and card stream
Quick Record M / Wide Write down an idea in one line, Enter to send to inbox; #note prefix saves as Note
Bookmarks S / M / Wide Quick access to frequently visited websites
Projects S / M / L Progress calculated by task completion rate, no external services connected
Read Later S / M / L Articles saved to read later
Agent Inbox S / M / L Review suggestions given by the background process, approve or reject item by item
Habits S / M Daily check-in, view consecutive days
Focus Timer S / M Pomodoro timer, can be linked to a task, countdown saved by the host
Schedule / Weather / Briefing / Embed — Requires a data source, not yet connected; labeled ‘Coming Soon’, no fake data shown

Built-in Information Sources

Source Default Presentation Cover Source Frequency
AIHOT Selected Image + Text + Rating and Recommendation Reason Original page og:image 10 minutes
AIHOT Hot List List (Multi-source Hot Top 10) None (Numbering is the visual) 30 minutes
HuggingFace Papers Real paper cover + one-sentence summary + keywords + likes/comments HuggingFace CDN or paper image 6 hours
Product Hunt Today Letter logo + one sentence Product page og:image 3 hours
YouTube · Dwarkesh Patel Full episodes 16:9, Shorts vertical shelf YouTube thumbnail 3 hours

The AIHOT and Product Hunt APIs themselves do not carry images. The plugin reads og:image (and twitter:image and JSON-LD) from the item link page. Each page is read only once, only reading the first 160KB before disconnecting, with results permanently cached; pages that fail to load images are noted and not repeatedly requested.

Installation & Enablement

Prerequisites: DeepSeek Harness >=0.2.0-rc.1, Node.js >=20. The plugin itself is version 0.2.0, pure JavaScript, no dependencies in package.json, no build steps.

Install directly from GitHub (Web profile):

dsh plugin --profile web add github:CaiZongyuan/dsh-sooyo

Desktop users can install in “Settings → Plugins”; for local development, you can also point the plugin manager to the current directory.

After installation, restart DSH once. Host plugins are cached by specifier, so changes only take effect in a new process. After restarting and refreshing the page, “sooyo daily” will appear in the sidebar.

Configuration

Configuration is written under config in cordis.patch.yml:

config:
  mode: selected                 # AIHOT: 'selected' is editor's choice, 'all' is all public updates
  sources: []                    # Empty means all enabled; only enable listed source ids
  refreshMinutes: null           # Override the scraping rhythm of all sources
  thumbnailBatch: 6              # Page limit for fetching covers per round, max 20
  sync:
    role: standalone
    tokens: []
    context: true
Field Default Description
mode selected AIHOT takes selected (editor’s choice) or all (all public updates)
sources All Only enable listed source ids
refreshMinutes — Override the scraping rhythm of all sources
thumbnailBatch 6 Page limit for fetching covers per round (max 20)
sync.role standalone standalone / hub / client
sync.tokens / sync.token Environment variable Device token for Hub / Token for Client, only stored on Host side
sync.allowLoopbackOnly true Whether Hub only accepts local connections
sync.context true Whether to inject Sooyo Context during human conversation

Not writing sync defaults to standalone, no need to change old configurations.

Multi-device Sync

Three roles:

Role Who holds data Scrapes sources Suitable for
standalone (default) Local machine Local machine Standalone use
hub Local machine Local machine Constant server, providing a token-protected sync API to the outside
client Hub Does not scrape Laptops, phones, and other devices

Hub configuration:

sync:
  role: hub
  tokens:
    - { token: 'at least 16-char random string', device: macbook, access: write }

Client configuration:

sync:
  role: client
  endpoint: https://sooyo.example.com
  # Suggest using environment variable SOOYO_SYNC_TOKEN for the token

Client will report a clear error if endpoint or token is missing; it will not silently start an empty local database. Backup and migration use the HTTP API:

GET  /sooyo/export                       # Export JSON (excluding scraped items)
POST /sooyo/import                       # Without apply: dry-run, list new/same/conflict/rejected per table
POST /sooyo/import  { apply: true }      # True write; conflicts still not overwritten
POST /sooyo/import  { overwrite: true, apply: true }   # Explicit overwrite

Importing never deletes or overwrites unconfirmed records; rerunning after interruption will not produce duplicate entities.

Agent Tools

The plugin registers several tools, separating read and write:

Tool Read/Write Purpose
sooyo_context_get Read-only Real-time summary of Today/Incomplete/Inbox/Recent Notes/Pending Proposals
sooyo_task_list Read-only Filter tasks by list, completion status, Project
sooyo_task_create Write Create task (can include Origin)
sooyo_task_update Write Update task, must include revision; returns conflict if modified by another device
sooyo_note_capture Write Capture note, source marked as agent
sooyo_inbox_list Read-only View proposals pending approval
sooyo_proposal_create Write Proposal Write a pending approval proposal, does not directly modify data
sooyo_review_run Read-only + Cursor Deterministic entry for background review: first free scan, then ack seen items

Saving Todo does not call any model. Generic tools like sooyo_action that can pass arbitrary command names are intentionally not implemented.

Background Review

Only one DSH Schedule runs on the Hub, time taken from the spec of GET /sooyo/review/schedule. The first step is the deterministic scan of sooyo_review_run: if there are no new or changed items, prompt the model to end this round immediately, producing no content.

Suggestions do not directly modify data but go to the Agent Inbox for human approval. The sync API rejects approval operations, so the model cannot approve its own suggestions. After approval, they are executed item by item; failures are marked as failed, pretending success is avoided.

Adding a Source

Sources only provide Items, suggest a default presentation, layout, and size are determined by the user:

{
  id: 'my-source',
  label: 'My Source',
  cadenceMinutes: 180,
  suggests: { pres: '图文' },
  async load(signal, previous) {
    // Returns { items: [{ nativeId, title, url, publishedAt, summary, score, category, origin }], etag }
  },
}

To disable a source, simply comment out the corresponding item in the SOURCES registry of the package’s SOURCES file; this is the only extension point for information sources.

Outbound & Security

The plugin comes with its own outbound layer: independent rhythm per source, conditional requests (ETag/304), global concurrency limit, retry incrementing by 1/2/4… minutes on failure, one source failing does not affect others.

Third-party text scraped is always treated as data, not executed as commands; every piece of content carries a source and original link. AIHOT explicitly allows personal non-commercial use, the plugin retains attribution and the original link; please also comply with each site’s robots.txt and terms of use.

Use Cases & Notes

Suitable for users already using DSH who want a permanent sidebar personal homepage and are willing to put tasks, notes, read later, and habits into the plugin for unified management. Everything is personal data, residing in the DSH storage domain; Board, layout, tasks, Notes, Read Later, keywords, habits, and Pomodoro timers are all persisted.

The premise is that the plugin runs within the permissions of the current DSH process, can read local configuration and storage, and can fetch sources according to configuration. Before installation, you should open the source code and review it, including cordis.patch.yml, the SOURCES registry, and the built-in tool registration logic; the license is MIT, the repository is public, but the community directory is a separate site with no official affiliation to DeepSeek / Hypothesis, and it is not an official app store.

The repository has 0 stars and 0 forks, it is an early personal project, and the interface and Widget form may be adjusted in the future. The current version 0.2.0 requires DSH >=0.2.0-rc.1.

Summary

What dsh-sooyo does is not complicated: splitting the Board/Widget/Source layers, letting information sources only produce Items, and letting card forms and layout become user data rather than code. Zero dependencies, zero build, install and restart to use; switch to hub/client roles when multi-device support is needed.

Directory Page: https://www.skillhub.cn/plugins/CaiZongyuan/dsh-sooyo
Repository: https://github.com/CaiZongyuan/dsh-sooyo

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye