@calimero-network/agent-skills 0.2.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.
Files changed (78) hide show
  1. package/README.md +137 -17
  2. package/SKILL.md +31 -23
  3. package/package.json +2 -2
  4. package/scripts/install.js +3 -3
  5. package/scripts/test.js +6 -15
  6. package/skills/calimero-abi-codegen/SKILL.md +121 -22
  7. package/skills/calimero-abi-codegen/references/abi-format.md +3 -5
  8. package/skills/calimero-abi-codegen/references/generated-output.md +12 -4
  9. package/skills/calimero-abi-codegen/rules/schema-version.md +11 -4
  10. package/skills/calimero-abi-codegen/rules/unique-names.md +2 -6
  11. package/skills/calimero-client-js/SKILL.md +127 -22
  12. package/skills/calimero-client-js/references/auth.md +18 -10
  13. package/skills/calimero-client-js/references/rpc-calls.md +15 -21
  14. package/skills/calimero-client-js/references/sso.md +9 -9
  15. package/skills/calimero-client-js/references/websocket-events.md +73 -59
  16. package/skills/calimero-client-js/rules/camelcase-api.md +10 -7
  17. package/skills/calimero-client-js/rules/token-refresh.md +59 -21
  18. package/skills/calimero-client-py/SKILL.md +26 -10
  19. package/skills/calimero-client-py/references/api.md +41 -43
  20. package/skills/calimero-client-py/references/auth.md +7 -7
  21. package/skills/calimero-client-py/rules/async-usage.md +27 -31
  22. package/skills/calimero-client-py/rules/stable-node-name.md +7 -7
  23. package/skills/calimero-core/SKILL.md +135 -0
  24. package/skills/calimero-core/references/architecture.md +101 -0
  25. package/skills/calimero-core/references/jsonrpc-protocol.md +192 -0
  26. package/skills/calimero-core/references/namespaces-groups.md +94 -0
  27. package/skills/calimero-core/references/storage-types.md +118 -0
  28. package/skills/calimero-core/references/websocket-events.md +142 -0
  29. package/skills/calimero-core/rules/context-is-not-app.md +35 -0
  30. package/skills/calimero-core/rules/crdt-types-only.md +55 -0
  31. package/skills/calimero-desktop/SKILL.md +25 -14
  32. package/skills/calimero-desktop/references/sso-integration.md +49 -22
  33. package/skills/calimero-desktop/rules/sso-fallback.md +3 -2
  34. package/skills/calimero-merobox/SKILL.md +255 -28
  35. package/skills/calimero-merobox/references/ci-integration.md +3 -2
  36. package/skills/calimero-merobox/references/workflow-files.md +7 -5
  37. package/skills/calimero-merobox/rules/docker-required.md +7 -6
  38. package/skills/calimero-meroctl/SKILL.md +68 -0
  39. package/skills/calimero-meroctl/references/commands.md +177 -0
  40. package/skills/calimero-meroctl/references/scripting.md +80 -0
  41. package/skills/calimero-meroctl/rules/call-view-flag.md +28 -0
  42. package/skills/calimero-meroctl/rules/register-node-once.md +34 -0
  43. package/skills/calimero-merod/SKILL.md +49 -0
  44. package/skills/calimero-merod/references/health-endpoints.md +90 -0
  45. package/skills/calimero-merod/references/init-flags.md +84 -0
  46. package/skills/calimero-merod/rules/init-before-run.md +40 -0
  47. package/skills/calimero-merod/rules/port-assignments.md +33 -0
  48. package/skills/calimero-node/SKILL.md +52 -35
  49. package/skills/calimero-node/references/context-lifecycle.md +34 -17
  50. package/skills/calimero-node/references/meroctl-commands.md +89 -99
  51. package/skills/calimero-node/rules/app-vs-context.md +4 -4
  52. package/skills/calimero-registry/SKILL.md +110 -31
  53. package/skills/calimero-registry/references/bundle-and-push.md +99 -34
  54. package/skills/calimero-registry/references/manifest-format.md +56 -35
  55. package/skills/calimero-registry/references/mero-sign.md +10 -9
  56. package/skills/calimero-registry/rules/key-security.md +3 -2
  57. package/skills/calimero-registry/rules/sign-before-pack.md +5 -5
  58. package/skills/calimero-rust-sdk/SKILL.md +154 -44
  59. package/skills/calimero-rust-sdk/references/blob-api.md +119 -0
  60. package/skills/calimero-rust-sdk/references/event-handlers.md +122 -0
  61. package/skills/calimero-rust-sdk/references/events.md +2 -1
  62. package/skills/calimero-rust-sdk/references/examples.md +81 -29
  63. package/skills/calimero-rust-sdk/references/migrations.md +123 -0
  64. package/skills/calimero-rust-sdk/references/nested-crdts.md +113 -0
  65. package/skills/calimero-rust-sdk/references/private-storage.md +76 -34
  66. package/skills/calimero-rust-sdk/references/state-collections.md +106 -21
  67. package/skills/calimero-rust-sdk/references/user-and-frozen-storage.md +169 -0
  68. package/skills/calimero-rust-sdk/rules/app-macro-placement.md +5 -2
  69. package/skills/calimero-rust-sdk/rules/no-std-collections.md +5 -2
  70. package/skills/calimero-rust-sdk/rules/state-derives.md +45 -0
  71. package/skills/calimero-rust-sdk/rules/wasm-constraints.md +12 -10
  72. package/skills/calimero-sdk-js/SKILL.md +145 -0
  73. package/skills/calimero-sdk-js/references/build-pipeline.md +98 -0
  74. package/skills/calimero-sdk-js/references/collections.md +132 -0
  75. package/skills/calimero-sdk-js/references/events.md +63 -0
  76. package/skills/calimero-sdk-js/rules/crdt-only-state.md +47 -0
  77. package/skills/calimero-sdk-js/rules/no-console-log.md +38 -0
  78. package/skills/calimero-sdk-js/rules/view-decorator.md +48 -0
