本文へ移動
cccskills
無料GitHub で公開

surface

How a downstream app consumes the shared @kolu/surface stack (@kolu/surface · surface-app · surface-nix-host · surface-mcp) — declaring a typed reactive surface, serving it, consuming it (SolidJS hooks or a CLI), and mirroring a remote surface over ssh. Grounded in the real consumers: kolu, pulam-web, drishti, odu, and the TUIs. Load when wiring a surface server/client/mirror, or reaching for getHostSession / a link / the `.use()` hooks. CHANGING the framework is gated separately — `.claude/rules/surface.md` (a paired, CI-green drishti PR pinned to final kolu HEAD).

インストール方法を見る

含まれるファイル(1)

  • SKILL.md6.1 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Using @kolu/surface (downstream consumer guide)

Declare a typed reactive surface once; the framework derives the oRPC contract, wires the server, and binds the Solid client hooks. This is the consumer guide — changing the framework needs a paired drishti PR (.claude/rules/surface.md).

Who uses it — match the closest consumer, don't hand-roll

ConsumerShapeNotable
kolu (client+server)one browser ⇄ one Node server, ONE wssingle-tier; two sibling surfaces; uses surface+surface-app only (not -nix-host)
pulam-webbrowser ⇄ Node ⇄ ssh fleet mirrorone ws per host (/rpc/ws?host=); connectSurface; re-serves terminalWorkspaceSurface
drishti (srid/drishti)browser ⇄ Node ⇄ ssh agent mirrorthe canonical twin; 3 workspaces (common/agent/app)
odu (juspay/odu)CI runner: stdio lanes → unix-socket fan-in → CLI/MCPserve+consume+mirror over every transport at once; surface-mcp projection
pulam-tui / kaval-tuione-shot CLI/TUI, no browsertransport-blind {client,dispose}; unix-socket local, ssh remote; no .use() hooks

The spine (real import paths)

  • Define — defineSurface({cells,collections,streams,events,procedures}) (@kolu/surface/define). Many surfaces over one transport: composeSurfaceContracts(map) + sibling clients, never merged.
  • Serve — implementSurface(surface, deps) / implementSurfaces(map, fwDeps, perKeyDeps) (@kolu/surface/server; inMemoryStore / inMemoryChannelByName back the cells/channels). Always flatten before serving: implement(surface.contract).router({ ...fragment.router }) — else oRPC double-prefixes /surface/surface/… and every call 404s.
  • Consume (SolidJS) — surfaceClient(surface, link) / surfaceClients(link, map) (@kolu/surface/solid) → client.cells.X.use({authority,initial,onError}), .collections.X.use({keys,onError}) then .byKey(id)?.() / .keys(), .streams.X.use(inputFn,{onError}) with .pending()/.error(), .events.X.use(inputFn,handler).
  • Consume (CLI/TUI) — no reactive hooks; raw awaited conn.client.surface.<verb>(…) + async-iterator iteration; a live board uses mirrorRemoteSurface(spec, client, {collections,streams}, {log}) (@kolu/surface/mirror) into plain callbacks.

Links (transport, swappable)

websocketLink(ws) (/links/websocket) · stdioLink (/links/stdio) · unixSocketLink({socketPath}) (/links/unix-socket) · directLink(router) (/links/direct, in-process identity, for tests). Serve side: serveOverStdio (/peer-server), serveOverUnixSocket (/unix-socket), oRPC RPCHandler (@orpc/server/ws, .upgrade(ws)) for browsers. CLIs keep ONE transport-blind Connection = {client, dispose} so every command is written once across local vs ssh.

Mirror a remote surface (drishti / pulam-web / odu)

  1. Dial the host — getHostSession<contract>({host, binary, resolveDrvPath}) (@kolu/surface-nix-host): long-lived, nix copys the agent closure, runs <bin> --stdio over ssh, reconnects. buildHostRegistry fans out N hosts; one-shot CLIs use dialAgentOnce instead.
  2. Mirror inward — pumpRemoteSurface({source, session, makeSink, …}) (-nix-host) folds the remote agent's frames into a local implementSurface re-serve via a SurfaceSink (makeSink, @kolu/surface/mirror). The parent implements the same surface; a remotely-unobservable cell (e.g. connection state) is parent-authoritative.
  3. Re-serve — the local fragment served on /rpc/ws, accepted via acceptSurfaceSocket (@kolu/surface-app/server). Browsers connect with connectSurface (@kolu/surface-app/solid), which bundles socket + websocketLink + surfaceClient + a default-on liveness heartbeat.

