Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: CI

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
check:
name: check (ubuntu-latest)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run check
55 changes: 55 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# AGENTS.md

This repository hosts community Mini App packages for MiniMax Code. One task dominates: add or
update one package at `plugins/<github-username>/<plugin-id>/`.

## Add or update a Mini App

1. New package: copy `examples/hello-miniapp/` to `plugins/<you>/<plugin-id>/`, then replace
`name`, `displayName`, `description`, `author`, `exampleQueries`, the `<title>`, the README, and
the LICENSE holder. Update: open the existing package. Read `docs/package-contract.md` before
editing any manifest.
2. Read `docs/runtime.md` before editing `miniapp/node/*`. Read `docs/security.md` before the
Node code reads or writes files, spawns processes, or makes network requests.
3. Write `README.md` (English; `README.zh-CN.md` optional): what it does, how to install and open
it, and the headings `## Tested environment` and `## Data & access` (files read/written,
network hosts, spawned processes, where state is stored).
4. Add one row to the table in both root READMEs.
5. Run `npm run check`. Done when it reports no errors and every warning is either fixed or
explained in the PR description.

## Hard rules

- `context.dataDir` is your private state directory, created and owned by the Host. Store durable
state there and treat its location as opaque. Reading Host files has no supported API; a plugin
that does so must state in its README which files, how it locates them, and that this relies on
unspecified layout.
- stdout and stdin belong to the Host. Log through `context.logger`.
- The Node entry is ESM with a named export `start(context)`. Resolve `start` only after the
listener accepts connections on `context.listen`. Return `{ dispose }`; `dispose` closes
everything the entry started: server, timers, child processes, streams, file handles.
- Bind only `context.listen.host` / `context.listen.port`. Serve `surface.path` plus your own
routes.
- A Mini App package is a MiniMax Plugin. Skills, MCP servers, hooks, host bindings, MCP endpoints,
and `hostConnectorAccess` may all be declared; `npm run check` validates their shape only, and the
Host validates them at install time. This repository documents the Mini App payload; treat
`context.hostConnector` and those capabilities as outside its scope.
- The runtime payload is exactly `miniapp/client` and `miniapp/node`. Keep tests and docs outside
`miniapp/`. Vendor third-party code inside the payload; `node_modules` is never committed.
- Paths are portable: ASCII, no symlinks, no `..`. `npm run check` enforces the full rule set.
- Secrets stay in the Node process: never in HTML, Client JavaScript, logs, or error responses.
- Plugin ID = directory name = `plugin.json.name`, unique across the repository.

## Review policy

Maintainers gate on three things: manifests pass `npm run check`; the README describes real
behaviour (files, network, processes, tested environment); the package cannot damage Host or user
data. Everything else is a suggestion.

## Navigation

- `docs/package-contract.md` — layout, the three manifests, portable paths, limits
- `docs/runtime.md` — `start(context)`, `dispose`, logger, lifecycle
- `docs/security.md` — process boundary, state, writing outside `dataDir`, spawning, network
- `examples/hello-miniapp/` — the copyable starting point
- `CONTRIBUTING.md` — fork, pull request, and license steps for people
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ English | [简体中文](CONTRIBUTING.zh-CN.md)
We welcome tools, games, and other interesting apps you have built for MiniMax Code.

1. Fork this repository and add your complete plugin package under `plugins/<your-github-username>/<plugin-id>/`. Use a lowercase GitHub username for the author directory.
2. Include the hidden `.minimax-plugin/` directory, `package.json`, `miniapp/`, and all required runtime assets. The plugin must work when copied on its own, without depending on other directories in this repository.
2. Start from `examples/hello-miniapp/`. Include the hidden `.minimax-plugin/` directory, `package.json`, `miniapp/`, and all required runtime assets. The plugin must work when copied on its own, without depending on other directories in this repository. The exact rules are in `docs/package-contract.md`, `docs/runtime.md`, and `docs/security.md`.
3. Add a short English `README.md`. You may also include `README.zh-CN.md` with links between the two versions. Explain what the app does, how to install and use it, tested client versions and operating systems, required configuration, file access, and network requests. Screenshots or GIFs are welcome.
4. Include a `LICENSE` you are entitled to use, and preserve required attribution for third-party code and assets.
5. Add an entry to the app tables in both root READMEs and open a pull request.
5. Add an entry to the app tables in both root READMEs, run `npm run check` (Node.js 22 or later) until it reports no errors, and open a pull request.

The plugin directory name must match `name` in `.minimax-plugin/plugin.json`. **Plugin IDs must be unique across the repository**, since the author directory is not kept during installation. If a name is already taken, consider adding an author prefix.