@@ -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
+ ```
@@ -0,0 +1,33 @@
1
+ # Rule: Understand Port Assignments
2
+
3
+ **`merod` uses two distinct ports with different roles. Both matter.**
4
+
5
+ ## Port roles
6
+
7
+ | Flag | Default | Connected by |
8
+ | --------------- | ------- | ----------------------------------------------------------------------- |
9
+ | `--server-port` | `2428` | `meroctl`, app clients (browser, Python, JS), all HTTP/WS API consumers |
10
+ | `--swarm-port` | `2528` | Other `merod` nodes — P2P state sync, namespace invite protocol |
11
+
12
+ ## What fails when a port is wrong or blocked
13
+
14
+ | Problem | Symptom |
15
+ | ----------------------- | ------------------------------------------------------------------------------------ |
16
+ | Server port unreachable | `meroctl` cannot connect; clients get connection refused; apps cannot make API calls |
17
+ | Swarm port unreachable | Multi-node sync silently fails; namespaces cannot be joined; nodes appear isolated |
18
+
19
+ ## Multiple nodes on the same machine
20
+
21
+ Each `merod` instance needs unique ports:
22
+
23
+ ```bash
24
+ merod --home ./data --node node1 init --server-port 2428 --swarm-port 2528
25
+ merod --home ./data --node node2 init --server-port 2429 --swarm-port 2529
26
+ merod --home ./data --node node3 init --server-port 2430 --swarm-port 2530
27
+ ```
28
+
29
+ ## Ports are set at init time
30
+
31
+ Port assignments are written into the config file during `merod init`. You cannot change them with
32
+ `merod run` flags — edit `config.toml` in the node home or re-init if you need different ports
33
+ (re-init destroys the node identity, so prefer editing `config.toml`).
@@ -4,7 +4,8 @@ You are helping a developer manage a **Calimero node** using `merod` and `meroct
4
4
 
5
5
  ## Key concepts
6
6
 
7
- - `merod` — the node runtime. Runs as a daemon. Hosts WASM apps, manages storage, exposes JSON-RPC + WebSocket
7
+ - `merod` — the node runtime. Runs as a daemon. Hosts WASM apps, manages storage, exposes JSON-RPC +
8
+ WebSocket
8
9
  - `meroctl` — the CLI for administrating a running node (contexts, apps, identities)
