Agent Skills › arcships/rutis › rutis-new-runtime

rutis-new-runtime

GitHub

指导在rutis框架中新增插件语言或平台运行时,涵盖设计决策、SDK开发及合规性检查。

.agents/skills/rutis-new-runtime/SKILL.md arcships/rutis

Trigger Scenarios

添加新的插件语言支持 编写新的leaf SDK 使现有运行时支持远程调用

Install

npx skills add arcships/rutis --skill rutis-new-runtime -g -y
More Options

Non-standard path

npx skills add https://github.com/arcships/rutis/tree/main/.agents/skills/rutis-new-runtime -g -y

Use without installing

npx skills use arcships/rutis@rutis-new-runtime

指定 Agent (Claude Code)

npx skills add arcships/rutis --skill rutis-new-runtime -a claude-code -g -y

安装 repo 全部 skill

npx skills add arcships/rutis --all -g -y

预览 repo 内 skill

npx skills add arcships/rutis --list

SKILL.md

Frontmatter
{
    "name": "rutis-new-runtime",
    "description": "Use when adding support for a new plugin language or platform to rutis — \"add a runtime\", \"support Kotlin\/Swift\/Ruby\/… plugins\", writing a new leaf SDK, or making an existing runtime work remotely. Covers whether to do it at all, the design doc, the framework constraints, the decisions every runtime must state (artifact model, reentrancy and capabilities, channels, method enumeration, distribution), the runtime contract, and the checklist of places in the rutis repository a runtime touches, based on how Bun and Go were added. Self-contained; reference material is in references\/."
}

Adding a language runtime to rutis