Submit ready-to-run files. If the app requires a build step, include its source and build instructions. Do not commit `node_modules/`, credentials, real session records, personal data, or runtime caches. Use synthetic or thoroughly anonymized data in screenshots and examples.

Before submitting, install the app in MiniMax Code, open it, and check its main features. Include your test environment and results in the pull request, and state any unverified behavior. When updating an existing app, keep its plugin ID and update the version and usage instructions as appropriate.

Working with an AI coding agent? It reads `AGENTS.md` automatically; `docs/` holds the same rules for people.
6 changes: 4 additions & 2 deletions CONTRIBUTING.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
欢迎分享你为 MiniMax Code 制作的小工具、游戏和其他有趣作品。

1. Fork 本仓库,在 `plugins/<你的 GitHub username>/<plugin-id>/` 下放入完整插件包。用户名目录统一使用小写。
2. 保留 `.minimax-plugin/` 隐藏目录、`package.json`、`miniapp/` 和运行所需资源。插件应能独立复制使用,不依赖仓库里的其他目录。
2. 从 `examples/hello-miniapp/` 复制开始。保留 `.minimax-plugin/` 隐藏目录、`package.json`、`miniapp/` 和运行所需资源。插件应能独立复制使用,不依赖仓库里的其他目录。具体规则见 `docs/package-contract.md`、`docs/runtime.md` 和 `docs/security.md`(英文)
3. 添加简短的英文 `README.md`,可另附 `README.zh-CN.md` 并互相链接。说明用途、安装与使用方式、已验证的客户端版本和系统,以及需要的配置、文件访问或网络请求。欢迎附上截图或 GIF。
4. 添加你有权使用的 `LICENSE`,保留第三方代码和素材要求的署名。
5. 在根目录中英文 README 的作品表格中各增加一行,提交 Pull Request。
5. 在根目录中英文 README 的作品表格中各增加一行,运行 `npm run check`(需要 Node.js 22 或更高版本)直到没有 error,再提交 Pull Request。

插件目录名应与 `.minimax-plugin/plugin.json` 的 `name` 一致。**插件 ID 在整个仓库中唯一**,因为安装到客户端时不保留作者目录。重名时可加上作者前缀。

提交可直接运行的文件;如果需要构建,附上源码和构建说明。不要提交 `node_modules/`、密钥、真实会话记录、个人数据或运行缓存。截图和示例请使用合成数据或充分脱敏的数据。

提交前在 MiniMax Code 中手动安装、打开并检查主要功能,在 PR 中写明测试环境和结果;未验证的部分如实说明。更新已有作品时,保留插件 ID,并按改动更新版本与使用说明。

使用 AI 编码助手时,它会自动读取 `AGENTS.md`;`docs/` 里是同一套规则的人类可读版本。
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ To update an app, close it and exit MiniMax Code, then replace its complete plug

Tools, games, visualizations, and small experiments are all welcome. To share a MiniApp:

1. Fork the repository and add a complete, ready-to-run package under `plugins/<your-github-username>/<plugin-id>/`.
1. Fork the repository, copy `examples/hello-miniapp/` to `plugins/<your-github-username>/<plugin-id>/`, and build your app there. The package rules are in [`docs/`](docs/package-contract.md); AI coding agents read [`AGENTS.md`](AGENTS.md) automatically.
2. Include a README, a license, and any required runtime files. Document setup, data access, and what you have tested.
3. Add the app to the tables in both root READMEs and open a pull request.
3. Add the app to the tables in both root READMEs, run `npm run check`, and open a pull request.

Use a lowercase GitHub username for the author directory. The plugin directory name must match `.minimax-plugin/plugin.json` → `name`, and **plugin IDs must be unique across the repository**, since the author directory is not part of the installed path.

Expand Down
4 changes: 2 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ git clone https://github.com/MiniMax-AI/MiniMax-Code-MiniApps.git

欢迎分享工具、游戏、可视化应用和小实验。提交作品只需:

1. Fork 仓库,在 `plugins/<你的-github-username>/<plugin-id>/` 下加入可直接运行的完整插件包
1. Fork 仓库,把 `examples/hello-miniapp/` 复制到 `plugins/<你的-github-username>/<plugin-id>/`,在此基础上开发。插件包规则见 [`docs/`](docs/package-contract.md)(英文);AI 编码助手会自动读取 [`AGENTS.md`](AGENTS.md)
2. 附上 README、许可证和运行所需文件,说明配置方式、数据访问范围与验证情况。
3. 在根目录的中英文 README 作品表格中增加一行,然后提交 Pull Request。
3. 在根目录的中英文 README 作品表格中增加一行,运行 `npm run check`,然后提交 Pull Request。

