cinna-cli 0.4.0__tar.gz → 0.4.2__tar.gz
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.
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/PKG-INFO +211 -11
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/README.md +210 -10
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/README.md +6 -4
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/account_workspace/account_workspace.md +7 -2
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/account_workspace/account_workspace_acceptance.md +19 -1
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/account_workspace/account_workspace_tech.md +17 -1
- cinna_cli-0.4.2/docs/features/agent_addons/agent_addons.md +369 -0
- cinna_cli-0.4.2/docs/features/agent_addons/agent_addons_acceptance.md +673 -0
- cinna_cli-0.4.2/docs/features/agent_addons/agent_addons_tech.md +443 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/agent_api/agent_api.md +17 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/agent_api/agent_api_tech.md +3 -1
- cinna_cli-0.4.2/docs/features/agent_management/agent_management.md +270 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/agent_management/agent_management_acceptance.md +145 -8
- cinna_cli-0.4.2/docs/features/agent_management/agent_management_tech.md +324 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/bootstrap_onboarding/bootstrap_onboarding_tech.md +13 -1
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/git_versioning/git_versioning_acceptance.md +3 -3
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/live_sync/live_sync.md +19 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/live_sync/live_sync_acceptance.md +46 -3
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/live_sync/live_sync_tech.md +26 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/remote_chat/remote_chat.md +62 -1
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/remote_chat/remote_chat_acceptance.md +93 -0
- cinna_cli-0.4.2/docs/features/remote_chat/remote_chat_tech.md +274 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/remote_exec/remote_exec.md +10 -4
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/remote_exec/remote_exec_acceptance.md +21 -4
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/remote_exec/remote_exec_tech.md +5 -1
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/pyproject.toml +1 -1
- cinna_cli-0.4.2/src/cinna/account.py +5888 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/chat.py +308 -27
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/cli_version.py +76 -3
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/client.py +454 -1
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/console.py +27 -3
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/context.py +2 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/errors.py +37 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/git_versioning.py +2 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/main.py +1057 -20
- cinna_cli-0.4.2/src/cinna/scenarios.py +602 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/sync.py +4 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/templates/ACCOUNT_CLAUDE.md.template +88 -14
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/templates/CHAT_TESTING.md +15 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/templates/CLAUDE.md.template +100 -26
- cinna_cli-0.4.2/tests/test_account.py +6525 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_chat.py +187 -0
- cinna_cli-0.4.2/tests/test_cli_version.py +150 -0
- cinna_cli-0.4.2/tests/test_client.py +471 -0
- cinna_cli-0.4.2/tests/test_console.py +22 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_context.py +5 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_main.py +124 -1
- cinna_cli-0.4.2/tests/test_scenarios.py +413 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/uv.lock +1 -1
- cinna_cli-0.4.0/docs/features/agent_management/agent_management.md +0 -149
- cinna_cli-0.4.0/docs/features/agent_management/agent_management_tech.md +0 -160
- cinna_cli-0.4.0/docs/features/remote_chat/remote_chat_tech.md +0 -159
- cinna_cli-0.4.0/src/cinna/account.py +0 -2849
- cinna_cli-0.4.0/tests/test_account.py +0 -3298
- cinna_cli-0.4.0/tests/test_cli_version.py +0 -55
- cinna_cli-0.4.0/tests/test_client.py +0 -196
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/.claude/commands/cinna-cli.feature.doc.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/.github/workflows/publish.yml +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/.gitignore +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/LICENSE.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/agent_api/agent_api_acceptance.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/agent_schedules/agent_schedules.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/agent_schedules/agent_schedules_acceptance.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/agent_schedules/agent_schedules_tech.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/bootstrap_onboarding/bootstrap_onboarding.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/bootstrap_onboarding/bootstrap_onboarding_acceptance.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/doctor/doctor.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/doctor/doctor_acceptance.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/doctor/doctor_tech.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/git_versioning/git_versioning.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/git_versioning/git_versioning_tech.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/improvement_requests/improvement_requests.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/improvement_requests/improvement_requests_acceptance.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/improvement_requests/improvement_requests_tech.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/local_agent_import/local_agent_import.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/local_agent_import/local_agent_import_acceptance.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/local_agent_import/local_agent_import_tech.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/mcp_integration/mcp_integration.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/mcp_integration/mcp_integration_acceptance.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/features/mcp_integration/mcp_integration_tech.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/interface.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/docs/mutagen_capabilities.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/scripts/check_docs_references.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/__init__.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/auth.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/bootstrap.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/config.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/doctor.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/improve.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/kit_contract.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/local_import.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/logging.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/mcp_proxy.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/mutagen_runtime.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/sync_session.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/sync_ssh_shim.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/sync_tui.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/templates/GIT_VERSIONING.md +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/src/cinna/templates/__init__.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/__init__.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/conftest.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_auth.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_bootstrap.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_config.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_doctor.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_git_versioning.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_improve.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_kit_contract.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_local_import.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_mutagen_runtime.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_onboarding.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_sync.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_sync_session.py +0 -0
- {cinna_cli-0.4.0 → cinna_cli-0.4.2}/tests/test_sync_ssh_shim.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: cinna-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Local development CLI for Cinna Core agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/opencinna/cinna-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/opencinna/cinna-cli
|
|
@@ -176,13 +176,13 @@ cinna account set-token 'curl -sL https://your-platform.com/api/cli-setup/accoun
|
|
|
176
176
|
|
|
177
177
|
### `cinna account agents`
|
|
178
178
|
|
|
179
|
-
List the agents your account can access (run from inside the account workspace). For each agent: display name + ID, building rights (`✓ can build`, `view-only`, or `foreign install` — installed bundles are publisher-managed and can't be synced), whether a remote environment is active, and whether a local workspace already exists under `agents/`.
|
|
179
|
+
List the agents your account can access (run from inside the account workspace). Ids are printed in full at any terminal width (the column folds rather than ellipsizing — a truncated UUID is a copy-paste trap that the API answers `404 not found` for). For each agent: display name + ID, building rights (`✓ can build`, `view-only`, or `foreign install` — installed bundles are publisher-managed and can't be synced), whether a remote environment is active, and whether a local workspace already exists under `agents/`.
|
|
180
180
|
|
|
181
181
|
### `cinna account status`
|
|
182
182
|
|
|
183
183
|
One-shot summary of the account workspace: platform/frontend URLs, machine name, synced-agent count, and an account-token probe (`valid token` / `expired token` / `no connection`) — the account-level counterpart of `cinna status`.
|
|
184
184
|
|
|
185
|
-
Also reports the workspace's **context package version** against the platform's current one — the orchestrator guides ship in that tree, so a workspace set up before a guide existed silently lacks it. When it is behind, the command says so and points at `cinna account refresh-context`; `cinna improve list` prints the same nudge, since its playbook lives there. Likewise it compares the installed **cinna-cli version** with the one the platform pins (its `/.well-known/cinna-desktop` discovery document) and suggests `uv tool install cinna-cli==<pin>` when behind; no pin means "unknown", not an error.
|
|
185
|
+
Also reports the workspace's **context package version** against the platform's current one — the orchestrator guides ship in that tree, so a workspace set up before a guide existed silently lacks it. When it is behind, the command says so and points at `cinna account refresh-context`; `cinna improve list` prints the same nudge, since its playbook lives there. Likewise it compares the installed **cinna-cli version** with the one the platform pins (its `/.well-known/cinna-desktop` discovery document) and suggests `uv tool install cinna-cli==<pin>` when behind; no pin means "unknown", not an error. An **editable install** (`uv tool install -e`, `pip install -e`) is detected and labelled instead of compared — its metadata records the version it was installed at and never changes again, so pinning that number against the platform's would report skew that does not exist and explain missing features with a version that is not the code being run. It renders as `0.2.5 (editable checkout of /path/to/cinna-cli)`, with the pin named as context, and neither `cinna account status` nor `cinna doctor` nudges an upgrade.
|
|
186
186
|
|
|
187
187
|
With `--json` it prints a single line: `{"result":"ok","workspace",…,"token":"valid|expired|unreachable","synced_agents":N,"agents":[…],"context_package":{"local","remote","state"},"cli":{"installed","required","state"}}`.
|
|
188
188
|
|
|
@@ -211,7 +211,9 @@ cinna account credentials types # types + the
|
|
|
211
211
|
cinna account credentials create --name "Stripe Key" --type api_token \
|
|
212
212
|
--agent billing-agent # create a draft and attach it in one step
|
|
213
213
|
# → prints required fields (e.g. api_token) + a link to fill them in
|
|
214
|
-
cinna account credentials list # name, type, status (complete / needs setup)
|
|
214
|
+
cinna account credentials list # name, type, slot, status (complete / needs setup), id
|
|
215
|
+
cinna account credentials list --json # the raw listing
|
|
216
|
+
cinna account credentials update <cred_id> --service-uri some-token.com # give it the slot a skill declares
|
|
215
217
|
cinna account credentials share-with-agent <cred_id> --agent crm-agent
|
|
216
218
|
cinna account credentials update <cred_id> --name "Stripe (live)"
|
|
217
219
|
cinna account credentials delete <cred_id> --yes
|
|
@@ -263,19 +265,60 @@ cinna agent sync crm-agent
|
|
|
263
265
|
|
|
264
266
|
### `cinna agent sync <agent>`
|
|
265
267
|
|
|
266
|
-
Mint a per-agent CLI token (no UI interaction) and materialize a standard workspace under `agents/<slug
|
|
268
|
+
Mint a per-agent CLI token (no UI interaction) and materialize a standard workspace under `agents/<slug>/<subdir>/` (the Model-A nested layout — `<subdir>` is the slug unless the agent is git-versioned with another one; the command prints the exact path). `<agent>` is the display name, slug, or agent ID from `cinna account agents`. The result is identical to what `cinna setup` produces — own `.cinna/config.json`, registry entry, generated `CLAUDE.md` / `BUILDING_AGENT.md` / MCP configs / `mutagen.yml`, and the initial workspace clone — so afterwards:
|
|
267
269
|
|
|
268
270
|
```bash
|
|
269
|
-
cd agents/hr-manager-agent/
|
|
271
|
+
cd agents/hr-manager-agent/hr-manager-agent/
|
|
270
272
|
cinna dev
|
|
271
273
|
```
|
|
272
274
|
|
|
273
275
|
works exactly as for a manually set-up agent. Synced agents also appear in `cinna list` and in the agent's Integrations-tab session list like any other CLI session. The backend gates minting on building rights: foreign bundle installs and view-only agents are rejected with the server's error message.
|
|
274
276
|
|
|
277
|
+
It also **starts the sync session and flushes it once**, while local and remote are still the same clone, so edits made afterwards sync as plain changes — a session first created by a later `cinna sync push` has no common starting point and reported the builder's own edits as conflicts. If the session cannot start (Mutagen missing, environment unreachable) the sync still succeeds with a warning to run `cinna sync push --agent <slug>` before editing.
|
|
278
|
+
|
|
275
279
|
### `cinna agent unsync <agent>`
|
|
276
280
|
|
|
277
281
|
Detach a synced workspace: stop its sync session, revoke the minted CLI token server-side (via the account-scoped revoke endpoint, authenticated with the account token; idempotent), then perform the equivalent of `cinna disconnect`: remove `.cinna/`, generated files, and the registry entry. Workspace files under `agents/<slug>/workspace/` are preserved. The revoke degrades gracefully — if it fails (no connection, or a workspace synced before token-id tracking), a warning is printed and the local teardown still completes; the token then expires on its own or can be revoked from the agent's Integrations tab.
|
|
278
282
|
|
|
283
|
+
### `cinna agent prompts pull | diff | push <agent> [--dir DIR]`
|
|
284
|
+
|
|
285
|
+
Edit an agent's prompts as files instead of raw `cinna api` calls (whose inline JSON let the shell command-substitute a prompt's Markdown backticks).
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
cinna agent prompts pull crm-agent # → prompts/crm-agent/{workflow,entrypoint,refiner,router_trigger,description}.md + example_prompts.json
|
|
289
|
+
cinna agent prompts diff crm-agent # local edits vs the platform
|
|
290
|
+
cinna agent prompts push crm-agent --dry-run
|
|
291
|
+
cinna agent prompts push crm-agent # one bulk write, then the doc prompts into the running env
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
`pull` records what it pulled in `.pulled.json` and refuses to overwrite unpushed edits, files it did not write, or another agent's prompts without `--force`. `push` sends **only the fields edited since the pull**: a field the platform changed meanwhile is left alone when you did not edit it, and refused when you did (`--force` keeps yours; `pull --force` takes the platform's). After the write it calls the env's prompt sync when a workflow/entrypoint/refiner field changed (`--no-sync-env` to skip; a stopped environment picks them up on its next start). Delete a file to leave its field untouched. The agent config is authoritative — hand-editing the synced `workspace/docs/*.md` as well is a last-writer-wins race.
|
|
295
|
+
|
|
296
|
+
`cinna agent show <agent>` prints each prompt under its `[entrypoint]` / `[workflow]` / `[refiner]` label and each connected credential with its type, slot, setup state and id. `cinna agent rebuild-env <agent>` waits after the rebuild until the environment answers its health check, and says "ready to chat" only then. `cinna agent restart-env` re-runs the same image and does not update the container's core or SDK helpers.
|
|
297
|
+
|
|
298
|
+
### `cinna agent model show | set <agent>`
|
|
299
|
+
|
|
300
|
+
The model is a setting of the agent's environment, not of the agent. `show` prints each mode's SDK, model override, effective model and health; `set` changes only what you pass and rebuilds.
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
cinna agent model show crm-agent
|
|
304
|
+
cinna agent model set crm-agent --conversation haiku # rebuilds, waits for the health check
|
|
305
|
+
cinna agent model set crm-agent --building default --no-rebuild # clear the override; apply on the next rebuild-env
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
`default` clears an override, or with `--conversation-credential` / `--building-credential` unpins an AI credential. The other mode and the credential pins keep their values, a setting already in place is a no-op, and `unknown_model` right after a set is usually a typo in the model id. Refused on a foreign install.
|
|
309
|
+
|
|
310
|
+
### `cinna agent scenarios list | run <agent>`
|
|
311
|
+
|
|
312
|
+
Re-run the agent's recorded `docs/test_scenarios/*.md` — each file's `## Say | Expect` table — without one `cinna chat` per row.
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
cinna agent scenarios list crm-agent
|
|
316
|
+
cinna agent scenarios run crm-agent --out run.md
|
|
317
|
+
cinna agent scenarios run crm-agent scope_and_pushback --yes --json
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Every Say row goes to a fresh session, one after another. Each case reports the reply, the tool calls, the outcome and the session id, under a header naming the conversation model. The run does not judge: mark each row against its Expect. A case that does not complete prints its `cinna chat --attach` command, is not re-sent, and makes the command exit non-zero. The files are read from the synced workspace (`--path DIR` for any other folder) and never pushed.
|
|
321
|
+
|
|
279
322
|
### `cinna agent import <path> [--name TEXT] [--workspace REF] [--update] [--dry-run] [--no-push] [--yes]`
|
|
280
323
|
|
|
281
324
|
Import an agent that was built **locally** with the [Local Agent Kit](docs/features/local_agent_import/local_agent_import.md) — a folder holding a `cinna-agent.json` manifest, typically `../Local/<slug>` next to this account workspace. Run it from the account workspace root (or any folder inside it).
|
|
@@ -295,6 +338,152 @@ The folder rules come from the kit's versioned contract, `.cinna-kit/layout.json
|
|
|
295
338
|
|
|
296
339
|
Where the folder has been published is recorded in `publications.json`, a **sibling** of `cinna-agent.json` holding one entry per Cinna instance — it cannot live inside the manifest, because each entry records a hash of the exported tree and the manifest is part of that tree. Every step is idempotent (agent by the entry whose `platform_url` matches the instance you are logged into, credentials by name, schedules by name), so a partial import is resumed with `--update` instead of duplicating anything. The publication is recorded **only after the push settled** — `--no-push`, a failed flush, or remaining conflicts leave it unrecorded, and the next run is a plain `--update`. A legacy `cloud` block is migrated into the ledger on the first write and is still read until then, so an older folder's `--update` never creates a second agent. `--dry-run` makes no platform call and writes nothing.
|
|
297
340
|
|
|
341
|
+
### `cinna skills list <agent> [--json]`
|
|
342
|
+
|
|
343
|
+
List everything an agent carries beyond its prompt, as one deduplicated list. An **addon** is either an installed plugin or a `skills/<name>/` folder — a `SKILL.md` plus its files that the engine loads on demand. The two overlap (a skill installed from the catalog is *also* a plugin link), and the platform owns the dedupe rule, so this prints the server's projection rather than folding the halves itself: one row per addon, with its kind, source (`marketplace` / `bundle` / `catalog` / `local`), status, name and version.
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
cinna skills list crm-agent
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
Agent: CRM Agent
|
|
351
|
+
Addons (3)
|
|
352
|
+
┏━━━┳━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
|
|
353
|
+
┃ # ┃ Kind ┃ Source ┃ Status ┃ Name ┃ Version ┃
|
|
354
|
+
┡━━━╇━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
|
|
355
|
+
│ 1 │ plugin │ marketplace │ ● ok │ pdf-tools (PDF Tools) │ 2.1.0 │
|
|
356
|
+
│ 2 │ skill │ catalog │ ● ok │ dad-jokes (Dad Jokes) │ 1.0.0 → 1.1.0 │
|
|
357
|
+
│ 3 │ skill │ local │ ● ok │ report · published │ 1.0.1 │
|
|
358
|
+
│ 4 │ skill │ local │ ! secrets │ draft │ │
|
|
359
|
+
└───┴────────┴─────────────┴───────────┴───────────────────────┴───────────────┘
|
|
360
|
+
1 plugin(s), 3 skill(s) (2 of them this agent's own).
|
|
361
|
+
|
|
362
|
+
! 1 installed addon(s) have a newer revision: dad-jokes
|
|
363
|
+
Update with: cinna skills update crm-agent dad-jokes
|
|
364
|
+
|
|
365
|
+
! draft (secrets): This skill holds files that look like key material.
|
|
366
|
+
.env
|
|
367
|
+
|
|
368
|
+
A blank version means no `version:` in the skill's SKILL.md — or an index built
|
|
369
|
+
before skills carried one, which fills in after the next refresh or publish.
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
The **Version** column is what the agent carries (`installed_version`), and an installed addon whose catalog has moved since reads `1.0.0 → 1.1.0` with the update command named under the table — an agent sitting two revisions back must not look identical to a current one. `Name` is the engine-facing folder name — the string `cinna skills publish` takes back — with the display name beside it when they differ. `· published` marks a local skill that already has a catalog package, so a re-publish appends a revision instead of creating a second package. The status column carries the server's own code (`secrets`, `oversized`, `shadowed` for warnings; `missing_description`, `name_mismatch`, `source_unavailable`, `orphan` for errors), and the platform's own sentence for each flagged row — with the offending files for `secrets` — follows under the table. Reads the server's cache, so it never wakes a sleeping environment: when the skill half could not be read the plugin rows still list and the reason is printed (`env_not_running`, `adapter_error`, `parse_error`) instead of a short list looking complete. `--json` prints the raw payload (`addons`, `counts`, `skills_error`) for a script or a local coding agent.
|
|
373
|
+
|
|
374
|
+
When any skill declares credential slots (a `credentials:` block in its `SKILL.md`), a **Credentials** column lists each slot: `✓` filled, `! <reason>` not usable yet, `?` unchecked. Beneath the table each unusable slot gets its fix — e.g. naming the linked `api_token` credential that has no slot with `cinna account credentials update <id> --service-uri <slot>`, or a `credentials create … --service-uri <slot> --agent <agent>` draft when nothing could carry it. For a catalog install the reason is the platform's own (`not_linked`, `not_configured`, `access_revoked`); for a local or bundle skill an older platform computes nothing, so the CLI checks the agent's linked credentials itself (`not_linked`, `not_configured`, `type_mismatch`). A platform that does judge local skills has no `type_mismatch`, so a slot it calls `not_linked` while a linked credential of another type carries it is shown as `type_mismatch` — never as a draft for a second credential on that slot. A slot's value is read from the account credential listing, because the agent's own credential route reports none; a credential shared by someone else whose slot is not visible makes the slot `?`, never `not_linked`. The check is display-only: `--json` stays the raw payload.
|
|
375
|
+
|
|
376
|
+
### `cinna skills publish <agent> <name> [--visibility public|private|users] [--grant EMAIL ...] [--version V] [--notes TEXT] [--package-id ID] [--dry-run] [--yes] [--json]`
|
|
377
|
+
|
|
378
|
+
Publish one of the agent's own skills to the instance skills catalog, where other agents can install it. `<name>` is the folder name from `cinna skills list`. Requires the `agent-developer` role on an agent that is not a foreign install; the skill must be clean (no parse error, no files that look like key material).
|
|
379
|
+
|
|
380
|
+
**It publishes the agent's cloud workspace, not the folder you are standing in.** The files are read from the remote workspace on disk — which is why a *suspended* environment publishes fine, no container needs to be running — but an edit that has not synced yet is not there. Run `cinna sync push` first, or you publish the older remote copy as a revision you cannot take back.
|
|
381
|
+
|
|
382
|
+
**Without `--visibility` the package is private and nobody else sees it.** Say `--visibility public` for the catalog, or `--visibility users` with `--grant` for named people.
|
|
383
|
+
|
|
384
|
+
**The version is derived, not typed.** A skill's version is a line in its own `SKILL.md`, and the platform continues the series for you: the header's version if it has not been published yet, otherwise the next one after the newest release (the last run of digits incremented — `1.0.0`→`1.0.1`, `v3`→`v4`), or `1.0.0` for a skill nobody has versioned. The resolved version is written back into `skills/<name>/SKILL.md` on the environment before the snapshot, so the published bytes carry their own version and your next `cinna sync` brings the stamped header down. `--version` overrides it verbatim for one revision — after which the series continues from *that*. `--dry-run` prints the version, package id and revision number a publish would take, from the same code that will take them, and publishes nothing.
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
cinna skills publish crm-agent report --dry-run
|
|
388
|
+
cinna skills publish crm-agent report --visibility public \
|
|
389
|
+
--notes "Adds the quarterly rollup"
|
|
390
|
+
cinna skills publish crm-agent report --visibility users \
|
|
391
|
+
--grant alice@example.com --grant bob@example.com
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
Re-publish report from CRM Agent
|
|
396
|
+
Version: 1.0.2 (header 1.0.1, latest published 1.0.1)
|
|
397
|
+
Package: com.example.skill.report
|
|
398
|
+
Revision: 3
|
|
399
|
+
Publish? [Y/n]:
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
At a terminal that preview is shown and confirmed before the press; `--yes`, `--json` and `--no-input` publish straight away. `--package-id` is optional too — omitted, it is derived as `<reversed host>.skill.<name>`, with your own publisher slug appended when that id is already taken on the instance (`--dry-run` says when that happened, since a hex tail in your own package id has no other explanation).
|
|
403
|
+
|
|
404
|
+
A re-publish appends a revision to the same package, so `--package-id` (the reverse-DNS id, e.g. `com.acme.report`) is only for a first publish — a mismatch on a later one is refused rather than silently ignored. `--visibility` is likewise honoured on a first publish and on an explicit change; omitting it leaves the package as it is. `--grant` requires `--visibility users` and the CLI refuses the combination otherwise, before anything is written. The server would accept it — it stores the grant either way — but a package that is private or public never consults its grant list, so the publish would report success and share nothing, and a revision cannot be taken back. Within a `users` package `--grant` is strictly **additive**: it adds the addresses it names and never revokes the ones it omits (revoking is `cinna skills revoke`, so a stale publish cannot silently remove access), and an unknown address fails the whole publish rather than half-sharing it. On success the package id, revision and its version, visibility and catalog URL are printed, plus a line saying the version landed in `skills/<name>/SKILL.md` — and a warning instead when it could not be written there, because the header and the catalog have then diverged and the next publish continues from the catalog. A refusal is printed as the platform's own sentence with its code (`not_developer`, `foreign_install`, `no_environment`, `workspace_unavailable`, `package_id_immutable`, `skill_contains_secrets` — which also lists the offending files), and `--json` prints `{revision, package, catalog_url, skill_md_updated}` instead of the human block (`--dry-run --json` prints the preview payload).
|
|
405
|
+
|
|
406
|
+
### `cinna skills catalog [--search Q] [--mine] [--json]`
|
|
407
|
+
|
|
408
|
+
Browse the instance skills catalog: one row per package this account may see, with its reverse-DNS **package id**, display name, visibility and newest version. The package id — `com.acme.pdf-report`, not a UUID — is the reference every other package verb takes. A delisted package is marked as such beside its visibility.
|
|
409
|
+
|
|
410
|
+
The route takes no parameters — it answers the whole visible catalogue — so `--search` (matching the id, name and description) and `--mine` (packages this account can manage) narrow the rows locally. `--json` prints the filtered rows, not the raw envelope.
|
|
411
|
+
|
|
412
|
+
### `cinna skills show <package> [--revision N] [--json]`
|
|
413
|
+
|
|
414
|
+
One package in full: its display name, visibility, newest version and package UUID, then the revision table, then the `SKILL.md` of the newest revision (or the one `--revision` names). `<package>` is a package id, a display name, or a UUID. The `SKILL.md` is printed as plain text — it is someone else's file and may contain anything — and a content fetch that fails degrades the output rather than the command, because the package detail is the answer.
|
|
415
|
+
|
|
416
|
+
### `cinna skills revisions <package> [--json]`
|
|
417
|
+
|
|
418
|
+
A package's revisions, **newest first**: number, version, release date, size and the release notes given at publish time. A revision is immutable, so this is the question a publisher has before every publish — what is already out there — and the answer to it no longer requires `cinna api` and a UUID. Pair it with `cinna skills publish <agent> <name> --dry-run`, which says what the *next* one would be.
|
|
419
|
+
|
|
420
|
+
### `cinna skills files <package> [--revision N] [--json]`
|
|
421
|
+
|
|
422
|
+
The files one revision ships, with sizes and the total. A file list the server truncated says so.
|
|
423
|
+
|
|
424
|
+
There is no `download` verb, for two reasons: installing a skill lands it in the agent's own workspace, which sync brings down to the local mirror — so the bytes already arrive that way — and the archive routes are binary, which the JSON-only escape hatch could not carry anyway.
|
|
425
|
+
|
|
426
|
+
### `cinna skills install <agent> <package> [--revision N] [--conversation-only|--building-only] [--json]`
|
|
427
|
+
|
|
428
|
+
Install a catalog package onto an agent. `<agent>` is a name, slug or id; `<package>` is a package id, display name or UUID — the CLI resolves both, so neither a raw UUID nor a hand-built JSON body is needed.
|
|
429
|
+
|
|
430
|
+
```bash
|
|
431
|
+
cinna skills catalog --search jokes
|
|
432
|
+
cinna skills install crm-agent localhost.skill.dad-jokes
|
|
433
|
+
cinna skills install crm-agent localhost.skill.dad-jokes --revision 2 --conversation-only
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
Omitting `--revision` installs whatever the catalog calls latest *now*; because a revision is immutable, the install pins bytes that will not change under the agent until `cinna skills update` moves it. Both modes are on unless `--conversation-only` / `--building-only` narrows where the skill is offered (naming both is refused — it would install a skill offered nowhere).
|
|
437
|
+
|
|
438
|
+
Installing something the agent already carries is answered as a sentence, not a JSON body: the platform's own `already_installed` refusal followed by either "already at the newest revision" or the `cinna skills update` that closes the gap. The `--json` error code stays `already_installed`.
|
|
439
|
+
|
|
440
|
+
### `cinna skills update <agent> <name> [--json]`
|
|
441
|
+
|
|
442
|
+
Move an installed skill to the package's newest revision, printing the version it moved from and to. `<name>` is the name `cinna skills list` prints; the plugin-link id the route actually addresses is resolved internally. The listing's `has_update` is *reported*, never used to skip the call — it comes from a cache, and the upgrade route is what decides.
|
|
443
|
+
|
|
444
|
+
Every install / uninstall / update / toggle also pushes the change into the agent's running environments, and that push can partly fail while the call itself succeeds. When it does, the command says how many environments did not take it and points at `cinna agent restart-env` — a green check alone would hide the one case where the catalog and the live agent disagree. An environment built *before* the feature existed is reported separately (`unsupported_syncs`): the link write is complete and there is nothing to retry, so that half points at `cinna agent rebuild-env` and suppresses the plain success line rather than offering a restart that cannot change the outcome.
|
|
445
|
+
|
|
446
|
+
### `cinna skills uninstall <agent> <name> [--yes] [--json]`
|
|
447
|
+
|
|
448
|
+
Remove an agent's copy of an installed skill. The package and its revisions are untouched — what the agent held was a copy, not a reference. Asks first unless `--yes`. An agent's *own* `skills/<name>/` folder is not an install, and the command says so rather than failing on a route that could never match it.
|
|
449
|
+
|
|
450
|
+
### `cinna skills toggle <agent> <name> [--enable|--disable] [--conversation-mode|--no-conversation-mode] [--building-mode|--no-building-mode] [--json]`
|
|
451
|
+
|
|
452
|
+
Enable or disable an installed skill, or change where it is offered, without removing it. Every switch defaults to "leave it alone" and only the ones named are sent, so `--disable` cannot silently reset the mode flags a previous call set. Naming no switch at all is a usage error rather than a no-op call. A disabled install still lists and still reports its version — it is not an error — so `cinna skills list` marks it `· disabled`.
|
|
453
|
+
|
|
454
|
+
### `cinna skills refresh <agent> [--json]`
|
|
455
|
+
|
|
456
|
+
Rebuild the agent's addon index, reporting how many skills were indexed. Everything else in this group reads the platform's cache — which is what makes it safe against a sleeping environment, and what makes a stale index possible. This is the remedy when `cinna skills list` reports `parse_error`, or shows no version for a skill whose `SKILL.md` has one. It is *not* the remedy for every reason code — see below. The plugin half is refreshed too where the platform offers that route; a platform without it still refreshes the skill half and says so.
|
|
457
|
+
|
|
458
|
+
A refresh that still could not read the index answers **200 with the reason** — so this prints the reason and the remedy *that reason* has, rather than a green check. The four codes do not share a fix, and both `skills refresh` and `skills list` route through the same table:
|
|
459
|
+
|
|
460
|
+
| Code | What it means | The fix it prints |
|
|
461
|
+
|---|---|---|
|
|
462
|
+
| `env_not_running` | The environment is asleep | Send it a message, or refresh again, to wake it |
|
|
463
|
+
| `adapter_error` | Up, but not answering | `cinna agent restart-env <agent>` |
|
|
464
|
+
| `adapter_unsupported` | Built before agent skills existed; no skills endpoint to answer | `cinna agent rebuild-env <agent>` |
|
|
465
|
+
| `parse_error` | Answered, but the index did not parse | `cinna skills refresh <agent>` |
|
|
466
|
+
|
|
467
|
+
An unrecognised code gets a generic "refresh again, then check the logs" and names **no** verb: a code whose fix this build cannot name is one where guessing a verb sends the caller round a loop that cannot close. That is exactly what the old copy did to `adapter_unsupported` — it printed one hardcoded remedy for every code, so a container missing the route was told to restart (which re-runs the same image) or, in `skills list`, to "Rebuild it with: cinna skills refresh" (which re-reads a route that is not there, and calls a refresh a rebuild).
|
|
468
|
+
|
|
469
|
+
### `cinna skills grants <package> [--json]` · `grant <package> --user EMAIL` · `revoke <package> --user EMAIL [--yes]`
|
|
470
|
+
|
|
471
|
+
Who is named on a package, and adding or removing one. Visibility and grants belong to the *package*, not to a revision, so changing them costs no new revision — this is the post-publish half of `cinna skills publish --grant`.
|
|
472
|
+
|
|
473
|
+
A grant list is stored on any package but only *consulted* on one whose visibility is `users`, so `grants` prints the visibility beside the rows and both verbs warn when the list is being ignored. `revoke` takes the same email `grant` did and resolves it to the user id the route actually addresses; an address that was never granted is a sentence naming who actually is.
|
|
474
|
+
|
|
475
|
+
### `cinna skills visibility <package> <public|private|users> [--json]`
|
|
476
|
+
|
|
477
|
+
Change who may see a package after it was published. Switching to `users` with nobody named warns that it shares the package with nobody — the one setting that looks like sharing and is not.
|
|
478
|
+
|
|
479
|
+
### `cinna skills delist <package> [--yes] [--json]`
|
|
480
|
+
|
|
481
|
+
Take a package out of the catalog. Agents that already installed it keep what they have: a revision they hold is a copy, not a reference. Asks first unless `--yes`. Deleting a package outright is still web-UI only.
|
|
482
|
+
|
|
483
|
+
### `cinna skills relist <package> [--json]`
|
|
484
|
+
|
|
485
|
+
Put a delisted package back. `delist` has no inverse route of its own — without this verb the only way back would be `cinna api`, which would make delisting the one door in this group that opens only outwards.
|
|
486
|
+
|
|
298
487
|
### `cinna connect agent-api --producer <agent> --consumer <agent> [--label TEXT] [--read-only]`
|
|
299
488
|
|
|
300
489
|
Wire one agent to another's REST API from the account workspace. Resolves both agents (name, slug, or ID), mints a producer API token, and attaches it to the consumer as a credential — which rides the consumer's normal credential sync into its remote environment, so no key ever touches your machine. Prints the credential ID, token prefix, base URL, and spec URL. `--read-only` restricts the consumer to read-only access; `--label` names the credential. Backend errors surface verbatim: 400 if the producer's REST API is disabled, 403/404 for ownership violations.
|
|
@@ -319,8 +508,13 @@ Generic escape hatch into the platform API, authenticated with the account token
|
|
|
319
508
|
- The inner response is passed through verbatim: the body prints to stdout (pretty-printed for JSON) and the exit code is `0` for 2xx and `1` for an inner 4xx/5xx — so it composes in shell pipelines.
|
|
320
509
|
- When the escape hatch itself refuses the call, the detail prints to stderr and the exit code is `2`: policy denials (credentials, user management, admin, CLI, MFA/auth, and streaming routes are excluded — shown as `blocked by platform policy: …`), rate limiting (429, with the Retry-After delay), and request/response size caps (413/502).
|
|
321
510
|
|
|
511
|
+
`<path>` accepts the same **agent references** the rest of the CLI does: a segment straight after `agents/` that is not already a UUID is resolved against the account's agent listing, and the substitution is announced on stderr so a `--json` stdout stream stays pure. Resolution is sugar and never breaks the hatch — a reference that does not resolve (or an agent listing that cannot be reached) leaves the path exactly as typed, because `agents/` is a route prefix as well as a collection.
|
|
512
|
+
|
|
513
|
+
A path segment carrying an **elided id** (`agents/f0506e24-3740-4fe3…/addons`, copied out of a table cell too narrow to print it whole) is refused locally, before any request. The API would answer `404 Agent not found` for it, which reads as a missing agent rather than a mangled id.
|
|
514
|
+
|
|
322
515
|
```bash
|
|
323
516
|
cinna api GET agents
|
|
517
|
+
cinna api GET agents/crm-agent/addons # resolved to agents/<uuid>/addons
|
|
324
518
|
cinna api GET agents --query limit=5
|
|
325
519
|
cinna api PATCH agents/3fa85f64-5717-4562-b3fc-2c963f66afa6 --json '{"description": "updated"}'
|
|
326
520
|
cinna api POST tasks --data @task.json
|
|
@@ -339,6 +533,9 @@ Run it from the account workspace (or any synced agent folder under it). The rep
|
|
|
339
533
|
- Each `message` carries the agent's reasoning/tool trace under **`events`** — an ordered list of the `thinking` blocks, `tool` calls (with their full `tool_input` payload) and tool results behind the reply, so you see *what the agent did*, not just its final `content`. Pass `--no-events` to drop the trace and keep only the final text.
|
|
340
534
|
- Files the agent attaches to its replies are downloaded under `./cinna-chat-files/<session_id>/` (override with `--download-dir`, or skip with `--no-download` to just report the file ids). Downloads are bounded by the api-proxy's 8 MiB response cap.
|
|
341
535
|
- `--interval` / `--timeout` tune the poll cadence and the maximum wait for a turn. Ctrl-C interrupts the agent's turn and exits.
|
|
536
|
+
- A poll request that fails transiently (a proxy timeout, a 429, a 5xx) is **retried within `--timeout`**, each retry announced as a `warning` event — the turn runs on the platform regardless. If contact is lost for good the command exits `12` with an `error` event carrying `session_id` and `recover`.
|
|
537
|
+
- The closing `done` event always carries `outcome` — `completed`, `timeout` or `not_started` (`in_progress` / `idle` for `--show`) — plus `recover` when the turn may still be running.
|
|
538
|
+
- `--attach <session_id>` sends nothing: it waits for that session's current turn and prints it, the way back into a turn a dead command left running (Ctrl-C only stops watching). `--show <session_id>` prints a session's transcript once and waits for nothing.
|
|
342
539
|
|
|
343
540
|
```bash
|
|
344
541
|
cinna chat --agent crm-agent "Summarize today's leads"
|
|
@@ -346,9 +543,11 @@ cinna chat --agent crm-agent --file report.csv "Validate this export"
|
|
|
346
543
|
cinna chat --resume 3fa85f64-5717-4562-b3fc-2c963f66afa6 "Now break it down by region"
|
|
347
544
|
echo "ping" | cinna chat --agent crm-agent # message from stdin
|
|
348
545
|
cinna chat --agent crm-agent "hi" | jq -c 'select(.event=="message")'
|
|
546
|
+
cinna chat --attach 3fa85f64-5717-4562-b3fc-2c963f66afa6 # recover a turn after a timeout
|
|
547
|
+
cinna chat --show 3fa85f64-5717-4562-b3fc-2c963f66afa6 # read a transcript
|
|
349
548
|
```
|
|
350
549
|
|
|
351
|
-
The session id is printed in the first `session` event — capture it to drive a multi-turn conversation with `--resume`.
|
|
550
|
+
The session id is printed in the first `session` event — capture it to drive a multi-turn conversation with `--resume`, or to re-attach with `--attach`.
|
|
352
551
|
|
|
353
552
|
### `cinna dev`
|
|
354
553
|
|
|
@@ -370,8 +569,8 @@ cinna redev # remote wins the initial conflicts, then a normal dev session
|
|
|
370
569
|
Inspect and drive the sync session. `status` / `conflicts` are read-only views (safe alongside a live `cinna dev`); `push` / `pull` / `resolve` are for scripted (headless) builders who aren't running the TUI. All accept `--agent <ref>` to target a synced child workspace from the account root.
|
|
371
570
|
|
|
372
571
|
- `status` — state, pending changes, conflict count. Warns loudly when conflicts mean your edits aren't fully live.
|
|
373
|
-
- `conflicts` — list conflicted paths (sourced from the Mutagen daemon, so it agrees with `status`; two-way-safe writes no `.conflict.*` files on disk).
|
|
374
|
-
- `push [--force]` — ensure a session, then flush and block until settled. `--force` resolves any parked conflicts in favor of **local** first ("my local is the truth"). The session persists in the daemon so later edits keep syncing.
|
|
572
|
+
- `conflicts [--diff]` — list conflicted paths (sourced from the Mutagen daemon, so it agrees with `status`; two-way-safe writes no `.conflict.*` files on disk). `--diff` compares both copies of each path — size, sha256, a unified diff (remote → local) for text, and "identical content" / "only one copy exists" when the facts say so — reading the remote side in one `cinna exec`, and still showing the local side if the environment cannot answer.
|
|
573
|
+
- `push [--force]` — ensure a session, then flush and block until settled. `--force` resolves any parked conflicts in favor of **local** first ("my local is the truth"). The session persists in the daemon so later edits keep syncing. A flush that ends with conflicts never prints "Sync settled": it warns with the count and points at `conflicts --diff`. (`cinna agent sync` already started the session on the fresh clone, so edits made after attaching don't come back as conflicts.)
|
|
375
574
|
- `pull [--force]` — the mirror; `--force` resolves in favor of **remote** (e.g. after the backend regenerates managed files).
|
|
376
575
|
- `resolve --prefer local|remote` — clear parked conflicts in one command. `local` deletes the remote losing copies (your version propagates out); `remote` backs up your local copies under `.cinna/sync/` and takes the container's version. Replaces the manual kill/delete/restart dance.
|
|
377
576
|
|
|
@@ -379,7 +578,7 @@ Inspect and drive the sync session. `status` / `conflicts` are read-only views (
|
|
|
379
578
|
|
|
380
579
|
Stream a command through the platform to the remote agent environment. Output streams back live; Ctrl+C aborts. Exit code matches the remote process.
|
|
381
580
|
|
|
382
|
-
The command runs with the **workspace root (`/app/workspace`) as its working directory**, so relative paths resolve against the synced workspace — e.g. `cinna exec python scripts/main.py` runs `/app/workspace/scripts/main.py` (the same cwd the scheduler uses). No need to prefix paths with `/app/workspace/`.
|
|
581
|
+
The command runs with the **workspace root (`/app/workspace`) as its working directory**, so relative paths resolve against the synced workspace — e.g. `cinna exec python scripts/main.py` runs `/app/workspace/scripts/main.py` (the same cwd the scheduler uses). No need to prefix paths with `/app/workspace/`. `--cwd /app` starts at the container's app root instead. The command must be a program, not a shell builtin — hand pipes, redirects and `&&` to a shell: `cinna exec sh -c 'a | b'`.
|
|
383
582
|
|
|
384
583
|
Arguments pass through transparently — each token is re-quoted before being sent, so spaces and shell metacharacters inside an argument survive intact. Use ordinary single-level quoting, exactly as for a local command. To run a shell snippet (pipes, redirects, `&&`), pass it to a shell explicitly: `cinna exec bash -c '…'`.
|
|
385
584
|
|
|
@@ -417,6 +616,7 @@ It detects and fixes:
|
|
|
417
616
|
- **Orphaned sessions** — `cinna-*` sessions with no registry entry at all. Terminated.
|
|
418
617
|
- **Active sessions** — the healthy, still-watching sessions left over from past `cinna dev` runs. They are not broken, but they keep the shared Mutagen daemon busy and are recreated on demand, so doctor offers to clear them as a separate step.
|
|
419
618
|
- **Expired tokens** — for **account-managed** workspaces (those under an account root), the CLI token is re-minted automatically through the parent account token, no pasting required. **Standalone** workspaces (set up via `cinna setup`) can only be refreshed with a pasted setup token, so they are reported with a `cinna set-token` hint rather than changed.
|
|
619
|
+
- **cinna-cli behind the platform pin** — one report-only finding per platform whose discovery document pins a different version. An **editable install** raises none: its recorded version is a snapshot of the day it was installed, not the code that runs, so "behind the pin" would be a confident wrong answer — and one that invites missing features to be misdiagnosed as version skew.
|
|
420
620
|
- **Expired account token** — a sub-agent token can only be re-minted while the **account** token that mints it is still valid. When the account token has itself expired, doctor probes it once and surfaces a single _"renew the account token — run `cinna login`"_ finding (listing the blocked sub-agents) instead of a pile of re-mints that would all fail with 401. Run `cinna login`, then re-run `cinna doctor` to re-mint the dependents.
|
|
421
621
|
|
|
422
622
|
```bash
|
|
@@ -502,7 +702,7 @@ claude # or: opencode
|
|
|
502
702
|
|
|
503
703
|
## Sync & Conflict Resolution
|
|
504
704
|
|
|
505
|
-
`cinna sync` drives Mutagen in `two-way-safe` mode with VCS-aware ignores (including the backend-managed `credentials/` directory, so it never conflicts on files you're told not to edit). When the same file changes on both sides, Mutagen parks a conflict (it does **not** pick a winner, and does not write `.conflict.*` files in this mode) — list them with `cinna sync conflicts
|
|
705
|
+
`cinna sync` drives Mutagen in `two-way-safe` mode with VCS-aware ignores (including the backend-managed `credentials/` directory, so it never conflicts on files you're told not to edit). When the same file changes on both sides, Mutagen parks a conflict (it does **not** pick a winner, and does not write `.conflict.*` files in this mode) — list them with `cinna sync conflicts` (add `--diff` to compare the two copies of each), then clear them with `cinna sync resolve --prefer local` (your edits win) or `--prefer remote` (the container's version wins). For a non-interactive flush, `cinna sync push` / `cinna sync pull` settle the session and exit.
|
|
506
706
|
|
|
507
707
|
Large binary files and build artifacts are ignored by default (see `mutagen.yml`). Add your own ignores there if needed.
|
|
508
708
|
|