9
10
  - **Context** — an isolated application instance with its own members, state, and storage
10
11
  - **Application** — the WASM code; one app can power many contexts
@@ -13,60 +14,76 @@ You are helping a developer manage a **Calimero node** using `merod` and `meroct
13
14
  ## Node setup (first time)
14
15
 
15
16
  ```bash
16
- # Initialize node configuration
17
- merod --home ~/.calimero init
17
+ # Initialize node (creates key material and config)
18
+ merod --node node1 init --server-port 2428 --swarm-port 2528
18
19
 
19
20
  # Start the node
20
- merod --home ~/.calimero run
21
+ merod --node node1 run
21
22
  # Node listens on http://localhost:2428 by default
22
23
  ```
23
24
 
24
- ## Complete workflow: app context call
25
+ `--home <PATH>` is optional; defaults to the system config directory. Use it to specify a custom
26
+ data directory: `merod --home ./data --node node1 init`.
27
+
28
+ ## Connecting meroctl to a node
25
29
 
26
30
  ```bash
27
- # 1. Install an app
28
- meroctl --node-url http://localhost:2428 app install \
29
- --path myapp.mpk
30
- # → prints app-id
31
+ # Register a local node by name (one-time)
32
+ meroctl node add node1 /path/to/calimero/home
31
33
 
32
- # 2. Create a context (instantiate the app — init() is called)
33
- meroctl --node-url http://localhost:2428 context create \
34
- --app-id <app-id>
35
- # → prints context-id
34
+ # Or register a remote node
35
+ meroctl node add mynode http://node.example.com
36
36
 
37
- # 3. Call a mutation (changes state)
38
- meroctl --node-url http://localhost:2428 call <context-id> set \
39
- --args '{"key":"hello","value":"world"}'
37
+ # Set as default (so you don't need --node on every command)
38
+ meroctl node use node1
40
39
 
41
- # 4. Call a view (read-only)
42
- meroctl --node-url http://localhost:2428 call <context-id> get \
43
- --args '{"key":"hello"}' --view
40
+ # List configured nodes
41
+ meroctl node ls
42
+ ```
43
+
44
+ After setup, use `--node node1` or rely on the active node:
44
45
 
45
- # 5. Check node is running
46
- meroctl --node-url http://localhost:2428 node health
46
+ ```bash
47
+ meroctl --node node1 context ls # explicit
48
+ meroctl context ls # uses active node
47
49
  ```
48
50
 
49
- ## Multi-node context (invite + join)
51
+ Alternatively, pass a direct URL without registering:
50
52
 
51
53
  ```bash
52
- # On node A — invite a member
53
- meroctl --node-url http://localhost:2428 context invite \
54
- <context-id> --identity <identity-on-node-A>
55
- # → prints invitation payload (JSON)
56
-
57
- # On node B — accept the invitation
58
- meroctl --node-url http://localhost:2429 context join \
59
- --invitation '<paste-invitation-payload>'
60
- # → node B syncs state from node A
54
+ meroctl --api http://localhost:2428 context ls
61
55
  ```
62
56
 
63
- ## Global flags
57
+ ## Complete workflow: app → context → call
64
58
 
65
59
  ```bash