作者目录使用小写 GitHub username。插件目录名必须与 `.minimax-plugin/plugin.json` 中的 `name` 一致,且**插件 ID 在整个仓库中唯一**,因为安装路径不包含作者目录。

Expand Down
131 changes: 131 additions & 0 deletions docs/package-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Mini App package contract

Verified against MiniMax Code 3.0.73.

A Mini App is a MiniMax Plugin whose `package.json` declares a Mini App payload. MiniMax Code
enforces the manifest, payload, and path rules below when the package is installed. `npm run check`
enforces the same rules here, plus this repository's own requirements: `README.md` and `LICENSE`,
a real image file behind `icon`, `lifecycle` limited to `on-demand`, no hard links, no committed
`node_modules`, and the Node entry conventions in `docs/runtime.md`.

## Layout

```text
<plugin-id>/
.minimax-plugin/plugin.json Plugin manifest: identity, icon, category, declared capabilities
package.json Mini App declaration (see below)
icon.png Plugin icon (PNG, JPEG, or WebP)
miniapp/
miniapp.json Payload roots, Node entry, page route
client/ Runtime payload: files served to the page
node/ Runtime payload: the Node entry and what it imports
README.md Required by this repository
LICENSE Required by this repository
README.zh-CN.md Optional
tests/ Optional; keep outside miniapp/
skills/<name>/SKILL.md Optional plugin capability
*.mcp.json Optional plugin capability
bindings/<name>.binding.json Optional plugin capability
```

The directory name, `plugin.json.name`, and the installed plugin ID are the same string. It must be
unique across this repository because the author directory is dropped at install time.

Git does not keep empty directories. Every path listed under `artifacts` must contain at least one
committed file.

## `.minimax-plugin/plugin.json`

| Field | Rule |
| --- | --- |
| `$schema` | Optional string. |
| `schemaVersion` | The number `1`. |
| `name` | At most 80 characters, matches `^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$`, equals the directory name. |
| `displayName` | Optional non-empty string. |
| `version` | SemVer 2.0, at most 128 characters. |
| `description`, `author` | Non-empty strings. |
| `icon` | Relative path with a lowercase `.png`, `.jpg`, `.jpeg`, or `.webp` extension; the file must exist and be a real image. |
| `darkIcon` | Optional; same rules as `icon`. |
| `category` | One of `Office`, `Studio`, `Design & Sites`, `Code`, `Business`, `Sales`, `Productivity`, `Science & Healthcare`, `Education`, `Other`. |
| `exampleQueries` | Array of non-empty strings. Provide at least one; the Agent uses them to open the Mini App by name. |
| `apps` | Array of `*.app.json` paths. Locally installed packages ignore this field; use `[]`. |
| `mcpServers` | Array of `*.mcp.json` paths; each file must exist. These are MCP servers the plugin offers to the Agent, distinct from `mcpEndpoints` in `miniapp.json`. |
| `skills` | Array of `skills/<name>/SKILL.md` paths; each file must exist. |
| `hooks` | Optional array of `*.json` paths; each file must exist. Contents are validated by MiniMax Code at install time. |
| `hostBindings` | Optional array of `bindings/<name>.binding.json` paths; each file must exist. Contents are validated at install time. |
| Any other field | Rejected. |

Use `[]` for `apps`, `mcpServers`, and `skills` when the package has none.

## `package.json`

The `mcode` field must be exactly:

```json
{
"mcode": {
"schemaVersion": 2,
"miniApp": "./miniapp/miniapp.json"
}
}
```

No other keys are allowed inside `mcode`. Other top-level keys (`name`, `type`, `scripts`) are fine.

## `miniapp/miniapp.json`

```json
{
"schemaVersion": 1,
"artifacts": {
"client": ["./miniapp/client"],
"node": ["./miniapp/node"]
},
"runtime": {
"kind": "process",
"entry": "./miniapp/node/server.mjs",
"lifecycle": "on-demand"
},
"surface": { "path": "/dashboard" },
"mcpEndpoints": []
}
```

