syokan
Skill0 starsChanged 19 days agoMITView on GitHub
Build and POST a JSON snapshot envelope to syokan (召喚 — a verb: summon data into a rich, living view). Use when the user says \"syokan this\", \"syokan X\", \"show in syokan\", \"post a snapshot\", \"preview this markdown\", or in Japanese 『〜を syokan』『syokan に出して/表示して/投げて』『snapshot を作って/送って』『syokan のUIで見たい』『Markdown をプレビューして/md ファイルをブラウザで見たい』 — for RSS feeds, in-progress PR reviews, review risk panels, meeting notes, today's TODO, dashboards, or any aggregated data the user wants to see as structured UI. Whenever the word syokan appears, use this skill even if the user does not explicitly say snapshot.
In this repository8 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .agents/skills/brand-assets/AGENTS.mdAGENTS.md
- .agents/skills/coding/AGENTS.mdAGENTS.md
- .agents/skills/brand-assets/CLAUDE.mdCLAUDE.md
- .agents/skills/coding/CLAUDE.mdCLAUDE.md
- CLAUDE.mdCLAUDE.md
- brand-assetsSkill
- codingSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 2 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 20
Leaves cannot have children: only containers (Stack, Card, Checklist, Collapsible) accept children.
- Very specific: line 25
Check the available types and props with syokan catalog (see "Catalog" below).
- Distinctive: line 32
If you have built a similar view before, do not start from scratch — base it on a saved template (see "Templates for reproducibility" …
- Very specific: line 36
Only the following may go in the POST body.
- Very specific: line 37
Never include id, createdAt, or url — the server assigns them.
- Very specific: line 123
Do not rebuild a favorite view from scratch every time — save it as a template in syokan and reuse it.
- Distinctive: line 126
If a matching template exists, do not build from zero: find the id in the list → fetch it → swap in the data → post.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
syokan
syokan (召喚, "summon") is a verb — LLMs summon rich UI. When the user says "syokan X" (JA: 「Xを syokan」), that is a request to summon that data into a view. Under the hood it is a schema-driven view layer: instead of writing JSX, you speak a JSON incantation — a tree of catalog components — and syokan renders it with predefined components. Your job is to assemble the data into an envelope and POST it to syokan. In prose, use syokan as a bare transitive verb (never "do syokan" / never 「syokan する」 — syokan stands on its own).
If syokan is not installed yet (syokan --help fails), or the user says "onboarding", "set it up", or "first time using it", walk them through references/onboarding.md up to their first snapshot. Do not silently run environment-changing operations such as installs: report that it is not installed and get the user's approval before executing (never install on your own).
Non-negotiables
- Snapshots are ephemeral views: only put reconstructible, transient data there (today's RSS, an in-progress review, etc.). Deleting a view archives it rather than destroying it (see "Looking back at past snapshots" below), but the archive is a record, not a place to keep things on purpose. For layouts you reuse, save a template to reproduce them (templates persist — see "Templates for reproducibility" below).
- JSON only — no free-form markdown ingest: the server accepts nothing but a JSON envelope; you can't POST a raw
.mdfile.Markdownis a catalog node like any other, and it is deliberately restricted to prose flow: paragraphs, plain bullet/numbered lists (nested ok), bold/italic/strikethrough, inline code, fenced code, blockquotes, links. Block structure and data still belong to their own node — the server 400s aMarkdownbody containing a heading (useHeading), a GFM table (Table), a task-list item (Checklist), raw HTML, an image, or a non-http(s) link, naming the replacement in the error. A```mermaidfence insideMarkdownrenders as a plain code block, not a diagram — put diagrams in their ownMermaidnode. For anything outside that prose subset, structure it into catalog nodes yourself: headings →Heading, code fences needing their own filename/copy affordance →Code, mermaid fences →Mermaid, preformatted or verbatim text outside prose (raw logs, ASCII tables) →Codewith nolang. - Strict schema: props are validated strictly. Keys not in the schema are rejected — do not invent extra keys.
- Leaves cannot have children: only containers (
Stack,Card,Checklist,Collapsible) accept children; checkchildrenTypesinsyokan catalog. Attaching children to a leaf node is rejected at ingest. - Probes are predefined checks only:
Probe.checkmust be one of the kinds accepted byProbe'scheckprops schema (seesyokan catalog). There is no way to run an arbitrary command from a view — do not try.
From composing to viewing
- Check the available types and props with
syokan catalog(see "Catalog" below). - Map the data you want to show onto those components. The top level is usually a container (
Stacketc.) stacking items vertically. - Turn it into an envelope JSON (see "Envelope shape" below). Only
rootis required. - Post it with the CLI (see "Posting" below). On success the view URL is printed.
Write the view's own text (headings, verdicts, explanations, captions) in the language the user addressed you in. The docs and the catalog are English, but the view is for the reader, and an English panel handed to a Japanese-speaking reader is a defect, not a default.
If you have built a similar view before, do not start from scratch — base it on a saved template (see "Templates for reproducibility" below).
Envelope shape
Only the following may go in the POST body.
Never include id, createdAt, or url — the server assigns them.
{
"root": { "type": "Stack", "props": {}, "children": [ /* catalog nodes; full examples in references/examples.md */ ] }, // required. the view tree
"title": "Today's RSS", // optional. shown in the list and the view header
"schemaVersion": 1, // optional. server fills it in
"idempotencyKey": "rss-2026-06-28" // optional. names this view so it can be refreshed later instead of duplicated
}For daily or recurring views, include something like the date in the idempotencyKey. The syokan CLI handles the rest: it targets that key first, and only creates a new view if none exists yet — so the first post creates the view and every later post with the same key refreshes that same view in place instead of duplicating it. You don't need to track whether it's the first post yourself. (If you call the HTTP API directly instead of the CLI: POST /api/snapshots always creates and tags the key; PUT /api/snapshots targets an existing key and 404s if it's not there yet — there is no create-on-miss endpoint, which is why the CLI tries PUT first and falls back to POST on a 404.)
Catalog
Get the available types and their props definitions from syokan catalog (never transcribe them into md — pull them from here every time).
The output is { "items": [{ "type", "props", "childrenTypes", "notes" }], "envelope": <JSON Schema for the envelope's own keys> }.
props: the type's props as JSON Schema. Satisfyrequired/enum/format(httpUrl isuri,Time.datetimeisdate-time) /additionalProperties:false(unknown keys are rejected) exactly as given.Probe'scheckprops schema is where its predefined check kinds live.childrenTypes:nullmeans a container that accepts children,[]means a leaf that accepts none,[..]means only the listed types may be children.notes: usage contract the props schema can't express (e.g.Checklistpairschildren[i]withitems[i]). Read it before using a type.envelope: the JSON Schema for the envelope's own keys (root/title/schemaVersion/idempotencyKey) — the SSOT for "Envelope shape" above.rootis left opaque there; what may go inside it isitems, so a body is valid only when it satisfies both.
For complete examples combining the components, see references/examples.md.
Spacing (Stack)
Stack spaces its children by nesting depth: the outermost stack separates sections, and each level further in tightens the spacing (deeper than three levels stays at the tightest). Leave gap unset — that default is what keeps views from drifting apart visually. Set it (none / sm / md / lg) only when the depth-derived spacing is wrong for a specific group, e.g. none for a row of items meant to read as one strip. A horizontal Stack scrolls inside itself when its children exceed the width, so lining many up never breaks the page.
Card is not the default container
The default flow is Heading + body nodes inside a Stack; a Heading can carry the id that jump links target. Reach for Card only when a unit needs a visible boundary to be read as one thing — items the reader compares side by side, or a block that must stand apart from the surrounding flow. Wrapping every list item or section in a Card adds borders and padding without adding meaning, and makes long views heavier to scan.
Cross-cutting node field (id)
Besides type / props / children / key, any node may carry id: it makes the node addressable. A Link with href: "#<id>" jumps to it inside the view (revealing it if folded). It is also the identity for UI state — give an id to every Checklist / Collapsible / Probe so checks, folds, and probe reruns survive reloads. An id must be unique tree-wide; a duplicate 400s.
On an id-carrying Checklist, a check on the view is written back into the snapshot itself (PATCH /api/snapshots/:id) — progress survives reloads, shows up on other devices, and lands in published shares. The writeback is a conditional set on the item's checked, identified by label (same-label items by occurrence order), so you may reorder or insert items when you regenerate the tree and checks still land on the item the reader meant — but keep each item's label stable: a rewritten label breaks the correspondence and the reader's writeback is refused. A Checklist without an id keeps device-local checks (viewer's browser only) as before, so an id-less Checklist's progress never reaches the store. For Collapsible folds and Probe re-runs, state lives in the viewer's browser — post the initial state (checked, defaultOpen, result) and let the reader take it from there.
Interactive views (risk panels, TODO, dashboards)
For status/risk panels of any kind (PR review, deploy status, incident dashboards), see references/risk-panel.md, which lists the aspects worth showing and the recommended node for each — the panel structure is yours to decide. A minimal working example is references/examples.md Example 5.
Posting
Pass the assembled envelope as a file or via stdin; on success the view URL is printed to stdout (syokan snapshot.json / cat snapshot.json | syokan / claude -p '…JSON…' | syokan). The pipe form is agent-neutral — any agent that can emit the JSON as text (Codex, pi, Devin, a scheduled script) can post the same way.
For everything else — commands, subcommands, env vars, exit codes — consult syokan --help --json; for types and props, syokan catalog.
Posting a tree file
To iterate on a view from a file, write the catalog tree to a JSON file and syokan the path. A file holding a bare catalog tree ({ "type": ..., "props": ... }, no envelope) is inlined into a self-contained snapshot — title = the file name, idempotencyKey = file:<absolute path> — so re-running the same command updates the same view in place, and an open view follows the update without a reload.
syokan ./dashboard.json # post; edit the file and re-run to update the same viewsyokan <path>accepts JSON only: a file holding an envelope posts the envelope as-is; a bare catalog tree posts inline; anything else (markdown / log / txt / other JSON) is rejected withunsupported_input.- The snapshot holds the file's content at invocation time — nothing references the file afterward. Renaming or moving the file names a new view.
- The same goes for any envelope you post: every view is the stored snapshot, period — updating means PUT/PATCH into the store, never pointing a view at a live file.
To show a local markdown / text file, there is no file viewer: read it and post the result as catalog nodes (see "JSON only — no free-form markdown ingest" above). Prose sections (paragraphs, lists, links, fenced code, blockquotes) can go straight into a Markdown node's body; pull out headings into Heading, GFM tables into Table, and task lists into Checklist first — Markdown rejects those. For raw text, jq --rawfile streams a body in without worrying about JSON escaping.
jq -n --rawfile body app.log \
'{title:"app.log", root:{type:"Code",props:{code:$body}}}' \
| syokanLooking back at past snapshots
Deleting a snapshot (the sidebar's delete, or DELETE /api/snapshots/:id) archives it: it leaves the list and its view shows not-found, but the envelope — including checks the reader wrote back — stays readable. Use this to answer "what did I look at / finish yesterday?" from the store instead of digging through files:
syokan snapshots list --since 2026-06-27 --until 2026-06-27 # active snapshots created that day
syokan snapshots list --archived --since 2026-06-27 --until 2026-06-27 # archived ones (archivedAt set)
syokan snapshots get <id> # full envelope, active or archived — no flag needed--since/--untilare inclusive local calendar days oncreatedAt. Query both the active list and--archivedwhen you need the whole day.- An archived snapshot is read-only. Re-posting with the same
idempotencyKey(e.g. re-runningsyokan ./daily.json) brings it back under the same id/URL with the newly posted content; the archive keeps the old copy, and old checks are not carried over. syokan snapshots purge <id>permanently deletes an archive record — irreversible, and it only works on archived records (an active snapshot must be deleted first). Do not purge unless the user asks for it.
Templates for reproducibility
Do not rebuild a favorite view from scratch every time — save it as a template in syokan and reuse it.
A template is "the saved envelope itself". You may put markers like {{...}} in the skeleton and fill them in yourself.
If a matching template exists, do not build from zero: find the id in the list → fetch it → swap in the data → post. When you produce a new view worth keeping, save it and reproduce it next time. For subcommand syntax (templates list|add|get|rm), consult syokan --help --json.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

