@remits/remits-cli 0.1.112 → 0.1.114
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 +3 -1
- package/index.js +990 -42
- package/package.json +3 -2
- package/skills/remits-cli/SKILL.md +139 -3366
- package/skills/remits-cli/references/account-targeting.md +165 -0
- package/skills/remits-cli/references/agent-sessions.md +218 -0
- package/skills/remits-cli/references/branch-variants.md +372 -0
- package/skills/remits-cli/references/cli-state.md +158 -0
- package/skills/remits-cli/references/command-reference.md +268 -0
- package/skills/remits-cli/references/component-integrity.md +175 -0
- package/skills/remits-cli/references/component-resolution.md +209 -0
- package/skills/remits-cli/references/development-loop.md +366 -0
- package/skills/remits-cli/references/investigation.md +251 -0
- package/skills/remits-cli/references/support-tickets.md +389 -0
- package/skills/remits-cli/references/tool-reference.md +962 -0
- package/skills/remits-cli/references/troubleshooting.md +135 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Getting Started and Command Reference
|
|
2
|
+
|
|
3
|
+
> A `remits-cli` skill reference. **Load this when** you need the exact command surface: authentication, host versus data mode, the tool execution lifecycle, hierarchy-scoped reads, and every flag.
|
|
4
|
+
>
|
|
5
|
+
> The table of contents below carries **real line numbers** (`- L84 Some Heading`), resolved when
|
|
6
|
+
> this file is installed, so they are never stale. Read the head, pick your sections, and offset-read
|
|
7
|
+
> only those. The entry text is the heading verbatim, so it also greps.
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Getting Started](#getting-started)
|
|
12
|
+
- [Authentication](#authentication)
|
|
13
|
+
- [Host vs Data Mode](#host-vs-data-mode)
|
|
14
|
+
- [Tool Execution Lifecycle](#tool-execution-lifecycle)
|
|
15
|
+
- [Hierarchy-scoped tool reads](#hierarchy-scoped-tool-reads)
|
|
16
|
+
- [Data Mode](#data-mode)
|
|
17
|
+
- [Command Reference](#command-reference)
|
|
18
|
+
- [Prod banners and retryable failures](#prod-banners-and-retryable-failures)
|
|
19
|
+
|
|
20
|
+
## Getting Started
|
|
21
|
+
|
|
22
|
+
### Authentication
|
|
23
|
+
|
|
24
|
+
Authenticate once per session. Opens the user's browser for OAuth login:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
remits-cli auth --account-id <ACCOUNT_ID>
|
|
28
|
+
remits-cli auth --account-id <ACCOUNT_ID> --base-url http://localhost:8080
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- `--account-id` is auto-resolved from `account-info.json` when you're inside an account repo, so you can usually just run `remits-cli auth`. Pass `--account-id <ID>` explicitly to target a different account (e.g., authenticating into a child account from a parent-account repo) — the explicit flag always wins over the repo's `account-info.json` and any prior session.
|
|
32
|
+
- `--base-url` targets a specific platform instance (e.g., localhost for development). Sessions are stored per account + base URL + data mode, so authenticating against localhost does not overwrite a production session for the same account.
|
|
33
|
+
- If any command returns a 401 error, re-run `remits-cli auth` (with the same `--base-url` if you were targeting a non-default instance).
|
|
34
|
+
|
|
35
|
+
### Host vs Data Mode
|
|
36
|
+
|
|
37
|
+
Treat host selection and data mode as two separate decisions:
|
|
38
|
+
|
|
39
|
+
- `--base-url` chooses the Remits host: localhost vs a deployed environment.
|
|
40
|
+
- `--data-mode` chooses the data segment on that host: `test` vs `prod`.
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Deployed prod host, but test data segment
|
|
46
|
+
remits-cli tools --base-url https://your-prod-host --data-mode test
|
|
47
|
+
|
|
48
|
+
# Localhost host, but prod data segment on that localhost instance
|
|
49
|
+
remits-cli tool --base-url http://localhost:8080 --name mcp_account_view --data-mode prod
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Do not assume `--data-mode prod` implies the deployed prod host, or that `--data-mode test` implies localhost. If host matters, read `~/.remits-cli/sessions.json` first and pass `--base-url` explicitly.
|
|
53
|
+
|
|
54
|
+
### Tool Execution Lifecycle
|
|
55
|
+
|
|
56
|
+
`remits-cli tool` supports both synchronous and asynchronous execution. Use normal synchronous execution
|
|
57
|
+
for quick investigation tools:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
remits-cli tool --name "mcp_account_view" --input '{"accountId": 37}' --data-mode prod
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**There are two independent async mechanisms — do not confuse or stack them:**
|
|
64
|
+
|
|
65
|
+
1. **The tool's own async mode** (`mcp_run_action` / `mcp_run_agent`, via `executionMode:"async"` in the
|
|
66
|
+
tool input). The tool spawns the long work server-side and **returns immediately in the same HTTP
|
|
67
|
+
response** with its own run identifiers — `actionRunId` (or `agentRunId`) and, for agents, a stable
|
|
68
|
+
`sessionId`. You poll it with the tool's **own** status protocol (`controlAction:"status"`). This is the
|
|
69
|
+
preferred path for long Actions/Agents, because the run ids come back on the very first call.
|
|
70
|
+
|
|
71
|
+
2. **The CLI transport async** (`--async true`). This wraps *any* tool call in a background server task and
|
|
72
|
+
returns a CLI-level `callId` immediately, which you poll with `remits-cli tool status --call-id`. Use it
|
|
73
|
+
for long tools that do **not** have their own async mode. Its start response carries `callId`,
|
|
74
|
+
`status:"running"`, `threadGroupingId`, `accountId`, `branchName`, and `dataMode` — but **not** any
|
|
75
|
+
tool-specific ids, because the tool has not run yet; those arrive inside the `result` of the polled
|
|
76
|
+
completed status.
|
|
77
|
+
|
|
78
|
+
For `mcp_run_action` / `mcp_run_agent`, prefer mechanism (1) alone — it already makes the call non-blocking
|
|
79
|
+
**and** returns the run ids up front. Pass your own `actionRunId`/`agentRunId` so you can poll it
|
|
80
|
+
deterministically:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
remits-cli tool --name "mcp_run_action" --input '{"accountId":49,"actionId":200,"executionMode":"async","actionRunId":"my-stable-run-id","actionInput":{"sourceDocumentId":"..."}}' --data-mode prod
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Every tool response is saved to `./.remits-cli/tool-responses/<callId>.json`.
|
|
87
|
+
|
|
88
|
+
### Hierarchy-scoped tool reads
|
|
89
|
+
|
|
90
|
+
For read/discovery tools, the account resolved from the checkout/session is the **scope root**, not proof
|
|
91
|
+
that the business record is owned by that account. This closes the common support loop where you know a
|
|
92
|
+
precise document, object, event, or indexed source id but do not yet know which child account owns it.
|
|
93
|
+
|
|
94
|
+
Use the tool flags rather than editing JSON by hand:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
remits-cli tool --name mcp_firestore_search \
|
|
98
|
+
--input '{"collection":"statements","documentId":"1234"}' \
|
|
99
|
+
--scope children --data-mode prod
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Available flags:
|
|
103
|
+
|
|
104
|
+
| Flag | Meaning |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `--scope self|children|hierarchy` | Expand from the repo/session account for read/discovery. Exact-id lookups usually default to `children`; broad searches default to `self` unless widened. |
|
|
107
|
+
| `--target-account-id ID` | Exact owner/execution account when already known. Required by mutating tools. |
|
|
108
|
+
| `--account-ids 1,2,3` | Explicit bounded owner list. The platform verifies every id against the scope root. |
|
|
109
|
+
| `--anchor-account-id ID` | Path-disambiguation anchor for multi-parent account relationships. |
|
|
110
|
+
|
|
111
|
+
The CLI merges these into `--input`; a value already present in `--input` wins. Tool responses echo
|
|
112
|
+
`scopeRootAccountId`, `scope`, `accountIds`, and, when an exact owner is discovered,
|
|
113
|
+
`resolvedTargetAccountId`. Feed that returned owner to `mcp_firestore_patch`, action/test runs, and browser
|
|
114
|
+
tokens. Mutating tools do not infer or fan out writes.
|
|
115
|
+
|
|
116
|
+
The implicit account ceiling is intentionally different by shape: broad searches stay capped at 100 accounts
|
|
117
|
+
unless the tool says otherwise, while exact-id discovery may span up to 1000 accounts by default. If a broad
|
|
118
|
+
tool returns `scopeTooBroad`, narrow with `--target-account-id`, `--account-ids`, or a smaller `--scope`.
|
|
119
|
+
|
|
120
|
+
`mcp_firestore_search` handles exact Firestore document ids. `mcp_index_search` handles fuzzy/semantic
|
|
121
|
+
lookup through Vertex. `mcp_bigquery_query` handles warehouse lookup/query with server-resolved
|
|
122
|
+
`{table_current}`/`{table}` placeholders and the scoped `{account_filter}` predicate. BigQuery is a prod
|
|
123
|
+
analytics surface, so use `--data-mode prod` when you intend to query it.
|
|
124
|
+
|
|
125
|
+
Poll a CLI-transport async call (mechanism 2) by call id:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
remits-cli tool status --call-id <callId> --data-mode prod
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Pass `--wait true` to have the CLI process poll locally until the transport call completes (short polling
|
|
132
|
+
requests instead of one long HTTP connection):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
remits-cli tool --name "some_long_tool_without_its_own_async" --async true --wait true --input '{...}' --data-mode prod
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Stacking both (`--async true` **and** `executionMode:"async"`) works but is redundant: the tool's
|
|
139
|
+
`actionRunId`/`agentRunId`/`sessionId` then appear only in the polled completed `result`, not in the CLI
|
|
140
|
+
start response — which is why the start response looks "incomplete." Pick one mechanism.
|
|
141
|
+
|
|
142
|
+
`--timeout-ms <ms>` controls the per-request HTTP timeout. Prefer async execution over a large timeout for
|
|
143
|
+
multi-minute work so the server task is not tied to one HTTP connection.
|
|
144
|
+
|
|
145
|
+
### Data Mode
|
|
146
|
+
|
|
147
|
+
Controls whether you work with test data or production data. **Default is `test`.**
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
remits-cli data-mode # Show current mode
|
|
151
|
+
remits-cli data-mode set prod # Switch to prod for investigations
|
|
152
|
+
remits-cli data-mode set test # Switch back to test for development
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Command Reference
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
remits-cli auth [--base-url URL] [--account-id ID] [--data-mode test|prod]
|
|
159
|
+
remits-cli sessions [list|remove] [--account-id ID]
|
|
160
|
+
remits-cli config [set] [--agent claude|codex|gemini]
|
|
161
|
+
remits-cli agent serve [--worker-agent claude|codex|gemini] [--max-concurrent N] [--mode edit|investigate] [--label NAME] [--data-mode test|prod]
|
|
162
|
+
remits-cli agent workers [--json]
|
|
163
|
+
remits-cli agent register [--label NAME] [--data-mode test|prod] [--account-id ID] [--max-concurrent N]
|
|
164
|
+
remits-cli agent work [--wait SECONDS] [--json]
|
|
165
|
+
remits-cli agent status [--state idle|working|paused] [--ticket ID] [--activity "..."] [--step "..."]
|
|
166
|
+
remits-cli agent list [--account-id ID] [--json]
|
|
167
|
+
remits-cli agent map [--account-ids 1,4] [--json] # who is EDITING which repository, from which checkout/branch/staging lane
|
|
168
|
+
remits-cli agent release
|
|
169
|
+
remits-cli ticket read|accept|status|progress|complete|release|reopen|assign|planning --ticket ID [--status S] [--resolution "..."] [--summary "..."] [--category C] [--assignee EMAIL] [--workstream VALUE] [--planned-in VALUE] [--board-stage VALUE] [--rank N] [--size VALUE] [--blocked-by VALUE] [--notes "..."]
|
|
170
|
+
remits-cli ticket lease|unlease|force-unlease --ticket ID [--reason "..."] # force-unlease breaks SOMEBODY ELSE'S lease; operator only
|
|
171
|
+
remits-cli ticket where --ticket ID # WHERE this work is: repo account, checkout, branch, staging lane, live lease + holder's location, claim, your phase
|
|
172
|
+
remits-cli ticket ask --ticket ID --question "..." [--context "..."] [--to WHO] # park on a human decision
|
|
173
|
+
remits-cli ticket answer --ticket ID --message "..." [--route false] # answer it (alias: reply); re-routes by default
|
|
174
|
+
remits-cli ticket message --ticket ID --message "..." [--to a@x,b@y] [--subject "..."] [--channel email] # PUBLIC — the requester reads it
|
|
175
|
+
remits-cli ticket note --ticket ID --message "..." # INTERNAL — the next worker and a reviewer read it
|
|
176
|
+
remits-cli ticket deliver --ticket ID --channel email --to a@x [--template T] [--subject "..."] [--idempotency-key K] # ask for it to be SENT
|
|
177
|
+
remits-cli ticket deliveries --ticket ID [--channel email] # what is queued to go out, and what already went
|
|
178
|
+
remits-cli ticket delivered --ticket ID --delivery-id ID | ticket delivery-failed --ticket ID --delivery-id ID --reason "..."
|
|
179
|
+
remits-cli ticket tag --ticket ID --tags a,b # make a cluster of near-identical tickets visible as one
|
|
180
|
+
remits-cli ticket artifact --ticket ID --type TYPE --label "..." [--url U | --content "..."]
|
|
181
|
+
remits-cli ticket participant --ticket ID --email E [--role watcher|requester|agent]
|
|
182
|
+
remits-cli ticket field --ticket ID --key K --value V # the ORGANIZATION's own field, outside the planning slots
|
|
183
|
+
remits-cli ticket reclaim [--ticket ID | --account-id ID] [--stale-hours 24] [--apply] # OPERATOR: take back an agent's abandoned ticket
|
|
184
|
+
remits-cli ticket queue --account-id ID [--status ...] [--unrouted] [--unassigned] [--awaiting-response] [--workstream W] [--board-stage S] [--planned-in P] [--search "..."] [--sort-by ...] [--json]
|
|
185
|
+
remits-cli ticket create --account-id ID --subject "..." --type defect|question|task|incident|enhancement [--priority P] [--description "..."] [--tags a,b] [--workstream W] [--affected-component C] [--implementation-account-id ID] [--reference-id KEY]
|
|
186
|
+
remits-cli start [--foreground true] [--port 8787]
|
|
187
|
+
remits-cli stop
|
|
188
|
+
remits-cli status [--base-url URL] [--account-id ID] [--data-mode test|prod] [--json]
|
|
189
|
+
remits-cli whoami [--base-url URL] [--account-id ID] [--data-mode test|prod] [--json]
|
|
190
|
+
remits-cli listen [stop|status] [--foreground true] # compatibility alias
|
|
191
|
+
remits-cli data-mode [set test|prod]
|
|
192
|
+
remits-cli components stage [--branch <name>] [--workspace <name>] [--changed-only] [--data-mode test|prod] [--json|--verbose]
|
|
193
|
+
remits-cli workspace [show | use <name> | use --auto | clear]
|
|
194
|
+
remits-cli components status [--branch <name>] [--component-type <type>] [--component-id <id>] [--json|--verbose]
|
|
195
|
+
remits-cli components clear [--branch <name>] [--component-type <type>] [--component-id <id>] [--all] [--json|--verbose] # id alone scopes to one component when unambiguous (ids are type-local; add --component-type if the same id is staged in multiple families); no filter clears the whole branch scope; --all forces the full wipe
|
|
196
|
+
remits-cli components sync [--branch <name>] [--data-mode test|prod] [--force-tombstones] [--dry-run] [--summary] [--changed-only [--changed-since <ref>]] # gated; on trunk = full repo->DB reconcile, on a variant branch = ComponentVariant overlays only
|
|
197
|
+
remits-cli components commit [--message "msg"] [--data-mode test|prod] [--force-tombstones]
|
|
198
|
+
remits-cli components branches [--json] # branches carrying committed variants, with counts + drift
|
|
199
|
+
remits-cli components branch <name> [--json] # one branch: overridden / added / removed, drift flags, subscribers
|
|
200
|
+
remits-cli components branch <name> --diff <componentId> --component-type <kind> [--json]
|
|
201
|
+
remits-cli components branch <name> --subscribers [--json]
|
|
202
|
+
remits-cli components branch <name> --subscribe <accountId> [--parent-account <id>] [--domain <host>] [--dry-run] [--confirm-primary-edge] # make an account resolve this branch
|
|
203
|
+
remits-cli components branch <name> --unsubscribe <accountId> # return that account to trunk
|
|
204
|
+
remits-cli components branch <name> --retire [--force] # delete the branch's overlays
|
|
205
|
+
remits-cli test run --test <id|name> [--branch <stagingScope>] [--names "a|b"] [--watch true|false] [--data-mode test|prod] [--as-account <ID>] [--variant-branch <name|none>]
|
|
206
|
+
remits-cli token [--path <embeddablePathOrId>] [--data-mode test|prod] [--as-account <ID>] [--variant-branch <name|none>]
|
|
207
|
+
remits-cli token inspect --token <token|tokenKey|URL> # inspect token metadata, safety/dataMode evidence, and full context
|
|
208
|
+
remits-cli tools [--branch <name>] [--data-mode test|prod] [--variant-branch <name|none>]
|
|
209
|
+
remits-cli tool --name <toolName> [--branch <name>] [--input "{...}"] [--data-mode test|prod] [--variant-branch <name|none>] [--timeout-ms 60000] [--async true --wait true]
|
|
210
|
+
remits-cli tool status --call-id <callId> [--data-mode test|prod]
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
For tests specifically:
|
|
214
|
+
- If `--data-mode` is omitted, `remits-cli test run` uses `test`.
|
|
215
|
+
- `--names` is `|`-delimited (a comma still splits a single value) and may be repeated; an unmatched
|
|
216
|
+
selector fails the run instead of reporting zero cases as success.
|
|
217
|
+
- `--as-account <ID>` runs AS a descendant subscriber so its edge selects the component branch
|
|
218
|
+
(*"what does customer X get?"*); `--variant-branch <name>` probes a branch from any checkout
|
|
219
|
+
(*"what does branch Y look like?"*), and `--variant-branch none` forces production/subscription semantics.
|
|
220
|
+
Omit both and the working tree decides — see `branch-variants.md`.
|
|
221
|
+
- `--branch <stagingScope>` on `test run` selects the Redis staging namespace only. It is useful with
|
|
222
|
+
`--variant-branch none` when an existing staged cache on the real git branch would shadow committed trunk
|
|
223
|
+
or variant rows. On `components sync` / `commit`, `--branch` is different: it names the GitHub branch to
|
|
224
|
+
reconcile.
|
|
225
|
+
- `--force-tombstones` is only for non-trunk variant syncs, when missing trunk component files are known,
|
|
226
|
+
intentional tombstone overrides. It is rejected on trunk.
|
|
227
|
+
- `--dry-run` is only for `components sync` on non-trunk variant branches. It reports the variant write
|
|
228
|
+
plan without writing rows, caching the sync SHA, or clearing staging.
|
|
229
|
+
- `--summary` on `components sync --dry-run` prints compact counts, removals/tombstones, skipped items, errors,
|
|
230
|
+
and warnings instead of the full override/add/remove payload.
|
|
231
|
+
- **Fail-closed sync gates.** On non-trunk variant branches these flags now force a server dry-run first,
|
|
232
|
+
evaluate that plan before any overlay row is written, and only then run the mutating sync when the plan
|
|
233
|
+
passes. On trunk, there is no safe dry-run plan, so do not treat these as scoped commit controls:
|
|
234
|
+
- `--changed-only` — fail unless every planned write is a component **this checkout actually changed**.
|
|
235
|
+
This is the strongest guard against a sync that quietly rewrites components you never touched. It
|
|
236
|
+
also fails when the checkout is not a git working tree, because "git could not answer" must never
|
|
237
|
+
be read as "nothing changed".
|
|
238
|
+
> **Pair it with `--changed-since <ref>` after you have committed.** On its own `--changed-only`
|
|
239
|
+
> reads UNCOMMITTED edits, and the documented flow commits and pushes *before* syncing (sync reads
|
|
240
|
+
> the pushed remote, so it cannot see uncommitted work at all) — so the changed set is empty at
|
|
241
|
+
> exactly the moment the gate runs, and it refuses the whole plan. `--changed-since origin/main`
|
|
242
|
+
> (or the commit you branched from) makes the changed set the components your commits touched.
|
|
243
|
+
> The refusal message says this when it detects the empty-set case.
|
|
244
|
+
- `--fail-on-removed` — fail if the plan removes or tombstones anything.
|
|
245
|
+
- `--expected-removed <type:id>` — whitelist the removals you intend (repeatable, or comma-delimited,
|
|
246
|
+
e.g. `--expected-removed action:5,reader:9`). It **implies** `--fail-on-removed`, so any removal you
|
|
247
|
+
did not name fails the sync.
|
|
248
|
+
- `--fail-on-errors` — fail if the server reported any per-component sync error.
|
|
249
|
+
- `--names-only` — dry-run and print only `BUCKET type:id name` lines for the planned writes, then stop
|
|
250
|
+
without writing overlays.
|
|
251
|
+
|
|
252
|
+
A good default for an unattended promotion is:
|
|
253
|
+
`remits-cli components sync --summary --changed-only --fail-on-errors`
|
|
254
|
+
|
|
255
|
+
### Prod banners and retryable failures
|
|
256
|
+
|
|
257
|
+
- Every command that can touch production (`tool`, `test run`, `components sync`) prints a `PROD DATA`
|
|
258
|
+
banner naming the operation, the resolved account, and the host — and distinguishes a live **WRITE**
|
|
259
|
+
from a live **READ** and from a **DRY RUN**. `remits-cli tool` also prints an explicit **TEST DATA WRITE**
|
|
260
|
+
banner for mutating tool calls in the test lane, including multi-action tools such as
|
|
261
|
+
`mcp_account_user_admin` where the write is signaled by `input.action` (`account_create`, `user_update`,
|
|
262
|
+
`edge_update`, etc.). If you see a WRITE banner you did not intend, stop.
|
|
263
|
+
- A tool call that fails **in the platform runtime** rather than in the tool (Groovy reflective dispatch
|
|
264
|
+
of a runtime-compiled component, an empty connection pool, a Redis reconnect, a lock-wait timeout)
|
|
265
|
+
now comes back as HTTP `503` with `failureClass: "transient_infrastructure"` and `retryable: true`,
|
|
266
|
+
and the CLI prints `TRANSIENT INFRASTRUCTURE FAILURE (retryable)`. Retry that **once**; prefer an
|
|
267
|
+
idempotent input if the tool has side effects. A genuine tool error stays HTTP `500` with
|
|
268
|
+
`failureClass: "tool_error"` — do **not** retry it, fix the input or the component.
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Component Integrity: Repo to Database Reconciliation
|
|
2
|
+
|
|
3
|
+
> A `remits-cli` skill reference. **Load this when** you are about to run `components sync` or `components commit`, or a sync reported something you did not expect. This is the highest-impact failure mode in remits-cli.
|
|
4
|
+
>
|
|
5
|
+
> The table of contents below carries **real line numbers** (`- L84 Some Heading`), resolved when
|
|
6
|
+
> this file is installed, so they are never stale. Read the head, pick your sections, and offset-read
|
|
7
|
+
> only those. The entry text is the heading verbatim, so it also greps.
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Component Integrity Rules: Repo ↔ Database Reconciliation (read before any sync/commit)](#component-integrity-rules-repo--database-reconciliation-read-before-any-synccommit)
|
|
12
|
+
- [How the platform reconciles the repo into the database (the mechanism you must understand)](#how-the-platform-reconciles-the-repo-into-the-database-the-mechanism-you-must-understand)
|
|
13
|
+
- [The surfaces and their intended behavior](#the-surfaces-and-their-intended-behavior)
|
|
14
|
+
- [Intended workflows](#intended-workflows)
|
|
15
|
+
- [Pre-sync safety check (confirm ALL before `components sync` or `components commit`)](#pre-sync-safety-check-confirm-all-before-components-sync-or-components-commit)
|
|
16
|
+
- [If something looks wrong — stop, don't paper over](#if-something-looks-wrong--stop-dont-paper-over)
|
|
17
|
+
|
|
18
|
+
## Component Integrity Rules: Repo ↔ Database Reconciliation (read before any sync/commit)
|
|
19
|
+
|
|
20
|
+
Component source-of-truth mistakes are the highest-impact failure in remits-cli. A repo/DB mismatch can
|
|
21
|
+
hard-delete live components, spawn duplicates, renumber files, or leave the database and repo describing
|
|
22
|
+
different implementations. These rules override the normal fast loop whenever they conflict.
|
|
23
|
+
|
|
24
|
+
### How the platform reconciles the repo into the database (the mechanism you must understand)
|
|
25
|
+
|
|
26
|
+
> **First, check which branch you are on.** Everything in this section describes a **TRUNK** sync. Syncing
|
|
27
|
+
> from a **non-trunk branch** is a different, much safer operation — it writes `ComponentVariant` overlays
|
|
28
|
+
> only and can never create, delete, rename, or overwrite a live component row. Run
|
|
29
|
+
> `remits-cli components status` to see which mode your working tree is in, and read
|
|
30
|
+
> `branch-variants.md` for the variant-branch rules (which have their own hazard: tombstones).
|
|
31
|
+
|
|
32
|
+
`remits-cli components sync` (and the sync phase of `components commit`) calls
|
|
33
|
+
`GitHubClient.syncFromRepository`. On the account's **trunk branch** it is a **full two-way reconcile in
|
|
34
|
+
which the GitHub remote is authoritative over the database.** It reads the **remote repo ZIP — not your
|
|
35
|
+
local working tree** — and:
|
|
36
|
+
|
|
37
|
+
- **Match / update:** each component is matched to a DB row by the **numeric id prefix of its files**
|
|
38
|
+
(`58_x.groovy` → component 58), not by name. Matching files overwrite that component's DB fields
|
|
39
|
+
(source/schema/html/etc.).
|
|
40
|
+
- **Rename:** changing the component's `name:` in `.meta.yml` is supported as a normal update **as long as
|
|
41
|
+
the numeric id prefix stays the same**. On staging, the CLI updates the id/name cache aliases and prunes
|
|
42
|
+
stale old-name aliases for that id. On trunk sync, the platform canonicalizes the repo filenames to the
|
|
43
|
+
current component name (`58_OldName.groovy` with `name: New Name` becomes `58_NewName.groovy`, plus
|
|
44
|
+
sidecars) and reports those moves in `syncResults.renamed`.
|
|
45
|
+
- **Create:** a file whose id prefix is **not** a live component on the account — including any `new_*` file —
|
|
46
|
+
is created as a **brand-new DB row with a fresh server-assigned id**, and the platform renames the repo files
|
|
47
|
+
to that id (the `Rename X→Y after component creation` / `Delete old file` commits).
|
|
48
|
+
- **Delete:** after the create/update pass, **any live DB component whose id has no matching repo file is
|
|
49
|
+
hard-deleted** (`deleteMissingComponentsFor`), in reverse-dependency order. This runs only when the ZIP
|
|
50
|
+
"looks healthy" (contains `account-info.json` or `README.md`). Exempt from deletion: `auxiliary` components,
|
|
51
|
+
README-purpose prompts, and AGENT-purpose prompts.
|
|
52
|
+
|
|
53
|
+
> ### `auxiliary: true` opts a component OUT of the repo entirely — in BOTH directions
|
|
54
|
+
>
|
|
55
|
+
> This is a silent trap, so know it before you author a sidecar. `auxiliary: true` does not merely
|
|
56
|
+
> "de-emphasize" a component:
|
|
57
|
+
>
|
|
58
|
+
> - **Repo → platform:** the sync **skips the file outright**. A `new_*` component whose `.meta.yml` says
|
|
59
|
+
> `auxiliary: true` is never created, so it **never gets a real id** and the file is never renamed. It
|
|
60
|
+
> looks like the sync silently ignored your work — because it did.
|
|
61
|
+
> - **Platform → repo:** the component's save hooks skip pushing source to GitHub, and repo initialization
|
|
62
|
+
> omits it.
|
|
63
|
+
> - It is also excluded from `getInformation()` (so AI agents do not discover it) and exempt from the
|
|
64
|
+
> deletion pass above.
|
|
65
|
+
>
|
|
66
|
+
> **Use `auxiliary: true` only for genuinely throwaway components** — ad-hoc reports, experiments, and the
|
|
67
|
+
> ephemeral fixtures a Test creates and deletes at runtime (those are created in Groovy with
|
|
68
|
+
> `auxiliary: true` and must never touch the repo).
|
|
69
|
+
>
|
|
70
|
+
> **Use `auxiliary: false` for anything durable** — above all a Test suite that is a regression guard. If you
|
|
71
|
+
> want it versioned in git, addressable by a stable id, or discoverable by another agent, it is not
|
|
72
|
+
> auxiliary. Symptom to recognize: *"I added `new_Foo.groovy`, synced, and it neither appeared on the account
|
|
73
|
+
> nor got renamed."* Check the sidecar's `auxiliary` flag first.
|
|
74
|
+
|
|
75
|
+
**The single most important consequence:** the id in a component's **filename is load-bearing**. If a file's id
|
|
76
|
+
no longer matches its DB row (a renumber or move across ids), the next sync will **create a duplicate at the
|
|
77
|
+
new id and hard-delete the original at the old id**. If a component's files are missing from the repo at sync
|
|
78
|
+
time, that component is **hard-deleted from the DB**. This is exactly how a prior session deleted live schemas
|
|
79
|
+
and an embeddable.
|
|
80
|
+
|
|
81
|
+
**Therefore: never renumber, rename-across-ids, or remove component files as a side effect.** Name-only
|
|
82
|
+
renames are fine when every file keeps the same numeric id; either rename the local filename stem yourself or
|
|
83
|
+
let trunk sync canonicalize it from `.meta.yml`. Before any sync, the repo must already mirror the live DB:
|
|
84
|
+
every live component present at its real id, and nothing extra.
|
|
85
|
+
|
|
86
|
+
### The surfaces and their intended behavior
|
|
87
|
+
|
|
88
|
+
| Command | What it touches | Danger |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `remits-cli components stage` (alias: deprecated `push`) | **Redis staging cache only.** Never mutates the DB or git. The safe iteration surface. | none |
|
|
91
|
+
| `remits-cli components status` | Reads this lane's staging scope (account/user/branch/workspace) and branch resolution, and lists every other lane on the branch. | none |
|
|
92
|
+
| `remits-cli components clear` | Clears THIS lane's staging cache without changing DB or git. Never touches another workspace lane. | none |
|
|
93
|
+
| `remits-cli components sync` **on trunk** | **Server-side git→DB reconcile of the whole account** (create/update/**delete**/rename). Reads the pushed remote; ignores local files. | **high** |
|
|
94
|
+
| `remits-cli components sync` **on a variant branch** | Writes `ComponentVariant` overlays for that branch only. Never touches trunk rows or the account's trunk branch. When the checkout identifies a subscribing account, the branch-local `account-info.json` is refreshed for that subscriber; `--dry-run` reports the plan without writes. | medium (a missing file becomes a **tombstone** that hides the component from subscribers) |
|
|
95
|
+
| `remits-cli components commit` | **One shot:** `git add -A` + commit + `git push` + **`components sync`** + `git pull --ff-only`. Blindly stages the *entire* working tree (including any drift) and reconciles it into prod. Inherits the danger of whichever sync mode the branch selects. | **highest on trunk** |
|
|
96
|
+
|
|
97
|
+
Key implications:
|
|
98
|
+
- **`stage` is always safe** — stage and test as much as you want; it never reconciles or deletes.
|
|
99
|
+
- **`components commit` is the most dangerous command**, not a mere convenience wrapper: it `git add -A`
|
|
100
|
+
commits and pushes whatever is in the working tree, then immediately syncs. Never run it while the tree
|
|
101
|
+
contains drift or unexplained changes. Prefer the explicit, observable
|
|
102
|
+
`git commit → git push → components sync → git pull` sequence so each phase can be inspected.
|
|
103
|
+
- **`components sync` acts on the pushed remote**, so local edits are invisible to it until committed **and
|
|
104
|
+
pushed**, and a drifted **remote** is dangerous even when your local tree looks fine.
|
|
105
|
+
- After a successful non-dry-run `components sync` / `components commit`, the server clears the full
|
|
106
|
+
staging scope for that lane (account/user/branch/workspace). This is the expected clean state: old Redis aliases should not keep shadowing
|
|
107
|
+
the newly synced DB rows. `components sync --dry-run` intentionally leaves staging untouched.
|
|
108
|
+
|
|
109
|
+
### Intended workflows
|
|
110
|
+
|
|
111
|
+
**Change existing components (normal path):**
|
|
112
|
+
1. Edit files under `components/` **keeping each component's existing numeric id** (use `new_*` only for
|
|
113
|
+
genuinely new components). To rename a component, update `name:` in its `.meta.yml`; keep the id prefix
|
|
114
|
+
fixed. Renaming the file stem is optional before trunk sync because the platform will canonicalize it, but
|
|
115
|
+
doing it locally keeps the working tree easier to read.
|
|
116
|
+
2. `remits-cli components stage` → verify in test mode. Iterate (edit → stage → run).
|
|
117
|
+
3. When ready to promote: pass the pre-sync safety check below, then
|
|
118
|
+
`git add -A && git commit && git push`, `remits-cli components sync`, `git pull --ff-only`.
|
|
119
|
+
|
|
120
|
+
**Create a new component:** add `new_Name.groovy` (+ `.json` / `.meta.yml` as applicable). Sync assigns the
|
|
121
|
+
durable id and renames the files. Standalone Prompts live in `components/prompts/new_Name.md`, and their
|
|
122
|
+
sidecar must include `name`, `summary`, `description`, and `purpose` (usually `CUSTOM`). AGENT prompts do
|
|
123
|
+
not live there; they are the `.md` sidecar beside the Utility in `components/agents/`. Do not create a
|
|
124
|
+
direct database row to work around an id/name mismatch, and never create a replacement for a component
|
|
125
|
+
that was unexpectedly deleted or renumbered.
|
|
126
|
+
|
|
127
|
+
**Delete a component (deliberate only):** remove **all** of that component's files from the repo, confirm via
|
|
128
|
+
`git status` that only those files are gone, then sync — the delete phase removes exactly that DB row. Deletion
|
|
129
|
+
is a real, supported outcome of a missing file, which is precisely why an *accidentally* missing or renamed
|
|
130
|
+
file is catastrophic.
|
|
131
|
+
|
|
132
|
+
### Pre-sync safety check (confirm ALL before `components sync` or `components commit`)
|
|
133
|
+
|
|
134
|
+
- **You know which sync mode this branch selects.** `remits-cli components status` states it outright. On a
|
|
135
|
+
variant branch the id/delete/renumber checks below apply to the **overlay set** instead: confirm every
|
|
136
|
+
component absent from the branch is *meant* to be tombstoned for subscribers.
|
|
137
|
+
- The user intends durable platform promotion now — not just local edits, staging, or verification.
|
|
138
|
+
- `git status --short` shows only intended changes; every rename/delete is explained. **No component file has
|
|
139
|
+
been renumbered to a different id.**
|
|
140
|
+
- Local branch is committed and pushed; sync will read the intended remote commit.
|
|
141
|
+
- Local filenames and live inventory (`mcp_account_view`) **agree on id and name for every component**: no live
|
|
142
|
+
component appears locally under a different id, and no expected component is missing a repo file.
|
|
143
|
+
> **Do not run this comparison against `account-info.json` alone — it will report false orphans.** That
|
|
144
|
+
> file omits `auxiliary: true` components by design, so every auxiliary component looks like a repo file
|
|
145
|
+
> with no DB row, i.e. exactly the "a trunk sync will CREATE a duplicate" signal this check exists to
|
|
146
|
+
> catch. It also omits README- and AGENT-purpose Prompts, which live at the repo root and as `.md`
|
|
147
|
+
> sidecars in `components/agents/` rather than in `components/prompts/`, so they look like DB rows with
|
|
148
|
+
> no repo file — the "will be DELETED" signal. Both are benign. Before treating a flagged component as
|
|
149
|
+
> drift, confirm against the live row: `mcp_component_view`, or
|
|
150
|
+
> `mcp_run_action controlAction:"describe"` for an Action. A component that answers is not an orphan.
|
|
151
|
+
- You can state the expected create/update/delete set. **If any delete or renumber is unexpected, stop.**
|
|
152
|
+
|
|
153
|
+
### If something looks wrong — stop, don't paper over
|
|
154
|
+
|
|
155
|
+
If sync reports unexpected `deleted` / `created` / `renamed`, uniqueness errors, or missing components — or you
|
|
156
|
+
discover id drift — **stop. Do not re-run sync, do not `components commit`, and do not create replacement
|
|
157
|
+
components to "make ids line up" or replace a deleted component.** Those actions compound the corruption.
|
|
158
|
+
Preserve the repo-local session log and tool responses, and reconcile source-of-truth first.
|
|
159
|
+
|
|
160
|
+
**Safe recovery pattern (repo ↔ DB drift):**
|
|
161
|
+
1. Establish DB truth: `mcp_account_view` for the full live inventory; `mcp_component_view` to confirm and read
|
|
162
|
+
exact sources.
|
|
163
|
+
2. Fix the **local tree to mirror the live DB** — rename component files back to their real DB ids, reassemble
|
|
164
|
+
any split components, remove orphan/duplicate files, and **refresh any local source that differs from the
|
|
165
|
+
live DB** (the DB is the running truth; a stale local file would overwrite good DB source on sync).
|
|
166
|
+
3. Keep files for any components that were wrongly deleted so sync **re-creates** them (new ids are fine —
|
|
167
|
+
schemas are keyed by title, agents link tools by name).
|
|
168
|
+
4. Make the remote authoritative **non-destructively**: commit the corrected tree, then
|
|
169
|
+
`git merge -s ours origin/<branch>` (keeps your tree, supersedes drifted remote history) and a fast-forward
|
|
170
|
+
`git push` — no force-push.
|
|
171
|
+
5. Run **one** `components sync`: it updates everything to identical, creates the missing components, and
|
|
172
|
+
deletes nothing. Verify with `mcp_account_view`.
|
|
173
|
+
|
|
174
|
+
If the mismatch is a genuine platform/tooling defect (not agent drift), follow the Back-Stage Escalation
|
|
175
|
+
Workflow in `troubleshooting.md` instead of improvising.
|