Production-ready ReScript bindings for Tauri 2.x's official JS SDK (@tauri-apps/api). A monorepo centered on @rescript-tauri/core, exposing the entire Tauri public API surface—IPC, Event, Window, Webview, Menu, Tray—from ReScript.
Status: All ten packages are merged on
main.@rescript-tauri/coreprovides 100% coverage of the stable public surface of@tauri-apps/apiv2.11.0 (onlyImage.transformImageis intentionally omitted as upstream marks it unstable). The full set (@rescript-tauri/core,@rescript-tauri/plugin-fs,@rescript-tauri/plugin-dialog,@rescript-tauri/plugin-shell,@rescript-tauri/plugin-notification,@rescript-tauri/plugin-log,@rescript-tauri/plugin-os,@rescript-tauri/plugin-clipboard-manager,@rescript-tauri/plugin-http,@rescript-tauri/schema) is awaiting its first npm publish (v0.1.0track); CI matrices, the release runbook, and the Sphinx documentation site are all in place. Seedocs/product-requirements.mdanddocs/functional-design.mdfor the full scope.Visibility: the repository is public. The npm version badges above will populate once the first
0.1.0releases ship. The CI workflow status is summarized in.github/workflows/README.md.LICENSE(MIT) andCONTRIBUTING.mdare in place.
- Idiomatic ReScript — leverages
variant/option/result/ polymorphic variants to translate constructs that TypeScript expresses withunknownor string-literal unions into type-safe ReScript. - Faithful to Tauri — preserves a near-1:1 mapping with the JS API surface so the official Tauri docs remain directly applicable. Each
.residoc comment links to the corresponding Tauri page. - Three-layer IPC — Layer 1 (Raw
invoke) / Layer 2 (typedCommand) / Layer 3 (Schema integration) lets users choose their own point on the safety/ergonomics curve. - Maintainable monorepo — mirrors the structure of
@tauri-apps/plugin-*, evolving core, plugins, and examples on independent semver. Designed to remain sustainable for a 1–3 person maintainer team.
For the full rationale and scope, see docs/product-requirements.md.
| Package | Role |
|---|---|
@rescript-tauri/core |
Core bindings covering the entire @tauri-apps/api public surface |
@rescript-tauri/plugin-fs |
Bindings for @tauri-apps/plugin-fs |
@rescript-tauri/plugin-dialog |
Bindings for @tauri-apps/plugin-dialog |
@rescript-tauri/plugin-shell |
Bindings for @tauri-apps/plugin-shell (process spawning + openPath) |
@rescript-tauri/plugin-notification |
Bindings for @tauri-apps/plugin-notification (toast notifications + scheduling + Android channels) |
@rescript-tauri/plugin-log |
Bindings for @tauri-apps/plugin-log (5 log levels + attachLogger / attachConsole) |
@rescript-tauri/plugin-os |
Bindings for @tauri-apps/plugin-os (platform / version / arch / family / hostname / locale) |
@rescript-tauri/plugin-clipboard-manager |
Bindings for @tauri-apps/plugin-clipboard-manager (read/write text / image / HTML) |
@rescript-tauri/plugin-http |
Bindings for @tauri-apps/plugin-http (Web-Fetch wrapper that bypasses webview CORS) |
@rescript-tauri/schema |
Command.fromSchemas helper integrating rescript-schema (rescript-struct is deprecated upstream and intentionally not supported) |
Each package is published with independent semver and declares the corresponding upstream @tauri-apps/* package as a peerDependency.
| Component | Supported range |
|---|---|
| Tauri | 2.x (matches the @tauri-apps/api peerDep range) |
| ReScript | >= 12.0.0 (uncurried-by-default) |
@rescript/core |
>= 1.6.0 |
| Node.js | Active LTS |
| OS | Linux / macOS / Windows (Tauri 2.x desktop targets) |
Nightly CI against the latest Tauri release and the next ReScript 12.x minor / next-major prerelease line detects API drift early (compat-tauri-latest.yml, compat-rescript-prerelease.yml). The full job catalogue is documented in .github/workflows/README.md, with design rationale in docs/functional-design.md §6.
The packages are not yet on npm. Once v0.1.0 ships, installation will look like:
pnpm add @rescript-tauri/core @tauri-apps/apiThen add @rescript-tauri/core to dependencies in your rescript.json.
// Layer 1 — Raw invoke (1:1 with @tauri-apps/api)
let greeting: string =
await Tauri.Core.Raw.invoke("greet", ~args={"name": "ReScript"})
// Layer 2 — typed Command with explicit encoder/decoder
module Commands = {
let greet = Core.Command.make(
~name="greet",
~encodeArgs=({name}) =>
JSON.Encode.object([("name", JSON.Encode.string(name))]),
~decodeResult=json =>
switch json->JSON.Decode.string {
| Some(s) => Ok(s)
| None => Error("expected string")
},
)
}
switch await Commands.greet->Core.Command.invoke({name: "ReScript"}) {
| Ok(message) => Console.log(message)
| Error(DecodeError(msg)) => Console.error("decode failed: " ++ msg)
| Error(RustError(json)) => Console.error2("rust error:", json)
}
// Event subscription — Event.make first, then Event.listen
let fileChanged = Event.make(
~name="file-changed",
~decode=json =>
switch json->JSON.Decode.string {
| Some(s) => Ok(s)
| None => Error("expected string")
},
)
let unlisten = await fileChanged->Event.listen(result =>
switch result {
| Ok(evt) => Console.log(evt.payload)
| Error(_) => () // ignore decode failures
}
)Runnable examples live under examples/ (hello-world, window-management, ipc-typed, streaming-ipc, plugin-fs-demo, plugin-dialog-demo, ipc-typed-with-schema) and are CI-built on Linux / macOS / Windows.
# Install dependencies (pnpm required)
pnpm install
# Build all workspaces
pnpm --recursive build
# Clean rebuild
pnpm --recursive run clean && pnpm --recursive build
# Tests (type-level + vitest)
pnpm --recursive test
# Incremental build of the core package only
pnpm --filter @rescript-tauri/core build
# Format + lint hand-written JS / JSON (Biome)
pnpm run check # verify (CI gate)
pnpm run check:fix # auto-fix locally.res / .resi files are formatted by rescript format (run via pnpm --recursive build toolchain). Hand-written .mjs and JSON files are formatted and linted by Biome; ReScript-generated *.res.mjs and lib/ outputs are excluded from Biome.
For contributor-facing details (development flow, local setup, the new-module recipe, coding patterns, PR review angles), see docs/development-guidelines.md (Japanese, internal-facing).
The top-level layout is summarized below. The canonical source is docs/repository-structure.md, which must be updated whenever a new directory is introduced.
rescript-tauri/
├── packages/ # @rescript-tauri/core, plugin-*, schema
├── examples/ # hello-world / window-management / ipc-typed / streaming-ipc / plugin-fs-demo / plugin-dialog-demo / ipc-typed-with-schema
├── docs/ # Internal design docs (PRD, functional design, architecture, ...)
│ └── ideas/ # Drafts / RFCs (input only; not edited after acceptance)
├── sphinx-docs/ # External-facing docs (English base + Japanese via Sphinx i18n)
├── .steering/ # Per-task steering documents (requirements / design / tasklist)
├── .claude/ # Claude Code configuration (rules / skills / agents / commands)
├── .github/ # GitHub Actions / templates
├── CLAUDE.md # Mandatory project instructions for Claude Code (Japanese)
└── README.md # This file
| Document | Contents | Language |
|---|---|---|
docs/product-requirements.md |
Product Requirements Document (personas, user stories, KPIs) | Japanese |
docs/functional-design.md |
Functional design (per-module APIs and types) | Japanese |
docs/architecture.md |
Architecture and technical specification (design principles, 3-layer IPC, cross-cutting policies) | Japanese |
docs/repository-structure.md |
Repository structure (canonical source) | Japanese |
docs/glossary.md |
Ubiquitous-language glossary | Japanese |
docs/ideas/RFC-0001-core-api-design.md |
Core API design RFC (historical input to the PRD; not edited) | English |
CLAUDE.md |
Mandatory instructions for Claude Code | Japanese |
External-facing user and contributor documentation lives in sphinx-docs/ with English as the base language and Japanese translations provided through Sphinx i18n (.po files under sphinx-docs/locale/ja/). The site is built by .github/workflows/docs.yml and deployed to GitHub Pages at https://nagatatz.github.io/rescript-tauri/ (English under /en/, Japanese under /ja/).
This repository is configured for development with Claude Code. The .claude/ directory contains four kinds of configuration:
| Kind | Location | Role | Activation |
|---|---|---|---|
| rules | .claude/rules/ |
Always-applied conventions. @import-ed from CLAUDE.md, enforced in every session. |
Always (no manual trigger) |
| skills | .claude/skills/ |
Situational knowledge / workflows loaded automatically when conditions match. Can also be triggered explicitly with /skill-name. |
Auto / explicit /<name> |
| agents | .claude/agents/ |
Specialized sub-agents (code-reviewer / debugger / build-resolver / security-reviewer / ...). Invoked through the Agent tool. | Agent tool |
| commands | .claude/commands/ |
Slash command definitions (/setup-project, /add-feature, ...). |
/<command> |
The rule / skill / agent / command files themselves are intentionally kept in Japanese to match the primary working language for Claude Code in this project.
When introducing a new convention or workflow, choose its location in this priority order:
- Must be enforced in every session, without exception →
rules/(and@importit fromCLAUDE.md). - Should fire automatically in specific situations / on specific keywords →
skills/. - Has a distinct role best handled by a dedicated sub-agent →
agents/. - Needs an explicit entry point of the form
/xxx→commands/.
rules and skills are easily confused: "always applied" is rules; "applied when the situation arises" is skills. When in doubt, start in skills/ and promote to rules/ later if the scope grows.
| Rule | Contents |
|---|---|
rules/testing.md |
Mandatory tests; self-verification flow |
rules/code-comments.md |
Doc and inline comment conventions |
rules/git-conventions.md |
Emoji-prefixed commits, commit granularity, branch naming, PR-only main workflow (branch protection) |
rules/steering-workflow.md |
Steering documents, worktree workflow, worktree → main reflection via PR self-merge |
rules/documentation.md |
Roles of docs/ vs sphinx-docs/ |
rules/definition-of-done.md |
Single Source of Truth for the Definition of Done (Phases 1–5) |
rules/permission-modes.md |
Plan Mode / steering / auto / sandbox split |
External pull requests and design feedback are welcome. See CONTRIBUTING.md for the branch / commit / steering / CI conventions, and SECURITY.md for vulnerability disclosure.
main is protected by GitHub branch protection (steering 20260512-006): every change lands through a pull request — direct push, force-push, and branch deletion are all blocked, even for admins. The required-approval count is 0, so maintainers can self-merge for solo-dev iteration, but every change still flows through a PR record.
MIT © 2026 Nagatatz and rescript-tauri contributors.