66
- meroctl --node-url http://localhost:2428 <command> # connect to specific node
67
- meroctl --home ~/.calimero <command> # use alternate config path
60
+ # (Assumes: meroctl node add node1 ... && meroctl node use node1 already done)
61
+
62
+ # 1. Install an app
63
+ meroctl app install --path myapp.wasm
64
+ # → prints application-id
65
+
66
+ # 2. Create a context (instantiate the app — init() is called)
67
+ meroctl context create --application-id <application-id>
68
+ # → prints context-id
69
+
70
+ # 3. Call a mutation (changes state)
71
+ meroctl call <context-id> set --args '{"key":"hello","value":"world"}'
72
+
73
+ # 4. Call a view (read-only)
74
+ meroctl call <context-id> get --args '{"key":"hello"}' --view
68
75
  ```
69
76
 
77
+ ## Related skills
78
+
79
+ - **`calimero-merod`** — deep-dive on `merod` daemon: all init flags, config file schema, health
80
+ endpoints, Docker setup
81
+ - **`calimero-meroctl`** — complete `meroctl` CLI reference: every subcommand, every flag, scripting
82
+ patterns, multi-node namespace/group workflow
83
+ - **`calimero-core`** — context/app/identity model, JSON-RPC protocol, WebSocket events, CRDT
84
+ storage types
85
+
70
86
  ## References
71
87
 
72
- See `references/` for full meroctl command reference and context lifecycle.
88
+ See `references/` for context lifecycle detail and multi-node namespace/group setup. For the full
89
+ `meroctl` command reference, use the `calimero-meroctl` skill.
@@ -1,26 +1,27 @@
1
1
  # Context Lifecycle
2
2
 
3
- A **context** is an isolated instance of an application with its own members, CRDT state, and storage.
3
+ A **context** is an isolated instance of an application with its own members, CRDT state, and
4
+ storage.
4
5
 
5
6
  ## App vs Context
6
7
 
7
- | Concept | What it is | Analogy |
8
- | --- | --- | --- |
9
- | Application | WASM binary + manifest | A class / template |
10
- | Context | Running instance of an app | An object / instance |
8
+ | Concept | What it is | Analogy |
9
+ | ----------- | -------------------------- | -------------------- |
10
+ | Application | WASM binary + manifest | A class / template |
11
+ | Context | Running instance of an app | An object / instance |
11
12
 
12
13
  One application can power many independent contexts. Each context has completely isolated state.
13
14
 
14
15
  ## Lifecycle
15
16
 
16
- ```
17
+ ```text
17
18
  App installed on node
18
19
 
19
20
 
20
21
  Context created (init() called → initial state set)
21
22
 
22
23
 
23
- Members invited and joined
24
+ Members join via namespace/group membership
24
25
 
25
26
  ├─ Methods called (mutations + views)
26
27
  ├─ Events emitted to members
@@ -33,23 +34,38 @@ Context deleted (state and storage wiped)
33
34
  ## Creating a context
34
35
 
35
36
  ```bash
36
- meroctl context create --app-id <app-id>
37
+ meroctl --node node1 context create --application-id <application-id>
37
38
  # Returns: context-id
38
39
  ```
39
40
 
40
- ## Inviting members
41
+ Dev mode — auto-reinstalls when the WASM file changes:
41
42
 
42
43
  ```bash
43
- # On node A generate an invitation
44
- meroctl context invite <context-id> --identity <identity-on-node-A>
45
- # Returns: invitation payload (share this with the new member)
46
-
47
- # On node B — accept the invitation
48
- meroctl context join --invitation <paste-invitation-payload>
44
+ meroctl --node node1 context create --watch path/to/app.wasm
49
45
  ```
50
46
 
51
- After joining, node B's state will sync from node A. From that point both nodes
52
- participate in CRDT state synchronization.
47
+ ## Multi-node participation (namespace + group model)
48
+
49
+ Nodes join a context via **namespaces** (root groups). The inviting node creates a namespace
50
+ invitation; joining nodes accept it, then join the context via group membership.
51
+
52
+ ```bash
53
+ # ── Node A (creator) ──
54
+ meroctl --node node1 namespace create
55
+ # → <namespace-id>
56
+
57
+ meroctl --node node1 context create --application-id <app-id>
58
+ # → <context-id>
59
+
60
+ meroctl --node node1 namespace invite <namespace-id>
61
+ # → invitation JSON — share with Node B
62
+
63
+ # ── Node B (joiner) ──
64
+ meroctl --node node2 namespace join <namespace-id> '<invitation-json>'
65
+
66
+ meroctl --node node2 group join-context <context-id>
67
+ # Node B now participates and syncs CRDT state from Node A
68
+ ```
53
69
 
54
70
  ## State synchronization
55
71
 
@@ -57,3 +73,4 @@ participate in CRDT state synchronization.
57
73
  - All context members receive mutations from all other members
58
74
  - Conflicts are resolved deterministically by the CRDT engine
59
75
  - Sync works offline — changes queue up and merge when reconnected
76
+ - Manual sync: `meroctl --node node1 context sync <context-id>`