- `schemaVersion` is `1`. Unknown top-level fields are rejected.
- `artifacts.client` and `artifacts.node` are non-empty arrays of unique paths under `miniapp/`.
Each path must exist. These are the runtime payload roots: exactly what MiniMax Code hashes and
installs. Any `node_modules` directory is excluded from payloads.
- `runtime.kind` is `process`. `runtime.entry` ends in `.js`, `.mjs`, or `.cjs`, exists, and lies
inside one of `artifacts.node`. Use `.mjs`: this repository checks the entry for an ESM `start`
export (see `docs/runtime.md`). `runtime.lifecycle` is `on-demand` or omitted.
- `surface.path` is the route the Node entry serves the page on. It is relative to the Host and
must not contain an origin, query, fragment, or backslash. A missing leading `/` is added.
- `mcpEndpoints` is an array of `{ "server": string, "path": string }`. `server` matches
`^[a-zA-Z0-9_-]{1,128}$` and must name a server declared through `plugin.json.mcpServers`; MiniMax
Code checks that reference at install time. `server` and `path` are each unique. Use `[]` when
there are none.
- `hostConnectorAccess` is optional: `{ "providers": string[] }`, each matching
`^[a-z0-9_-]{1,64}$` and unique. Declared providers are granted by the Host at install time; this
repository does not document their use.

## Portable paths

Every path inside the package, and every path written in a manifest, must be portable:

- ASCII only; each segment matches `[A-Za-z0-9._-]+` and does not end with `.`.
- No `.` or `..` segments, no backslashes, no leading or trailing `/`, no control characters.
- Each segment at most 128 bytes; the whole path at most 512 bytes and at most 16 segments.
- A segment's part before its first `.` must not be a Windows reserved name (`con`, `prn`, `aux`,
`nul`, `com1`–`com9`, `lpt1`–`lpt9`).
- No symbolic links or hard links anywhere in the package, and the package directory itself is not
a symbolic link.

## Package limits

At most 1024 files, 16 MiB per file, and 64 MiB in total.

## Runtime payload

Only `artifacts.client` and `artifacts.node` become the runtime payload. Keep tests, docs, and
source-only files outside `miniapp/`. Vendor any third-party runtime code inside a payload root;
`node_modules` is never committed to this repository.
65 changes: 65 additions & 0 deletions docs/runtime.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Mini App Node runtime

Verified against MiniMax Code 3.0.73.

## Loading

MiniMax Code imports `runtime.entry` as an ES module from a `file:` URL and requires a named export
`start`. The entry's real path must be inside the package. The manifest accepts `.js`, `.mjs`, and
`.cjs`; this repository requires ESM export syntax, so use `.mjs` and do not depend on
`package.json#type`.

```js
export async function start(context) {
// install routes, start the server, return { dispose }
}
```

`miniapp/node/miniapp-api.ts` in `examples/hello-miniapp/` declares the types below. Copy it next
to your entry for editor type checking; it is never imported at runtime.

## `context`

| Field | Meaning |
| --- | --- |
| `pluginId` | The plugin ID (`plugin.json.name`). |
| `pluginRoot` | Real path of the installed package. Read your Client files from here. |
| `dataDir` | a private directory the Host creates and owns for this plugin; its location is opaque and may change; there is no supported way to reach Host files from it. Store durable state here. |
| `listen` | `{ host: "127.0.0.1", port }`. Bind exactly this address; never pick your own port. |
| `signal` | An `AbortSignal` that fires when the Host stops the Mini App. |
| `logger` | `debug` / `info` / `warn` / `error` `(message, fields?)`. Messages are truncated at 4 KiB. Only the **keys** of `fields` leave the process; values stay local, so put diagnostic detail in the message. |
| `hostConnector` | May be absent. Its use is outside the scope of this repository. |

## `start(context)`

- Install every route and start listening before resolving. Resolution is the readiness signal;
there is no health route.
- Return `{ dispose }` or `undefined`. An object without `dispose` is rejected as an invalid
lifecycle. Throwing fails the start; a port collision is reported as its own error.
- Do not fetch business data inside `start`. Register handlers and resolve.

## `dispose()`

Close everything the entry started: the HTTP server, timers, child processes, streams, and any
open file or database handles. The Host stops only the entry process; it does not discover or
terminate processes the entry spawned.

## stdout and stdin

Both belong to the Host. Never call `console.log`, `console.info`, `console.debug`,
`console.dir`, `console.table`, or `process.stdout.write`; log through `context.logger`.

## Lifecycle

The process starts on demand and may be stopped at any time. Only a small number of Mini Apps run at
once, so assume yours can be stopped and restarted between two page views: keep durable state in
`dataDir`, not in memory.

## Client

Serve the page yourself on `surface.path`; a static HTML file is a complete Client. The Client calls
only the routes your Node entry exposes.

## Platforms

MiniMax Code runs on macOS and Windows. Use `node:path` for paths and avoid Unix-only commands.
Loading
Loading