@calimero-network/agent-skills 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -17
- package/SKILL.md +31 -28
- package/package.json +1 -1
- package/scripts/install.js +3 -3
- package/scripts/test.js +6 -15
- package/skills/calimero-abi-codegen/SKILL.md +121 -22
- package/skills/calimero-abi-codegen/references/abi-format.md +3 -5
- package/skills/calimero-abi-codegen/references/generated-output.md +12 -4
- package/skills/calimero-abi-codegen/rules/schema-version.md +11 -4
- package/skills/calimero-abi-codegen/rules/unique-names.md +2 -6
- package/skills/calimero-client-js/SKILL.md +126 -31
- package/skills/calimero-client-js/references/auth.md +18 -10
- package/skills/calimero-client-js/references/rpc-calls.md +15 -21
- package/skills/calimero-client-js/references/sso.md +9 -9
- package/skills/calimero-client-js/references/websocket-events.md +73 -92
- package/skills/calimero-client-js/rules/camelcase-api.md +10 -7
- package/skills/calimero-client-js/rules/token-refresh.md +11 -11
- package/skills/calimero-client-py/SKILL.md +25 -13
- package/skills/calimero-client-py/references/api.md +41 -43
- package/skills/calimero-client-py/references/auth.md +7 -7
- package/skills/calimero-client-py/rules/async-usage.md +27 -31
- package/skills/calimero-client-py/rules/stable-node-name.md +7 -7
- package/skills/calimero-core/SKILL.md +135 -0
- package/skills/calimero-core/references/architecture.md +101 -0
- package/skills/calimero-core/references/jsonrpc-protocol.md +192 -0
- package/skills/calimero-core/references/namespaces-groups.md +94 -0
- package/skills/calimero-core/references/storage-types.md +118 -0
- package/skills/calimero-core/references/websocket-events.md +142 -0
- package/skills/calimero-core/rules/context-is-not-app.md +35 -0
- package/skills/calimero-core/rules/crdt-types-only.md +55 -0
- package/skills/calimero-desktop/SKILL.md +24 -19
- package/skills/calimero-desktop/references/sso-integration.md +2 -2
- package/skills/calimero-desktop/rules/sso-fallback.md +3 -2
- package/skills/calimero-merobox/SKILL.md +255 -28
- package/skills/calimero-merobox/references/ci-integration.md +3 -2
- package/skills/calimero-merobox/references/workflow-files.md +7 -5
- package/skills/calimero-merobox/rules/docker-required.md +7 -6
- package/skills/calimero-meroctl/SKILL.md +68 -0
- package/skills/calimero-meroctl/references/commands.md +177 -0
- package/skills/calimero-meroctl/references/scripting.md +80 -0
- package/skills/calimero-meroctl/rules/call-view-flag.md +28 -0
- package/skills/calimero-meroctl/rules/register-node-once.md +34 -0
- package/skills/calimero-merod/SKILL.md +49 -0
- package/skills/calimero-merod/references/health-endpoints.md +90 -0
- package/skills/calimero-merod/references/init-flags.md +84 -0
- package/skills/calimero-merod/rules/init-before-run.md +40 -0
- package/skills/calimero-merod/rules/port-assignments.md +33 -0
- package/skills/calimero-node/SKILL.md +50 -39
- package/skills/calimero-node/references/context-lifecycle.md +34 -17
- package/skills/calimero-node/references/meroctl-commands.md +89 -99
- package/skills/calimero-node/rules/app-vs-context.md +4 -4
- package/skills/calimero-registry/SKILL.md +110 -31
- package/skills/calimero-registry/references/bundle-and-push.md +99 -34
- package/skills/calimero-registry/references/manifest-format.md +56 -35
- package/skills/calimero-registry/references/mero-sign.md +10 -9
- package/skills/calimero-registry/rules/key-security.md +3 -2
- package/skills/calimero-registry/rules/sign-before-pack.md +5 -5
- package/skills/calimero-rust-sdk/SKILL.md +154 -44
- package/skills/calimero-rust-sdk/references/blob-api.md +119 -0
- package/skills/calimero-rust-sdk/references/event-handlers.md +122 -0
- package/skills/calimero-rust-sdk/references/events.md +2 -1
- package/skills/calimero-rust-sdk/references/examples.md +81 -29
- package/skills/calimero-rust-sdk/references/migrations.md +123 -0
- package/skills/calimero-rust-sdk/references/nested-crdts.md +113 -0
- package/skills/calimero-rust-sdk/references/private-storage.md +76 -34
- package/skills/calimero-rust-sdk/references/state-collections.md +106 -21
- package/skills/calimero-rust-sdk/references/user-and-frozen-storage.md +169 -0
- package/skills/calimero-rust-sdk/rules/app-macro-placement.md +5 -2
- package/skills/calimero-rust-sdk/rules/no-std-collections.md +5 -2
- package/skills/calimero-rust-sdk/rules/state-derives.md +9 -10
- package/skills/calimero-rust-sdk/rules/wasm-constraints.md +12 -10
- package/skills/calimero-sdk-js/SKILL.md +34 -26
- package/skills/calimero-sdk-js/references/build-pipeline.md +6 -6
- package/skills/calimero-sdk-js/references/collections.md +11 -11
- package/skills/calimero-sdk-js/references/events.md +7 -3
- package/skills/calimero-sdk-js/rules/crdt-only-state.md +18 -18
- package/skills/calimero-sdk-js/rules/no-console-log.md +6 -6
- package/skills/calimero-sdk-js/rules/view-decorator.md +6 -4
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Rule: Docker must be running before merobox commands
|
|
2
2
|
|
|
3
|
-
Merobox uses Docker to run node containers. All `merobox up`, `merobox down`, and `merobox status`
|
|
3
|
+
Merobox uses Docker to run node containers. All `merobox up`, `merobox down`, and `merobox status`
|
|
4
|
+
commands require the Docker daemon to be running.
|
|
4
5
|
|
|
5
6
|
## Check before running
|
|
6
7
|
|
|
@@ -11,11 +12,11 @@ merobox up --workflow workflow.yml
|
|
|
11
12
|
|
|
12
13
|
## Common errors and fixes
|
|
13
14
|
|
|
14
|
-
| Error
|
|
15
|
-
|
|
|
16
|
-
| `Cannot connect to the Docker daemon` | Start Docker Desktop or `sudo systemctl start docker`
|
|
17
|
-
| `port is already allocated`
|
|
18
|
-
| `image not found`
|
|
15
|
+
| Error | Fix |
|
|
16
|
+
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `Cannot connect to the Docker daemon` | Start Docker Desktop or `sudo systemctl start docker` |
|
|
18
|
+
| `port is already allocated` | Another process (or a previous merobox run) is using that port. Run `merobox down` first or change the port in `workflow.yml` |
|
|
19
|
+
| `image not found` | First run pulls images — ensure internet access. Re-run after pull completes. |
|
|
19
20
|
|
|
20
21
|
## Minimum Docker version
|
|
21
22
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# calimero-meroctl — Agent Instructions
|
|
2
|
+
|
|
3
|
+
You are helping a developer use **`meroctl`** — the Calimero CLI for administering a running `merod`
|
|
4
|
+
node (apps, contexts, identities, calls, namespaces, groups).
|
|
5
|
+
|
|
6
|
+
## What meroctl is
|
|
7
|
+
|
|
8
|
+
`meroctl` is a standalone CLI that connects to a running `merod` node over HTTP. It does **not**
|
|
9
|
+
start or stop the node — use `merod` for that. `meroctl` is for everything you would do after the
|
|
10
|
+
node is running.
|
|
11
|
+
|
|
12
|
+
## Connecting to a node
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Register a local node once (recommended)
|
|
16
|
+
meroctl node add node1 /path/to/calimero/home
|
|
17
|
+
meroctl node use node1 # set as default
|
|
18
|
+
|
|
19
|
+
# Or use a remote node
|
|
20
|
+
meroctl node add prod http://my-node.example.com
|
|
21
|
+
meroctl node use prod
|
|
22
|
+
|
|
23
|
+
# Or pass URL directly on any command (no registration needed)
|
|
24
|
+
meroctl --api http://localhost:2428 context ls
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Once a node is registered and set as active, you can omit `--node` from every command.
|
|
28
|
+
|
|
29
|
+
## Core workflow: app → context → call
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# 1. Install app
|
|
33
|
+
meroctl app install --path myapp.wasm
|
|
34
|
+
# → prints application-id
|
|
35
|
+
|
|
36
|
+
# 2. Create context (calls init())
|
|
37
|
+
meroctl context create --application-id <application-id>
|
|
38
|
+
# → prints context-id
|
|
39
|
+
|
|
40
|
+
# 3. Call a mutation
|
|
41
|
+
meroctl call <context-id> set --args '{"key":"hello","value":"world"}'
|
|
42
|
+
|
|
43
|
+
# 4. Call a view
|
|
44
|
+
meroctl call <context-id> get --args '{"key":"hello"}' --view
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Global flags
|
|
48
|
+
|
|
49
|
+
| Flag | Purpose |
|
|
50
|
+
| --------------- | --------------------------------------------------------------- |
|
|
51
|
+
| `--node <name>` | Use a registered node by name |
|
|
52
|
+
| `--api <url>` | Connect to a node directly by URL (skips registration) |
|
|
53
|
+
| `--home <path>` | Alternate meroctl config directory (default: system config dir) |
|
|
54
|
+
|
|
55
|
+
## Key rules
|
|
56
|
+
|
|
57
|
+
- `app install` and `context create` are always two separate steps.
|
|
58
|
+
- Use `--view` on calls that only read state — it skips state persistence.
|
|
59
|
+
- Register a node with `meroctl node add` + `meroctl node use` once; after that no `--node` flag is
|
|
60
|
+
needed.
|
|
61
|
+
|
|
62
|
+
## References
|
|
63
|
+
|
|
64
|
+
See `references/` for:
|
|
65
|
+
|
|
66
|
+
- Full command reference for all subcommand groups
|
|
67
|
+
- Scripting patterns for CI and automation
|
|
68
|
+
- Multi-node setup with namespaces and groups
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# meroctl Command Reference
|
|
2
|
+
|
|
3
|
+
## Global flags
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
meroctl --node <name> <cmd> # registered node by name
|
|
7
|
+
meroctl --api <url> <cmd> # direct URL, no registration
|
|
8
|
+
meroctl --home <path> <cmd> # alternate config directory
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## node — manage node connections
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Register a local node
|
|
17
|
+
meroctl node add <name> <path-to-calimero-home>
|
|
18
|
+
|
|
19
|
+
# Register a remote node
|
|
20
|
+
meroctl node add <name> <http-url>
|
|
21
|
+
|
|
22
|
+
# Set active (default) node
|
|
23
|
+
meroctl node use <name>
|
|
24
|
+
|
|
25
|
+
# List registered nodes
|
|
26
|
+
meroctl node ls
|
|
27
|
+
|
|
28
|
+
# Remove a node connection
|
|
29
|
+
meroctl node remove <name>
|
|
30
|
+
|
|
31
|
+
# Show this node's peer identity (public key)
|
|
32
|
+
meroctl node identity
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## app — manage installed applications
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Install from local WASM file
|
|
41
|
+
meroctl app install --path path/to/app.wasm
|
|
42
|
+
|
|
43
|
+
# Install from local .mpk bundle
|
|
44
|
+
meroctl app install --path path/to/app.mpk
|
|
45
|
+
|
|
46
|
+
# Install from registry URL
|
|
47
|
+
meroctl app install --url https://apps.calimero.network/<app-id>/<version>
|
|
48
|
+
|
|
49
|
+
# List installed apps
|
|
50
|
+
meroctl app ls
|
|
51
|
+
|
|
52
|
+
# Get details of a specific app
|
|
53
|
+
meroctl app get <application-id>
|
|
54
|
+
|
|
55
|
+
# Remove an app (does not delete existing contexts)
|
|
56
|
+
meroctl app remove <application-id>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## context — manage contexts
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Create a context (instantiates app — calls init())
|
|
65
|
+
meroctl context create --application-id <application-id>
|
|
66
|
+
|
|
67
|
+
# Create in dev mode (auto-reinstall when WASM file changes)
|
|
68
|
+
meroctl context create --watch path/to/app.wasm
|
|
69
|
+
|
|
70
|
+
# List all contexts on this node
|
|
71
|
+
meroctl context ls
|
|
72
|
+
|
|
73
|
+
# Get details of a specific context
|
|
74
|
+
meroctl context get <context-id>
|
|
75
|
+
|
|
76
|
+
# Delete a context (wipes all state — irreversible)
|
|
77
|
+
meroctl context delete <context-id>
|
|
78
|
+
|
|
79
|
+
# Manually trigger state sync with peers
|
|
80
|
+
meroctl context sync <context-id>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## call — invoke app methods
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Mutation — changes shared CRDT state
|
|
89
|
+
meroctl call <context-id> <method-name> --args '{"key":"val"}'
|
|
90
|
+
|
|
91
|
+
# View — read-only, skips state persistence
|
|
92
|
+
meroctl call <context-id> <method-name> --args '{"key":"val"}' --view
|
|
93
|
+
|
|
94
|
+
# Method with no arguments
|
|
95
|
+
meroctl call <context-id> list_all --args '{}' --view
|
|
96
|
+
|
|
97
|
+
# Specify executor identity explicitly
|
|
98
|
+
meroctl call <context-id> <method> --args '{}' --as <identity-id>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The `--view` flag should be used for any method that is annotated `@View()` (JS) or takes `&self`
|
|
102
|
+
without state mutation (Rust). Omitting `--view` on a read method is not harmful but wastes a
|
|
103
|
+
storage write.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## identity — manage identities
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Create a new identity (Ed25519 keypair)
|
|
111
|
+
meroctl identity create
|
|
112
|
+
|
|
113
|
+
# List all identities
|
|
114
|
+
meroctl identity ls
|
|
115
|
+
|
|
116
|
+
# Get details of a specific identity
|
|
117
|
+
meroctl identity get <identity-id>
|
|
118
|
+
|
|
119
|
+
# Delete an identity
|
|
120
|
+
meroctl identity delete <identity-id>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## namespace — multi-node trust
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Create a namespace (this node is the trust root)
|
|
129
|
+
meroctl namespace create
|
|
130
|
+
|
|
131
|
+
# List namespaces on this node
|
|
132
|
+
meroctl namespace ls
|
|
133
|
+
|
|
134
|
+
# Generate an invite token (share with the joining node)
|
|
135
|
+
meroctl namespace invite <namespace-id>
|
|
136
|
+
|
|
137
|
+
# Join a namespace using an invite token
|
|
138
|
+
meroctl namespace join <namespace-id> '<invitation-json>'
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## group — context membership
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# List groups
|
|
147
|
+
meroctl group ls
|
|
148
|
+
|
|
149
|
+
# Join a context via group membership (after joining the namespace)
|
|
150
|
+
meroctl group join-context <context-id>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Full local dev flow (single machine)
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# 1. Start the node (in another terminal)
|
|
159
|
+
merod --node node1 init --server-port 2428 --swarm-port 2528
|
|
160
|
+
merod --node node1 run
|
|
161
|
+
|
|
162
|
+
# 2. Register the node
|
|
163
|
+
meroctl node add node1 ~/.calimero/node1
|
|
164
|
+
meroctl node use node1
|
|
165
|
+
|
|
166
|
+
# 3. Install app
|
|
167
|
+
meroctl app install --path target/wasm32-unknown-unknown/release/myapp.wasm
|
|
168
|
+
# → save application-id
|
|
169
|
+
|
|
170
|
+
# 4. Create context
|
|
171
|
+
meroctl context create --application-id <application-id>
|
|
172
|
+
# → save context-id
|
|
173
|
+
|
|
174
|
+
# 5. Develop interactively
|
|
175
|
+
meroctl call <context-id> set --args '{"key":"foo","value":"bar"}'
|
|
176
|
+
meroctl call <context-id> get --args '{"key":"foo"}' --view
|
|
177
|
+
```
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Scripting with meroctl
|
|
2
|
+
|
|
3
|
+
## Capturing output for use in scripts
|
|
4
|
+
|
|
5
|
+
Most `create` commands print an ID on stdout. Capture it with shell variable assignment:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
APP_ID=$(meroctl app install --path app.wasm | grep -oP '(?<=application-id: )[\w-]+')
|
|
9
|
+
CTX_ID=$(meroctl context create --application-id "$APP_ID" | grep -oP '(?<=context-id: )[\w-]+')
|
|
10
|
+
meroctl call "$CTX_ID" set --args '{"key":"hello","value":"world"}'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> Check the actual output format of your `merod` version — the label text may vary. Use `--as-json`
|
|
14
|
+
> if available to get machine-readable output.
|
|
15
|
+
|
|
16
|
+
## JSON output (if supported)
|
|
17
|
+
|
|
18
|
+
Some `meroctl` commands support a `--as-json` flag for machine-readable output:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
meroctl --as-json context ls
|
|
22
|
+
meroctl --as-json app ls
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Minimal CI script (GitHub Actions)
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
- name: Deploy and test
|
|
29
|
+
run: |
|
|
30
|
+
# Register node (assumes merod is running in a service container)
|
|
31
|
+
meroctl node add ci http://localhost:2428
|
|
32
|
+
meroctl node use ci
|
|
33
|
+
|
|
34
|
+
# Install app
|
|
35
|
+
APP_ID=$(meroctl app install --path app.wasm)
|
|
36
|
+
echo "APP_ID=$APP_ID" >> $GITHUB_ENV
|
|
37
|
+
|
|
38
|
+
# Create context
|
|
39
|
+
CTX_ID=$(meroctl context create --application-id "$APP_ID")
|
|
40
|
+
echo "CTX_ID=$CTX_ID" >> $GITHUB_ENV
|
|
41
|
+
|
|
42
|
+
- name: Run integration tests
|
|
43
|
+
run: |
|
|
44
|
+
meroctl call "$CTX_ID" set --args '{"key":"test","value":"1"}'
|
|
45
|
+
RESULT=$(meroctl call "$CTX_ID" get --args '{"key":"test"}' --view)
|
|
46
|
+
echo "$RESULT" | grep -q '"1"' || (echo "FAIL: unexpected value" && exit 1)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Dev-mode hot reload
|
|
50
|
+
|
|
51
|
+
Use `--watch` during development to automatically reinstall the WASM and update the context whenever
|
|
52
|
+
the file changes:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Watches app.wasm, reinstalls on change
|
|
56
|
+
meroctl context create --watch path/to/app.wasm
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Calling methods in a loop
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
for key in foo bar baz; do
|
|
63
|
+
meroctl call "$CTX_ID" set --args "{\"key\":\"$key\",\"value\":\"$key-val\"}"
|
|
64
|
+
done
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Multi-node scripting
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Node A: setup
|
|
71
|
+
meroctl --node node1 namespace create
|
|
72
|
+
NS_ID=<paste namespace-id>
|
|
73
|
+
meroctl --node node1 context create --application-id "$APP_ID"
|
|
74
|
+
CTX_ID=<paste context-id>
|
|
75
|
+
INVITE=$(meroctl --node node1 namespace invite "$NS_ID")
|
|
76
|
+
|
|
77
|
+
# Node B: join
|
|
78
|
+
meroctl --node node2 namespace join "$NS_ID" "$INVITE"
|
|
79
|
+
meroctl --node node2 group join-context "$CTX_ID"
|
|
80
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Rule: Use --view for Read-Only Methods
|
|
2
|
+
|
|
3
|
+
**Always pass `--view` when calling a method that only reads state.**
|
|
4
|
+
|
|
5
|
+
## Why
|
|
6
|
+
|
|
7
|
+
Without `--view`, the node treats the call as a mutation — it persists the state after the call and
|
|
8
|
+
broadcasts a `StateMutation` event to all context members. For read-only methods this is wasteful
|
|
9
|
+
(unnecessary writes and network traffic) and may cause unexpected state mutation events in
|
|
10
|
+
subscribers.
|
|
11
|
+
|
|
12
|
+
## How to identify view methods
|
|
13
|
+
|
|
14
|
+
- **Rust SDK**: method takes `&self` (not `&mut self`)
|
|
15
|
+
- **JS SDK**: method is annotated with `@View()`
|
|
16
|
+
- **meroctl call**: you cannot tell from the CLI alone — check the app source
|
|
17
|
+
|
|
18
|
+
## Correct usage
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Read-only — use --view
|
|
22
|
+
meroctl call <ctx-id> get_posts --args '{}' --view
|
|
23
|
+
meroctl call <ctx-id> get --args '{"key":"foo"}' --view
|
|
24
|
+
|
|
25
|
+
# Mutation — no --view
|
|
26
|
+
meroctl call <ctx-id> create_post --args '{"title":"Hello"}'
|
|
27
|
+
meroctl call <ctx-id> set --args '{"key":"foo","value":"bar"}'
|
|
28
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Rule: Register Node Once, Then Use by Name
|
|
2
|
+
|
|
3
|
+
**Run `meroctl node add` + `meroctl node use` once. After that, omit `--node` from all commands.**
|
|
4
|
+
|
|
5
|
+
## Pattern
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# One-time setup:
|
|
9
|
+
meroctl node add node1 /path/to/calimero/home # or http://url for remote
|
|
10
|
+
meroctl node use node1
|
|
11
|
+
|
|
12
|
+
# All subsequent commands use the active node automatically:
|
|
13
|
+
meroctl app install --path app.wasm # no --node needed
|
|
14
|
+
meroctl context ls # no --node needed
|
|
15
|
+
meroctl call <ctx-id> get --args '{}' --view # no --node needed
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Don't do this
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Repetitive and error-prone:
|
|
22
|
+
meroctl --node node1 app install --path app.wasm
|
|
23
|
+
meroctl --node node1 context create --application-id <id>
|
|
24
|
+
meroctl --node node1 call <ctx-id> get --args '{}' --view
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Exception: multiple nodes
|
|
28
|
+
|
|
29
|
+
When scripting across multiple nodes in one session, use explicit `--node` to avoid ambiguity:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
meroctl --node node1 namespace invite <ns-id> # Node A generates invite
|
|
33
|
+
meroctl --node node2 namespace join <ns-id> ... # Node B accepts
|
|
34
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# calimero-merod — Agent Instructions
|
|
2
|
+
|
|
3
|
+
You are helping a developer run and configure the **`merod` Calimero node daemon**.
|
|
4
|
+
|
|
5
|
+
## What merod is
|
|
6
|
+
|
|
7
|
+
`merod` is the Calimero node runtime. It:
|
|
8
|
+
|
|
9
|
+
- Executes WASM applications inside isolated contexts
|
|
10
|
+
- Manages persistent CRDT storage
|
|
11
|
+
- Exposes a JSON-RPC + WebSocket HTTP API (default port 2428)
|
|
12
|
+
- Participates in the P2P swarm for state sync with other nodes (default port 2528)
|
|
13
|
+
- Issues and validates JWT tokens for client authentication
|
|
14
|
+
|
|
15
|
+
`merod` is a long-running daemon. Use `meroctl` for administration after startup.
|
|
16
|
+
|
|
17
|
+
## Two-step startup
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Step 1 — initialise (run ONCE on a fresh home directory)
|
|
21
|
+
merod --node node1 init --server-port 2428 --swarm-port 2528
|
|
22
|
+
|
|
23
|
+
# Step 2 — run (run every time)
|
|
24
|
+
merod --node node1 run
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Never run `merod run` on an uninitialised home.** Run `init` first.
|
|
28
|
+
|
|
29
|
+
## Key flags
|
|
30
|
+
|
|
31
|
+
| Flag | Purpose | Default |
|
|
32
|
+
| ---------------------- | --------------------------------------------------- | ----------------- |
|
|
33
|
+
| `--node <name>` | Node identity name (used to namespace config files) | required |
|
|
34
|
+
| `--home <path>` | Base directory for all config and data | system config dir |
|
|
35
|
+
| `--server-port <port>` | HTTP/WS API port (init only) | `2428` |
|
|
36
|
+
| `--swarm-port <port>` | P2P swarm port (init only) | `2528` |
|
|
37
|
+
|
|
38
|
+
## Port responsibilities
|
|
39
|
+
|
|
40
|
+
| Port | What connects to it |
|
|
41
|
+
| ---------------------- | --------------------------------------------------------------- |
|
|
42
|
+
| `--server-port` (2428) | meroctl, app clients, browser frontends, Python client |
|
|
43
|
+
| `--swarm-port` (2528) | Other `merod` nodes (P2P state sync, namespace invite protocol) |
|
|
44
|
+
|
|
45
|
+
Both ports must be open / reachable for multi-node setups.
|
|
46
|
+
|
|
47
|
+
## References
|
|
48
|
+
|
|
49
|
+
See `references/` for init flags, config file schema, health endpoints, and Docker setup.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Health Endpoints and API Discovery
|
|
2
|
+
|
|
3
|
+
## Health check
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
GET http://localhost:2428/health
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Returns `200 OK` with a JSON body when the node is running and ready.
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{ "status": "alive" }
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
> **Note:** The status value is `"alive"`, not `"healthy"`. Code that checks for `"healthy"` will
|
|
16
|
+
> incorrectly treat a live node as unhealthy.
|
|
17
|
+
|
|
18
|
+
## Wait for node ready (shell)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
until curl -sf http://localhost:2428/health > /dev/null; do
|
|
22
|
+
echo "waiting for node..."
|
|
23
|
+
sleep 1
|
|
24
|
+
done
|
|
25
|
+
echo "node is ready"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Wait for node ready (CI — GitHub Actions)
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
- name: Wait for node
|
|
32
|
+
run: |
|
|
33
|
+
for i in $(seq 1 30); do
|
|
34
|
+
if curl -sf http://localhost:2428/health; then
|
|
35
|
+
echo "Node ready"
|
|
36
|
+
break
|
|
37
|
+
fi
|
|
38
|
+
echo "Waiting... ($i/30)"
|
|
39
|
+
sleep 2
|
|
40
|
+
done
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## API base URL
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
http://localhost:2428/api/v0/
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
All management endpoints are under `/api/v0/`. Clients must authenticate with
|
|
52
|
+
`Authorization: Bearer <accessToken>` on all endpoints except `/api/v0/identity/login`.
|
|
53
|
+
|
|
54
|
+
## Key API paths
|
|
55
|
+
|
|
56
|
+
| Path | Method | Purpose |
|
|
57
|
+
| ------------------------------- | ------ | -------------------------------------- |
|
|
58
|
+
| `/health` | GET | Node liveness check (no auth required) |
|
|
59
|
+
| `/api/v0/identity/login` | POST | Get access + refresh tokens |
|
|
60
|
+
| `/api/v0/identity/refresh` | POST | Refresh access token |
|
|
61
|
+
| `/api/v0/contexts` | GET | List contexts |
|
|
62
|
+
| `/api/v0/contexts` | POST | Create context |
|
|
63
|
+
| `/api/v0/contexts/{id}/execute` | POST | Call app method |
|
|
64
|
+
| `/api/v0/applications` | GET | List installed apps |
|
|
65
|
+
| `/api/v0/applications` | POST | Install app (multipart) |
|
|
66
|
+
|
|
67
|
+
WebSocket: `ws://localhost:2428/ws`
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Docker health check
|
|
72
|
+
|
|
73
|
+
```dockerfile
|
|
74
|
+
HEALTHCHECK --interval=5s --timeout=3s --retries=10 \
|
|
75
|
+
CMD curl -sf http://localhost:2428/health || exit 1
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Docker Compose health check
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
services:
|
|
82
|
+
node:
|
|
83
|
+
image: calimero/merod:latest
|
|
84
|
+
healthcheck:
|
|
85
|
+
test: ['CMD', 'curl', '-sf', 'http://localhost:2428/health']
|
|
86
|
+
interval: 5s
|
|
87
|
+
timeout: 3s
|
|
88
|
+
retries: 10
|
|
89
|
+
start_period: 10s
|
|
90
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# merod Init and Run Flags
|
|
2
|
+
|
|
3
|
+
## merod init
|
|
4
|
+
|
|
5
|
+
Initialises a new node home directory: generates key material, writes the config file, and creates
|
|
6
|
+
the storage directory. Run **once** per node, before the first `merod run`.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
merod --node <name> init [flags]
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### Flags
|
|
13
|
+
|
|
14
|
+
| Flag | Required | Default | Description |
|
|
15
|
+
| ---------------------- | -------- | ------------- | ------------------------------------------------------------------- |
|
|
16
|
+
| `--node <name>` | Yes | — | Node identity name. Namespaces config files under `<home>/<name>/`. |
|
|
17
|
+
| `--home <path>` | No | OS config dir | Base directory. All node data lives under `<home>/<name>/`. |
|
|
18
|
+
| `--server-port <port>` | No | `2428` | HTTP/WS API port. Clients and meroctl connect here. |
|
|
19
|
+
| `--swarm-port <port>` | No | `2528` | P2P port. Other merod nodes connect here for state sync. |
|
|
20
|
+
|
|
21
|
+
### Examples
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Minimal (uses defaults)
|
|
25
|
+
merod --node node1 init
|
|
26
|
+
|
|
27
|
+
# Custom ports
|
|
28
|
+
merod --node node1 init --server-port 3000 --swarm-port 3001
|
|
29
|
+
|
|
30
|
+
# Custom home directory
|
|
31
|
+
merod --home ./data --node node1 init --server-port 2428 --swarm-port 2528
|
|
32
|
+
|
|
33
|
+
# Multiple nodes on the same machine (must use different ports)
|
|
34
|
+
merod --home ./data --node node1 init --server-port 2428 --swarm-port 2528
|
|
35
|
+
merod --home ./data --node node2 init --server-port 2429 --swarm-port 2529
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## merod run
|
|
41
|
+
|
|
42
|
+
Starts the node daemon. The home directory must already be initialised.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
merod --node <name> run [flags]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Run flags
|
|
49
|
+
|
|
50
|
+
| Flag | Required | Default | Description |
|
|
51
|
+
| --------------- | -------- | ------------- | --------------------------------------- |
|
|
52
|
+
| `--node <name>` | Yes | — | Must match the name used during `init`. |
|
|
53
|
+
| `--home <path>` | No | OS config dir | Must match the home used during `init`. |
|
|
54
|
+
|
|
55
|
+
### Run examples
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Run in foreground
|
|
59
|
+
merod --node node1 run
|
|
60
|
+
|
|
61
|
+
# Run in background (Unix)
|
|
62
|
+
merod --node node1 run &
|
|
63
|
+
|
|
64
|
+
# Run with custom home
|
|
65
|
+
merod --home ./data --node node1 run
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Data directory layout
|
|
71
|
+
|
|
72
|
+
After `init`, the following structure is created under `<home>/<node-name>/`:
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
<home>/
|
|
76
|
+
└── <node-name>/
|
|
77
|
+
├── config.toml # node configuration (server port, swarm port, etc.)
|
|
78
|
+
├── identity/ # Ed25519 node keypair
|
|
79
|
+
└── data/ # CRDT storage, application binaries
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Do not edit `config.toml` manually unless you know what you are changing.** Port numbers are
|
|
83
|
+
written to config during `init` and cannot be changed without re-initialising or manually editing
|
|
84
|
+
the config.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Rule: Always Init Before Run
|
|
2
|
+
|
|
3
|
+
**`merod init` must be run once before `merod run` on any new home directory.**
|
|
4
|
+
|
|
5
|
+
## Correct order
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# 1. Init (ONCE — creates config, keypair, storage dirs)
|
|
9
|
+
merod --node node1 init --server-port 2428 --swarm-port 2528
|
|
10
|
+
|
|
11
|
+
# 2. Run (every time after)
|
|
12
|
+
merod --node node1 run
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## What goes wrong without init
|
|
16
|
+
|
|
17
|
+
Running `merod run` on an uninitialised home fails immediately — the node has no config file, no
|
|
18
|
+
keypair, and no storage directory. The error will be something like `config not found` or
|
|
19
|
+
`identity not found`.
|
|
20
|
+
|
|
21
|
+
## Re-initialising loses all data
|
|
22
|
+
|
|
23
|
+
Running `merod init` on a home that already has data will **overwrite the config and generate a new
|
|
24
|
+
keypair**, effectively destroying the node's identity and making all existing contexts unreachable
|
|
25
|
+
(their members' trust roots refer to the old keypair).
|
|
26
|
+
|
|
27
|
+
**Never re-init a production node home.**
|
|
28
|
+
|
|
29
|
+
## Multiple nodes on one machine
|
|
30
|
+
|
|
31
|
+
Each node needs its own `--node` name and different ports:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
merod --home ./data --node node1 init --server-port 2428 --swarm-port 2528
|
|
35
|
+
merod --home ./data --node node2 init --server-port 2429 --swarm-port 2529
|
|
36
|
+
|
|
37
|
+
# Run both (separate terminals or background)
|
|
38
|
+
merod --home ./data --node node1 run &
|
|
39
|
+
merod --home ./data --node node2 run &
|
|
40
|
+
```
|