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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ without bundling server-runtime or coordinator-only dependencies.
Version 4 is a complete replacement for the legacy callback-based MiakAPI 3
client. It is currently an alpha while the Miakapp 4 stack is being completed.

**Building a home with a coding agent?** Read
[docs/agent-guide.md](docs/agent-guide.md) first. It covers the judgment the
reference below does not: what the coordinator must authorize, why component
requirements and coordinator grants intersect silently, and which failures must
never be retried. Start from [`templates/home`](templates/home).

## Coordinator requirements

- Bun 1.2.23 or newer (primary coordinator runtime)
Expand Down
408 changes: 408 additions & 0 deletions docs/agent-guide.md

Large diffs are not rendered by default.

97 changes: 97 additions & 0 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,115 @@ duplicate keys — is rejected with the offending line rather than guessed at.
| Command | What it does |
| --- | --- |
| `init` | Writes `miakapp.yaml`. Never overwrites an existing one. |
| `agent-pack` | Offline. Installs the guide and the MCP wiring into a repository. |
| `discover` | Offline. Inventories a Node-RED installation from its flows export. |
| `check` | Offline. Parses the project, verifies the artifact, prints the digest. |
| `publish` | Capability → delivery → finalization → activation, in one run. |
| `activate` | Activates an already finalized digest at a new generation. |
| `rollback` | Alias of `activate`, for returning to a known-good digest. |
| `release <sha256>` | Reads one finalized release record. |
| `upload <uploadId>` | Reads one upload status, to reconcile a lost request. |
| `mcp` | Serves every command above over MCP on stdio. |

`check` is the command to run in CI and before every publication. It costs
nothing, touches no network and catches the four artifact rules the broker's
pinned parser would reject anyway: module syntax, dynamic `import`, a source-map
directive and the ABI 1 token ceiling.

`discover` is the command to run *before* `init`, on a house that already exists:

```
miakapp discover --flows ~/node-red/flows.json --json
```

It needs no project file and no Home Key. It reads the bytes it was given —
opening no socket, contacting no broker, writing nothing back — and reports the
flows, the MQTT brokers with the topics their nodes actually reach, the v3
MiakAPI surface as V4 state and function candidates, and every node type it does
not model, so the reader knows what the inventory missed. It reports that a
coordinator secret is present in the export; it never prints the secret itself.
`docs/agent-guide.md` §3 explains what to do with each finding.

## The agent pack

`agent-pack` is the command to run *once* in a home repository, so that the next
agent to open it arrives already knowing the rules:

```
miakapp agent-pack # or --dir /path/to/the/repository
```

It writes four files and reports what it did to each one:

| File | Why |
| --- | --- |
| `.miakapp/agent-guide.md` | The full guide, copied out of this package. No network, no stale bookmark. |
| `AGENTS.md` | The instruction file Codex reads. |
| `CLAUDE.md` | The instruction file Claude Code reads. |
| `.mcp.json` | Project-scope MCP configuration, registering `miakapp mcp`. |

The repository is yours, so the pack edits rather than replaces. The guide is a
file it owns outright. The instruction files are touched only between
`<!-- miakapp:begin -->` and `<!-- miakapp:end -->`: prose above and below the
markers is copied through byte for byte, and a second run rewrites the block in
place instead of appending another copy. `.mcp.json` is merged as a structure —
one key, by name — so every other server in it survives, and a file that does
not parse is refused rather than replaced with a valid one.

The server is registered as the bare `miakapp` command rather than an absolute
path, because the file is committed and the next machine to check it out will
not have this one's directory layout.

Run it again whenever the CLI is upgraded: an unchanged file is reported
`unchanged`, and a guide that moved on is reported `updated`.

## MCP

An agent that already runs a shell does not need this. An agent that speaks the
Model Context Protocol natively does: `miakapp mcp` serves the same commands as
tools over newline-delimited JSON-RPC on stdio.

```json
{
"mcpServers": {
"miakapp": {
"command": "bunx",
"args": ["@miakapp/cli", "mcp"],
"env": { "MIAKAPP_HOME_KEY": "${MIAKAPP_HOME_KEY}" }
}
}
}
```

| Tool | Command | |
| --- | --- | --- |
| `miakapp_discover` | `discover` | read-only, offline |
| `miakapp_check` | `check` | read-only, offline |
| `miakapp_release` | `release` | read-only |
| `miakapp_upload` | `upload` | read-only |
| `miakapp_init` | `init` | writes `miakapp.yaml`, never overwrites |
| `miakapp_agent_pack` | `agent-pack` | offline, writes the pack into a repository |
| `miakapp_publish` | `publish` | **moves the pointer — needs `confirm: true`** |
| `miakapp_activate` | `activate` | **moves the pointer — needs `confirm: true`** |
| `miakapp_rollback` | `rollback` | **moves the pointer — needs `confirm: true`** |

The server is a translation layer: a tool call becomes the exact argv a person
would have typed and runs the same dispatch, so a tool and a command line cannot
drift apart. A tool argument is the option name with `_` for `-`
(`expected_generation` → `--expected-generation`); an argument the tool does not
declare is refused rather than ignored.

The three pointer-moving tools additionally require `confirm: true`. It is
checked before anything else and never reaches the command line, so a model that
hallucinated a publication spends the mistake on an argument check instead of on
a generation.

A command that fails comes back as a tool result carrying `isError: true` and
the same closed object the CLI prints — `kind`, `exit_code`, `message` and a
remedy — not as a JSON-RPC error. That distinction matters: a protocol error
means the call never happened, while a publication that reached the control
plane and failed did happen, and only `kind` says whether to reconcile.

## Authorization

The Home Key is read from `MIAKAPP_HOME_KEY` and from nowhere else. No command
Expand Down
Loading
Loading