rutis (https://github.com/arcships/rutis) has a Rust core; plugins in other languages connect through runtimes. This skill does not depend on the rutis documentation; everything it refers to is in references/:

File Contents
references/principles.md rutis design principles and how to decide whether a capability belongs
references/plugin-api.md The plugin API shared by all languages (what plugin authors see)
references/runtime-contract.md What a runtime implements: frames and channels, handshake and capabilities, mount, control operations, values, manifests, conformance tests

The key idea: the rutis paradigm (dependency gating, lifecycle, configuration reconciliation) is implemented once, in the Rust core. A runtime and its SDK are a thin leaf layer that only connects one language's plugins. If you find yourself implementing the paradigm again in the new language, you are going the wrong way.

0. Decide whether to do it

Using the criteria in references/principles.md:

  • What ecosystem does it bring? A runtime is added for an ecosystem, not to have one more language.
  • Is there a concrete user? If not, wait — Go and the desktop Kotlin/JVM runtime were both "when there is a need".
  • Does an existing runtime already cover it? (TS plugins already run on Node and Bun.)

1. Design doc first, code second

2. Framework constraints

Constraint Meaning
Leaf plugins The SDK offers only define (inject, optional provides with method shapes, config schema, apply; an undeclared ctx.provide is announced with its public methods, all async: rows.announce in the contract), ctx.use / ctx.provide / ctx.effect / ctx.on / ctx.emit, cancellation and errors. No child plugins, event trees or local dependency graphs
rutis drives The runtime does not decide whether dependencies are met, start order or restart policy; every inject is gated by rutis (feature leaf)
One plugin API Matches references/plugin-api.md: declarations, ctx, lifecycle, cleanup order, deadline, value rules, plugin API version (currently 2)
Platform-language implementation The runtime and SDK are written entirely in that language, with no Rust dependency (no FFI or native extension bridging to rutis)
Both directions Local channels are required; for remote use implement both listen: and dial:
Stay out of business logic Platform foreground/background, devices, identity and storage do not belong in a runtime
Tests are the contract Pass the Rust-side conformance tests in the rutis repository, not just your own unit tests

3. Decisions every runtime must state

Decision Options and how to choose
Artifact model Load by name: one runtime process loads several installed packages (Node, Bun, Python); rows are <prefix>:<module>. Compiled program: plugins are built into an executable that describes itself with --rutis-manifest and is started on demand (Go; Swift on macOS reuses this machinery). App hosting: plugins are built into an app that connects to rutis (Swift / Kotlin apps)
Row prefix Must not collide with existing ones: py, bun, go, swift, kt, …
Execution model One execution unit per incoming call (thread, goroutine, Task, virtual thread) makes the runtime reentrant; the reader thread only parses frames and never runs plugin code
Capabilities Declare sync-wait, reentrant-sync, sync-stack, objects honestly, per references/runtime-contract.md §2. A new runtime should declare sync-wait; otherwise it is outside wait-cycle detection
Channels Local: fd:3, dialing back to a socket path, tcp:127.0.0.1:<port> (used on Windows); dial back when the language cannot take an inherited fd. Remote: listen:wss:// and dial:wss://
Method enumeration and schema Derive them where the language has reflection (Go, Python); otherwise use an explicit method table and a hand-written schema (Swift, Kotlin)
Distribution The language's standard package channel (npm, PyPI, Go modules, SwiftPM, Maven Central); versions follow the rutis release train

4. The runtime contract

All of it is in references/runtime-contract.md. The fastest way to get the behavior right is to read an existing implementation alongside it:

5. What changes in the rutis repository

Compiled from the files Bun (arcships/rutis#200) and Go (arcships/rutis#227) actually changed.

Language side

  • <language>/…: session layer, SDK, runtime entry point, host-free test helper (like Go's rutistest, Python's rutis.testing)
  • A conformance entry point for the Rust tests to start

rutis-bridge

  • src/runtime/process.rs: Launcher::<language> (command, working directory, how the channel is handed over)
  • src/runtime/local.rs: LocalRuntime::<language> and the runtime name
  • src/runtime/mod.rs; a feature in Cargo.toml
  • Tests: tests/runtime_conformance.rs, tests/session_matrix.rs, tests/<language>_runtime.rs; for remote use tests/websocket_conformance.rs (and dial_conformance.rs for dialing out)

rutis-loader

  • Load by name: src/runtime.rs (RuntimeResolver). Compiled program: src/runtime/<language>.rs, reusing Go's manifest machinery
  • src/lib.rs; a feature in Cargo.toml
  • Tests: tests/<language>_rows.rs, tests/multilang_<language>.rs, tests/instance_<language>.rs, tests/leases.rs

rutis-host Every local language is one entry in a registry (arcships/rutis#230): config.rs, host.rs, new.rs, project.rs and main.rs loop over it and need no edit. Read https://github.com/arcships/rutis/tree/main/crates/rutis-host/src/languages first: node.rs (load by name) or go.rs (compiled program).

  • src/config.rs: a runtimes.<language> field in Runtimes and its settings type (this is the rutis.json format; the persisted-fixture tests guard it)
  • src/languages/<language>.rs: one type implementing the Language trait: its runtimes key; rebase/merge of its settings; the names it takes as runtimes.remote[].language and how its rows are named (rows); runtime, which finds the package or interpreter, runs the preflight check of its version and builds the LocalRuntime (a compiled-program language with one runtime per binary overrides start instead, as Go does); new --lang names, template and next steps; dev: how a project is recognized (is_project, project_file) and the rows that run it (the host never compiles; it only runs the project's own build)
  • src/languages/mod.rs: its mod line and its line in LANGUAGES (the order messages list languages in; the host starts them in reverse, so Node, whose resolver takes bare npm names, stays first)
  • src/main.rs: only the USAGE help text names the languages. A compiled-program language that rebuilds in dev or lists its binaries in check follows Go there (host.go, project::GoDev)
  • templates/<language>/: plugin, tests, rutis.dev.json, publish workflow

Release and CI

  • .github/workflows/ci.yml: a runtimes-<language> job; release.yml
  • scripts/train.mjs: version file and package coordinates

Documentation (both .md and .en.md)

  • docs/guide/<language>-plugin.md; a column in docs/guide/plugin-api.md; docs/guide/rutis-host.md; docs/guide/nodes.md for remote use
  • The package table in the READMEs; toolchains in CONTRIBUTING
  • The multi-language master plan: milestones and §9

6. Phases (the Go / Swift rhythm)

  1. Merge the design doc.
  2. Session layer and conformance entry point: pass runtime_conformance.
  3. Runtime contract, SDK and Rust wiring: pass <language>_runtime, <language>_rows and the new multilang column; all existing tests stay green.
  4. Developer workflow: new, dev, check, template, publishing.
  5. Remote: listen: and dial:, passing websocket_conformance and dial_conformance.

7. Common mistakes

Mistake Instead
Implementing dependency waits, retries or start order in the SDK Leave gating to rutis; the SDK only carries out rows.load / unload
Embedding Rust through FFI to avoid implementing the protocol Implement it in the platform language; conformance tests keep it consistent with the others
Omitting or guessing capabilities Declare reentrant-sync, sync-stack, sync-wait according to the execution model
Running plugin code, or bridging sync calls, on the reader thread One execution unit per incoming call
Having the host compile plugin code dev runs only the project's own build; run runs only ready-made artifacts
Forwarding leaf events across processes Events are dispatched within the runtime process; host → runtime is declared with emits, runtime → host is not available yet
Writing docs in only one language Keep .md and .en.md in step
Running only your own unit tests The Rust-side conformance tests are the contract

Version History

  • b6e4351 Current 2026-10-18 15:27

Same Skill Collection

.agents/skills/rutis-remote-plugin/SKILL.md

Metadata

Files
0
Version
b6e4351
Hash
36d0b194
Indexed
2026-10-18 15:27

Home - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-10-19 22:51
浙ICP备14020137号-1