Gotchas (hard-won, all real)

  • Procedures call off the FULL link, not the scoped client — surfaceClients per-key .rpc is typed unknown; reach the root link for raw procedures.
  • Raw streaming — unenrolledStreamCall(client.X, input, {signal, onRetry}) (@kolu/surface/client) carries the reconnect (STREAM_RETRY) context; a bare client.X(…) silently loses it. There is no stream namespace (.claude/rules/streaming.md is stale on that point).
  • Consume streams fine-grained — value-bearing → .streams.use() (replace-each-frame); delta-accumulate → mirrorRemoteSurface / createSubscription+reduce. Never coarse-read-and-copy: same-shape frames coalesce and the view freezes.
  • Snapshot-then-deltas + fail-fast — a cell always opens with a snapshot; firstFrameOrThrow (@kolu/surface/first-frame) treats an empty stream as a link failure, never a silent empty.
  • Liveness is on by construction — framework-reserved surface.system.live; connectSurface / HostSession / createServerLifecycle default their watchdog to it (probeSurfaceLive). Don't nominate your own probe unless you mean to (pulam-tui's version-cell probe is the rare, deliberate exception).
  • Version skew — gate on isContractVersionCompatible (major.minor), never a string ==.
  • Nix-baked deps — odu declares no @kolu/* in package.json; they're symlinked at Nix build (the bake-in-via-Nix convention). A bare pnpm install won't resolve them.

Reference

Runnable end-to-end: packages/surface/example/ (its mini-ci stdio example is odu's seed). Full API + rationale: each package's README.md. Match the closest consumer above; don't reinvent a primitive the table already shows how to use.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

be

無料

Modern, interactive alternative to `/do` — clarify intent up front, then take a task end-to-end with a serial AI review gauntlet (lens debate (lowy ⇄ hickey) → codex debate → simplify → code-police, each editing the branch in turn) → CI → evidence. ONLY invoke when the user explicitly types `/be` or `$be`; never auto-select from a natural-language request.

日本語の概要は準備中です。原文の説明を表示しています。

srid/emanote9632026年7月26日 更新

be-review

無料

Run /be's review gauntlet SERIALLY — /lens-debate (lowy ⇄ hickey), then /codex-debate, then /simplify, then code-police, each editing and committing on the live branch in turn. Use from /be §4, or when the user asks to "run the review gauntlet". Requires Claude Code's Skill tool.

日本語の概要は準備中です。原文の説明を表示しています。

srid/emanote9632026年7月26日 更新

ci

無料

Reference for the `odu` runner — how to invoke a full pipeline, a single recipe, or a platform-pinned node, and how to attach to a live run, from a project whose CI odu runs. Trigger when the user asks to "run CI", "run the pipeline", "re-run a check", to run named lanes or recipes (e.g. "run fmt and nix", "just the e2e lane", bare selectors like `fmt`/`nix`/`e2e`), or names a recipe by `<recipe>@<platform>`. This skill — not a repo's local `just ci` / `just <recipe>` — is how an odu-run request is served.

日本語の概要は準備中です。原文の説明を表示しています。

srid/emanote9632026年7月26日 更新

Review code for quality, simplicity, and common mistakes before declaring work complete.

日本語の概要は準備中です。原文の説明を表示しています。

srid/emanote9632026年7月26日 更新

Run an automated codex⇄Claude debate to consensus — no round cap, no deadlock exit. Two explicit subcommands. `review` (also the bare/back-compat default) — codex (reviewer) critiques the current diff and a Claude subagent (author) fixes/disputes, looping until they agree. `answer` — Claude and codex each answer a freeform prompt in parallel, then cross-check until they agree, and a unified answer is returned. Use when the user types `/codex-debate`, asks to "have codex review this", "run the codex debate", "review this PR with codex", "argue this with codex until you agree", or passes a question to "have Claude and codex debate/answer until they agree".

日本語の概要は準備中です。原文の説明を表示しています。

srid/emanote9632026年7月26日 更新

do

無料

Do a task end-to-end — implement, PR, CI loop, ship. ONLY invoke when the user explicitly types `/do` or `$do`; never auto-select from a natural-language request, even one that sounds like an end-to-end task.

日本語の概要は準備中です。原文の説明を表示しています。

srid/emanote9632026年7月26日 更新

srid のスキルをすべて見る

このスキルの問題を報告する