cinna-cli 0.5.3__tar.gz → 0.6.0__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.
Files changed (128) hide show
  1. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/PKG-INFO +24 -2
  2. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/README.md +23 -1
  3. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/README.md +10 -1
  4. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/account_workspace/account_workspace.md +7 -1
  5. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_addons/agent_addons.md +14 -0
  6. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_addons/agent_addons_acceptance.md +26 -1
  7. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_addons/agent_addons_tech.md +14 -2
  8. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_management/agent_management.md +19 -2
  9. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_management/agent_management_tech.md +7 -1
  10. cinna_cli-0.6.0/docs/features/dashboards/dashboards.md +224 -0
  11. cinna_cli-0.6.0/docs/features/dashboards/dashboards_acceptance.md +271 -0
  12. cinna_cli-0.6.0/docs/features/dashboards/dashboards_tech.md +239 -0
  13. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/live_sync/live_sync.md +13 -0
  14. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/live_sync/live_sync_acceptance.md +24 -0
  15. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/live_sync/live_sync_tech.md +21 -4
  16. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/local_agent_import/local_agent_import.md +10 -3
  17. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/local_agent_import/local_agent_import_tech.md +2 -1
  18. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/remote_chat/remote_chat.md +13 -0
  19. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/pyproject.toml +1 -1
  20. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/account.py +182 -2
  21. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/chat.py +84 -4
  22. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/client.py +213 -13
  23. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/config.py +11 -0
  24. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/context.py +113 -0
  25. cinna_cli-0.6.0/src/cinna/dashboards.py +1648 -0
  26. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/errors.py +50 -0
  27. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/kit_contract.py +1 -0
  28. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/local_import.py +47 -1
  29. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/main.py +66 -3
  30. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/sync_session.py +86 -2
  31. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/templates/ACCOUNT_CLAUDE.md.template +18 -3
  32. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/templates/CLAUDE.md.template +16 -4
  33. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_account.py +120 -1
  34. cinna_cli-0.6.0/tests/test_dashboards.py +768 -0
  35. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_kit_contract.py +1 -0
  36. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_sync_session.py +85 -0
  37. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/uv.lock +1 -1
  38. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/.claude/commands/cinna-cli.feature.doc.md +0 -0
  39. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/.github/workflows/publish.yml +0 -0
  40. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/.gitignore +0 -0
  41. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/LICENSE.md +0 -0
  42. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/account_workspace/account_workspace_acceptance.md +0 -0
  43. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/account_workspace/account_workspace_tech.md +0 -0
  44. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_api/agent_api.md +0 -0
  45. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_api/agent_api_acceptance.md +0 -0
  46. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_api/agent_api_tech.md +0 -0
  47. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_management/agent_management_acceptance.md +0 -0
  48. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_schedules/agent_schedules.md +0 -0
  49. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_schedules/agent_schedules_acceptance.md +0 -0
  50. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/agent_schedules/agent_schedules_tech.md +0 -0
  51. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/artifacts/artifacts.md +0 -0
  52. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/artifacts/artifacts_acceptance.md +0 -0
  53. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/artifacts/artifacts_tech.md +0 -0
  54. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/bootstrap_onboarding/bootstrap_onboarding.md +0 -0
  55. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/bootstrap_onboarding/bootstrap_onboarding_acceptance.md +0 -0
  56. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/bootstrap_onboarding/bootstrap_onboarding_tech.md +0 -0
  57. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/delegation/delegation.md +0 -0
  58. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/delegation/delegation_acceptance.md +0 -0
  59. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/delegation/delegation_tech.md +0 -0
  60. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/doctor/doctor.md +0 -0
  61. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/doctor/doctor_acceptance.md +0 -0
  62. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/doctor/doctor_tech.md +0 -0
  63. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/git_versioning/git_versioning.md +0 -0
  64. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/git_versioning/git_versioning_acceptance.md +0 -0
  65. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/git_versioning/git_versioning_tech.md +0 -0
  66. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/improvement_requests/improvement_requests.md +0 -0
  67. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/improvement_requests/improvement_requests_acceptance.md +0 -0
  68. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/improvement_requests/improvement_requests_tech.md +0 -0
  69. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/local_agent_import/local_agent_import_acceptance.md +0 -0
  70. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/mcp_integration/mcp_integration.md +0 -0
  71. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/mcp_integration/mcp_integration_acceptance.md +0 -0
  72. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/mcp_integration/mcp_integration_tech.md +0 -0
  73. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/remote_chat/remote_chat_acceptance.md +0 -0
  74. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/remote_chat/remote_chat_tech.md +0 -0
  75. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/remote_exec/remote_exec.md +0 -0
  76. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/remote_exec/remote_exec_acceptance.md +0 -0
  77. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/remote_exec/remote_exec_tech.md +0 -0
  78. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/team_library/team_library.md +0 -0
  79. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/team_library/team_library_acceptance.md +0 -0
  80. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/features/team_library/team_library_tech.md +0 -0
  81. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/interface.md +0 -0
  82. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/docs/mutagen_capabilities.md +0 -0
  83. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/scripts/check_docs_references.py +0 -0
  84. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/__init__.py +0 -0
  85. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/artifacts.py +0 -0
  86. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/auth.py +0 -0
  87. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/bootstrap.py +0 -0
  88. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/cli_version.py +0 -0
  89. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/console.py +0 -0
  90. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/delegation.py +0 -0
  91. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/doctor.py +0 -0
  92. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/git_versioning.py +0 -0
  93. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/improve.py +0 -0
  94. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/library.py +0 -0
  95. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/logging.py +0 -0
  96. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/mcp_proxy.py +0 -0
  97. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/mutagen_runtime.py +0 -0
  98. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/scenarios.py +0 -0
  99. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/sync.py +0 -0
  100. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/sync_ssh_shim.py +0 -0
  101. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/sync_tui.py +0 -0
  102. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/templates/CHAT_TESTING.md +0 -0
  103. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/templates/GIT_VERSIONING.md +0 -0
  104. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/src/cinna/templates/__init__.py +0 -0
  105. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/__init__.py +0 -0
  106. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/conftest.py +0 -0
  107. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_agent_api_access.py +0 -0
  108. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_artifacts.py +0 -0
  109. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_auth.py +0 -0
  110. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_bootstrap.py +0 -0
  111. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_chat.py +0 -0
  112. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_cli_version.py +0 -0
  113. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_client.py +0 -0
  114. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_config.py +0 -0
  115. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_console.py +0 -0
  116. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_context.py +0 -0
  117. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_delegation.py +0 -0
  118. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_doctor.py +0 -0
  119. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_git_versioning.py +0 -0
  120. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_improve.py +0 -0
  121. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_library.py +0 -0
  122. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_local_import.py +0 -0
  123. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_main.py +0 -0
  124. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_mutagen_runtime.py +0 -0
  125. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_onboarding.py +0 -0
  126. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_scenarios.py +0 -0
  127. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/tests/test_sync.py +0 -0
  128. {cinna_cli-0.5.3 → cinna_cli-0.6.0}/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.5.3
3
+ Version: 0.6.0
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
@@ -405,6 +405,8 @@ At a terminal that preview is shown and confirmed before the press; `--yes`, `--
405
405
 
406
406
  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).
407
407
 
408
+ **A publish from the CLI is never refused as stale.** It goes through the agent path, which records the package's latest revision as the new one's base (`cinna skills revisions` shows it under **Based on**), so another maintainer's newer version is built on, not checked against. Cinna Desktop's Share instead sends the base its folder holds, and core refuses that share (`stale_base`) when a co-maintainer has shared a newer version since; the CLI never makes that call.
409
+
408
410
  ### `cinna skills catalog [--search Q] [--mine] [--json]`
409
411
 
410
412
  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.
@@ -417,7 +419,7 @@ One package in full: its display name, visibility, newest version and package UU
417
419
 
418
420
  ### `cinna skills revisions <package> [--json]`
419
421
 
420
- 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.
422
+ A package's revisions, **newest first**: number, version, release date, size, **Shared by** (who published it, `—` once that account is deleted), **Based on** (`Version N`, the revision the sharer's copy held; `—` for a first revision, a share from an older Cinna Desktop, and any revision published before core recorded it) and the release notes given at publish time. A server older than skill co-maintainers sends neither field and both columns read `—`. `--json` passes the server's `published_by` and `base_revision_number` through untouched. 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.
421
423
 
422
424
  ### `cinna skills files <package> [--revision N] [--json]`
423
425
 
@@ -609,6 +611,26 @@ cinna artifacts link create 3fa85f64 --expires 7d --code
609
611
 
610
612
  The printed page link is a valid `link` artifact for `cinna delegation report --artifact`.
611
613
 
614
+ ### `cinna dashboards list | show | check | run | ref | boards | board create | add | tiles | tile …`
615
+
616
+ Build, check, run and place an agent's **dashboard components**: folders in the agent's `dashboards/<name>/` (`component.json` plus endpoint scripts or a page) that the owner keeps as live tiles on a dashboard. Run from the account workspace. `AGENT` is a name, slug, id, or `.` for the agent workspace you are in. Every verb first checks the server's dashboards capability. While an environment wakes, verbs retry for `--timeout` seconds (default 120). Verbs that read the agent's cloud copy push your pending local edits first (`--no-flush` skips that).
617
+
618
+ - `list AGENT` · `show AGENT NAME [--skill S]` (`--skill` names a component a skill ships, on every verb that takes `NAME`): the components as the environment sees them (checker findings, where each is placed, including "Cinna Desktop") and the **reference** line `cinna://component/bundle:<bundle_id>/<name>` that offers one.
619
+ - `check AGENT [NAME] [--run]`: the owner's card checks; `--run` also runs each source in the environment through `cinna exec` (never locally). Exits 1 on any error.
620
+ - `run AGENT NAME [--endpoint E] [--param k=v]… [--params @file.json]`: run it exactly as a tile would. `--json` prints `{result, value, params_resolved, notice, fetched_at}`, where `value` is exactly what a tile receives.
621
+ - `ref AGENT NAME [--check]`: print only the reference line; `--check` asks core whether it resolves.
622
+ - `boards` · `board create NAME` · `add AGENT NAME --board B [--new-board] [--size s|m|l|wide|tall] [--param k=v] [--title T] [--max-age 15m] [--every 5m|manual] [--after-turn]`: the owner's web dashboards; place a tile (refused for a component with errors or a full dashboard).
623
+ - `tiles BOARD` · `tile data|refresh|params|call|edit|remove BOARD TILE …`: read and drive tiles. `tile params --set/--clear/--reset` sends the whole set; `tile edit` changes title (`''` resets it), size and refresh overrides. Tiles on Cinna Desktop's dashboards are read-only here.
624
+ - `cinna chat --agent AGENT --board B [--focus TILE] [--context @file.json] [--new-chat] "…"`: talk in the agent's dashboard chat, where it has its tile tools.
625
+
626
+ ```bash
627
+ cinna dashboards check crm-agent deals --run
628
+ cinna dashboards run crm-agent deals --param stage=won
629
+ cinna dashboards ref crm-agent deals --check
630
+ cinna dashboards add crm-agent deals --board Sales --size l
631
+ cinna chat --agent crm-agent --board Sales --focus deals "Show only won deals"
632
+ ```
633
+
612
634
  ### `cinna dev`
613
635
 
614
636
  Start a foreground dev session — creates / resumes the Mutagen sync session for this workspace and attaches the terminal to a two-tab TUI (status + raw Mutagen details). Ctrl-C terminates the session; sync does not outlive the TUI. To observe sync from another terminal without affecting it, use `cinna sync status`.
@@ -368,6 +368,8 @@ At a terminal that preview is shown and confirmed before the press; `--yes`, `--
368
368
 
369
369
  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).
370
370
 
371
+ **A publish from the CLI is never refused as stale.** It goes through the agent path, which records the package's latest revision as the new one's base (`cinna skills revisions` shows it under **Based on**), so another maintainer's newer version is built on, not checked against. Cinna Desktop's Share instead sends the base its folder holds, and core refuses that share (`stale_base`) when a co-maintainer has shared a newer version since; the CLI never makes that call.
372
+
371
373
  ### `cinna skills catalog [--search Q] [--mine] [--json]`
372
374
 
373
375
  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.
@@ -380,7 +382,7 @@ One package in full: its display name, visibility, newest version and package UU
380
382
 
381
383
  ### `cinna skills revisions <package> [--json]`
382
384
 
383
- 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.
385
+ A package's revisions, **newest first**: number, version, release date, size, **Shared by** (who published it, `—` once that account is deleted), **Based on** (`Version N`, the revision the sharer's copy held; `—` for a first revision, a share from an older Cinna Desktop, and any revision published before core recorded it) and the release notes given at publish time. A server older than skill co-maintainers sends neither field and both columns read `—`. `--json` passes the server's `published_by` and `base_revision_number` through untouched. 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.
384
386
 
385
387
  ### `cinna skills files <package> [--revision N] [--json]`
386
388
 
@@ -572,6 +574,26 @@ cinna artifacts link create 3fa85f64 --expires 7d --code
572
574
 
573
575
  The printed page link is a valid `link` artifact for `cinna delegation report --artifact`.
574
576
 
577
+ ### `cinna dashboards list | show | check | run | ref | boards | board create | add | tiles | tile …`
578
+
579
+ Build, check, run and place an agent's **dashboard components**: folders in the agent's `dashboards/<name>/` (`component.json` plus endpoint scripts or a page) that the owner keeps as live tiles on a dashboard. Run from the account workspace. `AGENT` is a name, slug, id, or `.` for the agent workspace you are in. Every verb first checks the server's dashboards capability. While an environment wakes, verbs retry for `--timeout` seconds (default 120). Verbs that read the agent's cloud copy push your pending local edits first (`--no-flush` skips that).
580
+
581
+ - `list AGENT` · `show AGENT NAME [--skill S]` (`--skill` names a component a skill ships, on every verb that takes `NAME`): the components as the environment sees them (checker findings, where each is placed, including "Cinna Desktop") and the **reference** line `cinna://component/bundle:<bundle_id>/<name>` that offers one.
582
+ - `check AGENT [NAME] [--run]`: the owner's card checks; `--run` also runs each source in the environment through `cinna exec` (never locally). Exits 1 on any error.
583
+ - `run AGENT NAME [--endpoint E] [--param k=v]… [--params @file.json]`: run it exactly as a tile would. `--json` prints `{result, value, params_resolved, notice, fetched_at}`, where `value` is exactly what a tile receives.
584
+ - `ref AGENT NAME [--check]`: print only the reference line; `--check` asks core whether it resolves.
585
+ - `boards` · `board create NAME` · `add AGENT NAME --board B [--new-board] [--size s|m|l|wide|tall] [--param k=v] [--title T] [--max-age 15m] [--every 5m|manual] [--after-turn]`: the owner's web dashboards; place a tile (refused for a component with errors or a full dashboard).
586
+ - `tiles BOARD` · `tile data|refresh|params|call|edit|remove BOARD TILE …`: read and drive tiles. `tile params --set/--clear/--reset` sends the whole set; `tile edit` changes title (`''` resets it), size and refresh overrides. Tiles on Cinna Desktop's dashboards are read-only here.
587
+ - `cinna chat --agent AGENT --board B [--focus TILE] [--context @file.json] [--new-chat] "…"`: talk in the agent's dashboard chat, where it has its tile tools.
588
+
589
+ ```bash
590
+ cinna dashboards check crm-agent deals --run
591
+ cinna dashboards run crm-agent deals --param stage=won
592
+ cinna dashboards ref crm-agent deals --check
593
+ cinna dashboards add crm-agent deals --board Sales --size l
594
+ cinna chat --agent crm-agent --board Sales --focus deals "Show only won deals"
595
+ ```
596
+
575
597
  ### `cinna dev`
576
598
 
577
599
  Start a foreground dev session — creates / resumes the Mutagen sync session for this workspace and attaches the terminal to a two-tab TUI (status + raw Mutagen details). Ctrl-C terminates the session; sync does not outlive the TUI. To observe sync from another terminal without affecting it, use `cinna sync status`.
@@ -25,7 +25,8 @@ The platform also handles scheduling, triggers, email, A2A, MCP serving, and ses
25
25
  - Testing credential integrations (keys and tokens stay on the platform, exercised by the remote env)
26
26
  - Installing and validating Python / system packages
27
27
  - Writing and iterating on prompt files
28
- - Building webapp dashboards and data endpoints
28
+ - Building the agent's webapp and data endpoints
29
+ - Building dashboard components, checking and running them in the env, placing them as tiles
29
30
  - Preparing output files and reports
30
31
 
31
32
  ### What stays in the cloud
@@ -56,6 +57,10 @@ The live-sync rewrite removes the local container entirely. Mutagen keeps the wo
56
57
 
57
58
  A self-contained automation unit on the platform. Has a name, template, scripts, prompts, webapp, credentials, and a knowledge base. Identified by `agent_id`.
58
59
 
60
+ ### Dashboard component
61
+
62
+ A live view an agent keeps in `dashboards/<name>/` (`component.json` plus endpoint scripts or a page). The owner places it as a **tile** on a dashboard (core's web dashboards, or Cinna Desktop); the agent offers it by printing its reference `cinna://component/bundle:<bundle_id>/<name>`. It runs only in the agent's environment. See [Dashboards](features/dashboards/dashboards.md).
63
+
59
64
  ### Environment
60
65
 
61
66
  The runtime container configuration for an agent on the platform. Each agent has exactly one environment. Environments may be suspended when idle; opening a sync WebSocket auto-activates them.
@@ -298,6 +303,7 @@ authoring convention.
298
303
  | **Git versioning** | `cinna git` (link, status, commit, push, pull, log, checkout, unlink) — external remotes with your own credentials, `cinna` remotes with the CLI token | [business](features/git_versioning/git_versioning.md) · [tech](features/git_versioning/git_versioning_tech.md) · [acceptance](features/git_versioning/git_versioning_acceptance.md) |
299
304
  | **Durable delegation** | `cinna delegation` (create — idempotent per target + `--id`, status, report — owner side with a task id or from inside a cloud task, reply), gated on the backend capability version | [business](features/delegation/delegation.md) · [tech](features/delegation/delegation_tech.md) · [acceptance](features/delegation/delegation_acceptance.md) |
300
305
  | **Artifacts** | `cinna artifacts` (publish — republishes a remembered path, `--new` / `--update`; list, show, open, download, share and link create — person-only, refused without a TTY; link revoke, delete), gated on the server's artifacts capability | [business](features/artifacts/artifacts.md) · [tech](features/artifacts/artifacts_tech.md) · [acceptance](features/artifacts/artifacts_acceptance.md) |
306
+ | **Dashboards** | `cinna dashboards` (list, show, check `[--run]`, run, ref `[--check]` — an agent's components as its environment sees them; boards, board create, add, tiles, tile data / refresh / params / call / edit / remove — tiles on the owner's web dashboards, desktop dashboards read-only) · `cinna chat --board [--focus] [--context] [--new-chat]` (dashboard chat with the tile tools); gated on the server's dashboards capability | [business](features/dashboards/dashboards.md) · [tech](features/dashboards/dashboards_tech.md) · [acceptance](features/dashboards/dashboards_acceptance.md) |
301
307
  | **Improvement requests** | `cinna improve` (list, show, download, status) | [business](features/improvement_requests/improvement_requests.md) · [tech](features/improvement_requests/improvement_requests_tech.md) · [acceptance](features/improvement_requests/improvement_requests_acceptance.md) |
302
308
  | **Local agent import** | `cinna agent import` (Local Agent Kit → cloud agent), incl. the versioned folder contract (`.cinna-kit/layout.json`), `publications.json` and `content_hash` | [business](features/local_agent_import/local_agent_import.md) · [tech](features/local_agent_import/local_agent_import_tech.md) · [acceptance](features/local_agent_import/local_agent_import_acceptance.md) |
303
309
  | **Team library** | `cinna library` (list, get, share, update, status, grants, suggest) — kit folders in `Local/<slug>/` shared through cinna-core-hosted git with the account token; `cinna agent import --from-library` | [business](features/team_library/team_library.md) · [tech](features/team_library/team_library_tech.md) · [acceptance](features/team_library/team_library_acceptance.md) |
@@ -526,6 +532,8 @@ The platform's send-message route (`POST /sessions/{id}/messages/stream`) return
526
532
  3. Records the current message count as a cursor, then sends the message (`file_ids` carry the attachments).
527
533
  4. **Polls** `GET /sessions/{id}/messages?offset=<cursor>` (messages are ordered ascending by `sequence_number`, so `offset` is the cursor) and `GET …/messages/streaming-status` (`{is_streaming}`) until the turn settles — `is_streaming` false with no message flagged `streaming_in_progress`. A start-grace window covers env wake / queueing before the turn begins; an overall `--timeout` bounds the wait.
528
534
 
535
+ With `--board`, the session is the agent's **dashboard chat** (`POST /dashboards/{id}/chat`), each message carries `dashboard_context`, and a `tiles` event before `done` reports tiles whose params the turn changed (see [Dashboards](features/dashboards/dashboards.md)).
536
+
529
537
  Each finalized message is emitted as one NDJSON line (`session` / `upload` / `message` / `status` / `done`); the in-progress assistant message is held back (its content is still growing) and emitted once final. Every `message` also carries the agent's reasoning/tool trace under **`events`** — the normalized `streaming_events` (thinking blocks, `tool` calls with their full `tool_input` payloads, tool results), with the bookkeeping/`attachment` entries stripped (attachments are surfaced separately). The final coalesced text stays in `content`; the trace shows *how* the agent got there. `--no-events` drops the trace; `--pretty` swaps NDJSON for a Rich transcript. Ctrl-C calls `POST …/messages/interrupt` and exits 130.
530
538
 
531
539
  ### Attachments
@@ -626,6 +634,7 @@ When a CLI token expires (or is revoked) the normal remedy is `cinna set-token <
626
634
  | POST | `/api/v1/cli/account/agents/{id}/mint` | Account token | Mint a per-agent CLI token (`cinna agent sync`, `cinna doctor` re-mint) |
627
635
  | POST | `/api/v1/cli/account/api-proxy` | Account token | Buffered JSON escape hatch — `cinna api`, and the transport for every `cinna chat` session/message call |
628
636
  | POST | `/api/v1/cli/account/files/upload` | Account token | Multipart upload for `cinna chat --file` (the proxy can't carry multipart) |
637
+ | (proxy) | `dashboards/capabilities`, `agents/{id}/dashboards/…`, `dashboards/…`, `dashboards/{id}/blocks/{block}/component/…`, `dashboards/{id}/chat`, `dashboards/component-refs/resolve` | Account token | `cinna dashboards` and `cinna chat --board`, all through the api-proxy; never the `…/frame` routes (core's proxy refuses them) |
629
638
  | GET/PATCH | `/api/v1/cli/account/improvement-requests[/{id}[/archive]]` | Account token | Improvement requests received on the agents the account owns (`cinna improve`); the `/archive` route returns a binary ZIP the JSON-only proxy can't carry |
630
639
 
631
640
  `cinna chat` reaches the conversation API **through** the api-proxy (so these are inner routes, not CLI routes): `POST /sessions/`, `GET /sessions/{id}`, `GET /sessions/{id}/messages`, `POST /sessions/{id}/messages/stream`, `GET /sessions/{id}/messages/streaming-status`, `POST /sessions/{id}/messages/interrupt`, and `GET /files/{id}/download`.
@@ -178,7 +178,13 @@ each with its own token, registry entry, and Mutagen session.
178
178
  - `cinna account refresh-context` re-downloads `context/` and regenerates the
179
179
  orchestrator `CLAUDE.md`, the MCP wiring, and every synced child's per-agent
180
180
  `CLAUDE.md` from the bundled templates — so a CLI upgrade's new commands reach
181
- existing workspaces without a re-setup.
181
+ existing workspaces without a re-setup. A child whose config predates the
182
+ `bundle_id` field gets it filled in first (best effort), so its guide's
183
+ Dashboard components section carries the agent's own reference prefix.
184
+ - The orchestrator `CLAUDE.md` has a **Dashboards** command table and a
185
+ "Which one?" note (webapp / dashboard component / artifact). The Artifacts
186
+ heading says "a frozen copy", and its starter points at
187
+ `artifact-sqlite-report/`. See [Dashboards](../dashboards/dashboards.md).
182
188
 
183
189
  ## Business rules / guardrails
184
190
 
@@ -242,6 +242,20 @@ change without cutting a new one:
242
242
  it never revokes (revoking is its own verb in the web UI, so a stale
243
243
  invocation cannot silently remove access). An unknown address fails the whole
244
244
  publish rather than half-sharing it.
245
+ - **A CLI publish is never refused as stale.** It goes through the agent path
246
+ (`POST /agents/{id}/skills/{name}/publish`), which records the package's
247
+ latest revision as the new revision's base, so a version a co-maintainer
248
+ shared in the meantime is built on rather than checked against. Cinna
249
+ Desktop's Share sends the base its folder holds instead, and core refuses
250
+ that share (`stale_base`) when a co-maintainer has shared a newer version
251
+ since. The CLI never calls the desktop upload, so it never sees
252
+ `stale_base` or `editable_package_exists`.
253
+ - **Each revision names who shared it and what it was based on.**
254
+ `cinna skills revisions` and `cinna skills show` print **Shared by** (the
255
+ publisher's display name, `—` once the account is deleted) and **Based on**
256
+ (`Version N`, the revision the sharer's copy held; `—` for a first revision,
257
+ a share from an older Cinna Desktop, and any revision published before core
258
+ recorded it). An older server sends neither field and both read `—`.
245
259
  - **Publishing reads the cloud workspace.** The files come from the agent's
246
260
  remote workspace on disk — which is why a suspended environment publishes
247
261
  normally — so an unsynced local edit is simply not in the revision. Push
@@ -516,11 +516,36 @@ cinna skills revisions <PACKAGE_ID>
516
516
  ```
517
517
 
518
518
  **Expected** — one row per revision, newest first, with number, version, release
519
- date, size and the `release_notes` given at publish time.
519
+ date, size, **Shared by**, **Based on** and the `release_notes` given at publish
520
+ time.
520
521
 
521
522
  **Watch for** — a permanently blank notes column (the field is `release_notes`,
522
523
  not `notes`); ascending order, which buries the answer at the bottom.
523
524
 
525
+ ### 20a. Each revision names who shared it and what it was based on
526
+
527
+ **Goal** — the revision table shows the sharer and the base core recorded, and a
528
+ CLI re-publish is recorded as built on the latest revision. Needs core
529
+ d08c10d8 and 465c43c2 (revisions carrying `published_by` and
530
+ `base_revision_number`).
531
+
532
+ **Steps** — after scenarios 4 and 5 have published `acceptance-demo` twice:
533
+
534
+ ```bash
535
+ cinna skills revisions <PACKAGE_ID>
536
+ cinna skills revisions <PACKAGE_ID> --json
537
+ ```
538
+
539
+ **Expected** — the table has **Shared by** and **Based on** columns. Revision 2
540
+ reads **Based on** `Version 1`; revision 1 reads `—` there (a first revision has
541
+ no base). Both rows name the publisher's display name under **Shared by**.
542
+ `--json` carries the server's `published_by` (`{user_id, display_name}`) and
543
+ `base_revision_number` (`1` on revision 2, `null` on revision 1) as sent.
544
+
545
+ **Watch for** — revision 2 with no base (the agent publish path did not record
546
+ one); a crash or a blank cell instead of `—` on a revision published before
547
+ core recorded these fields.
548
+
524
549
  ### 21. Sharing changes after the publish
525
550
 
526
551
  **Steps**
@@ -139,6 +139,10 @@
139
139
  - `src/cinna/account.py:_revision_rows()` — revisions sorted newest first. The
140
140
  question this list answers is "what is the newest"; a payload that happened to
141
141
  be ascending would put the answer at the bottom.
142
+ - `src/cinna/account.py:_revision_shared_by()` / `_revision_based_on()` — the
143
+ revision table's **Shared by** (`published_by.display_name`) and **Based on**
144
+ (`Version <base_revision_number>`) cells, each `—` when the field is null or
145
+ absent.
142
146
  - `src/cinna/account.py:_addon_link()` — the row's `link` sub-object. Every
143
147
  fact about an *install* rather than a package lives there: `id` (the link id
144
148
  the plugin routes address), `installed_version`, `latest_version`,
@@ -242,11 +246,19 @@ hatch, `POST /api/v1/cli/account/api-proxy`:
242
246
  `grant_emails`, `package_id`). Returns the new revision; consumed fields are
243
247
  `package_id` (the package's UUID), `revision_number`, `version` and
244
248
  `frontmatter` (the last one only to tell whether the version reached the
245
- workspace's `SKILL.md`).
249
+ workspace's `SKILL.md`). Core records the package's previous latest revision
250
+ as the new one's `base_revision_number`; this route never answers
251
+ `stale_base` or `editable_package_exists` — those come only from the desktop
252
+ upload (`POST /skills/packages/publish`), which the CLI does not call.
246
253
  - `GET /api/v1/skills/packages/{package_id}` — consumed fields are the
247
254
  reverse-DNS `package_id` string, `display_name`, `visibility`,
248
255
  `latest_version` and `revisions[]` (`revision_number`, `version`,
249
- `created_at`, `release_notes` — **not** `notes` — and `size_bytes`).
256
+ `created_at`, `release_notes` — **not** `notes` — `size_bytes`,
257
+ `published_by` `{user_id, display_name}` (null once the account is deleted)
258
+ and `base_revision_number` (int or null)). The last two are absent on a
259
+ server older than skill co-maintainers; `_revision_shared_by()` and
260
+ `_revision_based_on()` render a missing or null value as `—`, and `--json`
261
+ passes both through untouched.
250
262
  - `POST /api/v1/agents/{agent_id}/skills/install` — `SkillInstallRequest`:
251
263
  `package_id` (the package **UUID**), optional `revision_number`,
252
264
  `conversation_mode`, `building_mode`. Answers `PluginSyncResponse`; 409
@@ -66,10 +66,14 @@ This doc covers the agent **lifecycle** verbs. The CRON automation subgroup
66
66
  conflicts against untouched remote originals. A session that cannot start is a
67
67
  warning naming `cinna sync push --agent <slug>` to run *before* editing — never
68
68
  a failed sync.
69
- 3. Re-running sync for an agent **already synced** in that folder is refused
69
+ 3. Sync also records the agent's **bundle id** and the environment's **platform
70
+ skills** in the workspace config. The per-agent `CLAUDE.md` uses them for its
71
+ Dashboard components section: the agent's own `cinna://component/bundle:<id>/`
72
+ prefix, and the path to the account's kit copy of the `cinna-dashboards` skill.
73
+ 4. Re-running sync for an agent **already synced** in that folder is refused
70
74
  (with a `cinna agent unsync` / `cinna set-token` hint) — it never silently
71
75
  re-clones or duplicates.
72
- 4. The workspace lands at `agents/<slug>/<subdir>/` (the Model-A nested layout;
76
+ 5. The workspace lands at `agents/<slug>/<subdir>/` (the Model-A nested layout;
73
77
  `<subdir>` is the slug unless the agent is git-versioned with another subdir) —
74
78
  the command prints the exact path. Afterward `cd` there and `cinna dev`, or stay
75
79
  at the account root and use `cinna sync push --agent <slug>` /
@@ -92,6 +96,12 @@ This doc covers the agent **lifecycle** verbs. The CRON automation subgroup
92
96
  re-materializes the backend scaffold and can clobber local changes, so the
93
97
  builder is told to `cinna sync push` first.
94
98
  3. It blocks until the container is back, then prints the post-restart status.
99
+ 4. If the agent is synced on this machine, it then **reconnects the sync
100
+ session** ("Sync session reconnected."). The old container took the remote
101
+ Mutagen agent with it, and without this the next `cinna sync push` failed
102
+ until Mutagen's own retry came round. A refused token is re-minted through
103
+ the account. A session that doesn't come back is a warning naming
104
+ `cinna sync push` / `cinna doctor`, never a failed restart.
95
105
 
96
106
  ### Rebuild an environment that predates a feature
97
107
  1. `cinna agent rebuild-env <agent_ref> [--yes]` is **not** a louder restart.
@@ -120,6 +130,8 @@ This doc covers the agent **lifecycle** verbs. The CRON automation subgroup
120
130
  row states; the server inside can still be starting, and a chat sent into that
121
131
  window sat streaming with no reply. It ends with "ready to chat", or a warning
122
132
  that the environment has not answered yet.
133
+ 7. Like `restart-env`, it then reconnects this machine's sync session for the
134
+ agent (see [Live Sync](../live_sync/live_sync.md)).
123
135
 
124
136
  ### Inspect what's live
125
137
  1. `cinna agent show <agent_ref>` prints the **effective prompts** (each under its
@@ -132,6 +144,11 @@ This doc covers the agent **lifecycle** verbs. The CRON automation subgroup
132
144
  `credentials:` block names. A credential shared by someone else whose slot
133
145
  this account cannot see reads `slot: unknown`, never `no slot`. When the
134
146
  agent's credential listing cannot be read, it falls back to name + type.
147
+ - A **Dashboard components** section (count, errors, tiles) when the server
148
+ has dashboards. It is read only while the environment is running, because
149
+ listing components would wake a suspended one; otherwise a dim note says the
150
+ environment's state. It never fails `show`. See
151
+ [Dashboards](../dashboards/dashboards.md).
135
152
 
136
153
  ### Choose the model per mode
137
154
  1. `cinna agent model show <agent_ref> [--json]` prints, for conversation and
@@ -66,7 +66,13 @@ The group/subgroup objects are `src/cinna/main.py:agent()` and
66
66
  - `src/cinna/account.py:run_agent_restart_env()` — resolve the agent; if a local
67
67
  child workspace exists (`resolve_child_workspace()`), read `sync_session.status()`
68
68
  and warn+confirm when `pending_to_remote > 0` or `conflict_count > 0`; then
69
- `AccountClient.restart_agent_env()` (blocking) and print status.
69
+ `AccountClient.restart_agent_env()` (blocking) and print status, then
70
+ `_reconnect_sync_session()`.
71
+ - `src/cinna/account.py:_reconnect_sync_session()` — shared by restart and
72
+ rebuild: for the child workspace of this agent (`list_child_workspaces()`)
73
+ whose session exists, `sync_session.heal_session(child_cfg, child)` (a forced
74
+ reconnect, plus a token re-mint on a 401/403). It prints "Sync session
75
+ reconnected." or a warning, and never raises.
70
76
  - `src/cinna/account.py:run_agent_rebuild_env()` — the same shape as
71
77
  `run_agent_restart_env()` plus a second gate: the D2 unsynced-changes
72
78
  warn+confirm, then a `Rebuild …?` confirmation (default No) that `--yes`
@@ -0,0 +1,224 @@
1
+ # Dashboards (`cinna dashboards`, `cinna chat --board`)
2
+
3
+ ## Purpose
4
+
5
+ Let a developer and their local assistant build an agent's **dashboard
6
+ components**, check and run them in the agent's real environment, print the
7
+ reference that offers one to the owner, place them as tiles on the owner's web
8
+ dashboards, and test the agent's behaviour in a dashboard chat, all from the
9
+ terminal.
10
+
11
+ ## Mental model / core concepts
12
+
13
+ A component lives **in the agent's workspace**. It's synced like any other file
14
+ and runs **only in the agent's environment**. Tiles and dashboards live **in
15
+ cinna-core**. The CLI is a remote control for both and runs nothing locally.
16
+
17
+ - **Component**: a folder `dashboards/<name>/` in the agent's workspace (or
18
+ `skills/<skill>/dashboards/<name>/` inside a skill). It holds a
19
+ `component.json` (title, view, source, endpoints, params, refresh, size,
20
+ `requires_credentials`, `context`), small endpoint scripts and, for an `html`
21
+ view, a page. It's bundle-owned source: it ships with the agent, the team
22
+ library and published bundles.
23
+ - **Component data**: what a schedule or the component's `refresh.command`
24
+ prepares under `app-data/dashboards/<name>/`. Per user, never shipped, never
25
+ carried by an import.
26
+ - **Tile**: one placement of a component on a dashboard. It refers to the
27
+ component (agent + skill + name) and never copies it, so an edit to the
28
+ component changes every tile that shows it. A tile keeps only the owner's
29
+ choices: title, size, params and refresh overrides. Core keeps its cached
30
+ data and its run budget.
31
+ - **Dashboard (board)**: the owner's page of tiles on the web, up to 20 blocks
32
+ each and 10 dashboards per user. Cinna Desktop also creates hidden **backing
33
+ dashboards** (`origin: desktop`) for its cloud tiles; those belong to the
34
+ desktop's layout.
35
+ - **Reference**: the line an agent prints to offer a component,
36
+ `cinna://component/bundle:<bundle_id>/<name>` (with `<skill>/` before the
37
+ name for a skill's component). The owner's chat, on the web or in Cinna
38
+ Desktop, turns that line into a card with Preview and Add to dashboard. Every
39
+ cloud agent has a bundle id, so the CLI always prints the `bundle:` form.
40
+ - **Dashboard chat**: one conversation per dashboard and agent. Each message
41
+ carries a `<dashboard_context>` (what the owner sees: the focused tile, its
42
+ params and data, the other tiles). In that chat, and only there, the agent has
43
+ the tile tools `dashboards_tiles` and `dashboards_update_tile`.
44
+ - **Webapp vs component vs artifact**: the webapp is the agent's own app and
45
+ can be shared; a component is the owner's live tile; an artifact is a frozen
46
+ copy for people. "Make me a dashboard" almost always means a component.
47
+
48
+ ## User flows
49
+
50
+ ### Build and check a component (assistant in a synced agent workspace)
51
+ 1. The assistant reads the kit's dashboards guide and the `cinna-dashboards`
52
+ skill. The per-agent `CLAUDE.md` links the account's copy under
53
+ `context/local-kit/`.
54
+ 2. It writes `workspace/dashboards/deals/component.json`, then the endpoints.
55
+ Mutagen syncs them to the environment.
56
+ 3. `cinna dashboards check . deals --run` pushes pending edits, reads the
57
+ environment's own checker findings through core, runs the checker's run
58
+ checks in the environment, and exits 1 on any error.
59
+ 4. `cinna dashboards run . deals --param stage=won` prints the value exactly as
60
+ a tile would receive it.
61
+
62
+ ### Offer it to the owner
63
+ 5. `cinna dashboards ref . deals --check` prints the reference line and
64
+ confirms it resolves. The assistant prints that line, on its own and outside
65
+ backticks, in its reply to the user. The owner gets a card.
66
+
67
+ ### Place and drive tiles (when the user asks)
68
+ 6. `cinna dashboards boards` lists the owner's web dashboards;
69
+ `board create Sales` makes one.
70
+ 7. `cinna dashboards add crm-agent deals --board Sales [--size l] [--param k=v]`
71
+ adds the tile and prints its id and the dashboard link. `--new-board`
72
+ creates the dashboard if no dashboard has that name. `--title`, `--max-age`,
73
+ `--every` and `--after-turn/--no-after-turn` set the tile's title and
74
+ refresh overrides. A component a skill ships is named with `--skill <skill>`
75
+ on `show`, `check`, `run`, `ref` and `add`.
76
+ 8. `cinna dashboards tiles Sales` shows each tile's params, size and data age
77
+ without waking any environment. `tile data|refresh|params|call|edit|remove`
78
+ reads or changes one tile. `tile edit` takes `--title` (`''` goes back to
79
+ the component's title), `--size`, `--max-age`, `--every` and
80
+ `--after-turn/--no-after-turn`.
81
+
82
+ ### Test the agent in a dashboard chat
83
+ 9. `cinna chat --agent crm-agent --board Sales --focus deals "Which deal first?"`
84
+ opens (or continues) the agent's dashboard chat and sends the dashboard
85
+ context. The transcript shows the agent's tile-tool calls. A tile whose
86
+ stored params the turn changed is reported in a closing `tiles` event.
87
+ `--new-chat` starts a fresh chat; `--context @file.json` sends a
88
+ hand-written context instead.
89
+
90
+ ### Import a kit agent that ships components
91
+ 10. `cinna agent import <path>` lists the components that travel and warns
92
+ about what won't work in the cloud, then ends with their references and
93
+ the `add` hint.
94
+
95
+ ## Business rules
96
+
97
+ - **The environment is the runtime.** Nothing runs an endpoint or the checker's
98
+ run checks locally. `check --run` goes through `cinna exec`, `run` through
99
+ core. The only local check is the kit's static checker during import.
100
+ - **Flush before reading.** `list`, `show`, `check`, `run` and `add` first push
101
+ the agent's pending local edits when it's synced under this account
102
+ workspace and its sync session exists, and they say so. They never create a
103
+ session. `--no-flush` skips the push. A failed flush is a warning, and the
104
+ read goes ahead. Reads ask core for a fresh listing (`fresh=true`) so a check
105
+ right after a push isn't served from core's 10-second cache.
106
+ - **Server support first.** Every verb asks `GET dashboards/capabilities`
107
+ before anything else. If the route is missing (the server predates
108
+ dashboard components), the answer is one message with code
109
+ `dashboards_unsupported`. Another version is refused up front too.
110
+ `cinna chat --board` asks the same route but also needs its `chat` flag, and
111
+ refuses with `dashboard_chat_unsupported` when the server has no dashboard
112
+ chat. The
113
+ limits it reports (runs a minute, blocks per dashboard, context size) are
114
+ the ones the CLI enforces and quotes. A refusal by the api-proxy itself
115
+ (its own per-token rate limit) is reported as exactly that, never as
116
+ "no dashboards".
117
+ - **Waking environments.** `env_unavailable` is retried until `--timeout`
118
+ (default 120 s; on `check` the same flag also bounds each `--run` check, and
119
+ defaults to 300 s), waiting `retry_after_s` (default 5 s) between tries. Listing components or
120
+ running one wakes a suspended environment. Reading a tile's data never does.
121
+ `cinna agent show` lists components only when the server has dashboards
122
+ and the environment is already running. `cinna doctor` doesn't check
123
+ dashboards at all, because it would wake every environment.
124
+ - **Refusals keep core's sentence** and add the CLI's next step:
125
+ - `adapter_unsupported` → `cinna agent rebuild-env <agent>`.
126
+ - `needs_credentials` → link them (`cinna agent show`). A name is the name of
127
+ a credential linked to the agent; for a bundle install it's the bundle's
128
+ credential spec name.
129
+ - `rate_limited` → try again in N s.
130
+ - `not_found` → `cinna dashboards list <agent>`.
131
+ - `invalid_input` → names the field.
132
+ - `call_failed` → core's sentence, which carries the script's stderr tail.
133
+ - Exit codes: `invalid_input` 2, `env_unavailable` 12, everything else 1.
134
+ - **The CLI's own refusals** (exit 1, with the remedy in the message):
135
+ - `component_errors`: `check` found an error, or `add` was asked to place a
136
+ component with errors; the JSON lists the components.
137
+ - `dashboard_full`: `add` on a dashboard that already holds the block limit.
138
+ - `not_synced`: `check --run` for an agent with no synced workspace under
139
+ this account (the checker runs with that workspace's token).
140
+ - `ref_<status>` (e.g. `ref_gone`, `ref_invalid`): `ref --check` got a status
141
+ other than `ok`.
142
+ - `desktop_dashboard`: see Desktop dashboards below.
143
+ - **Own run budget.** Core allows 30 runs a minute per target. CLI runs carry
144
+ `tile_key: "cli"`, so a developer looping `run` doesn't use up the budget of
145
+ core's Preview dialog. The CLI never auto-loops past a `rate_limited`.
146
+ - **Agents offer, people place.** The assistant's default is to print the
147
+ reference. `add` and the tile verbs are for people and explicit requests, and
148
+ they aren't person-only: a tile is private to its owner.
149
+ - **A component with errors can't be placed.** `add` refuses first and lists
150
+ the errors (core would refuse too). It also refuses a dashboard that already
151
+ holds the block limit.
152
+ - **Desktop dashboards are read-only here.** Tiles on an `origin: desktop`
153
+ dashboard can be listed and read (`tiles`, `tile data`), but `tile refresh`,
154
+ `call`, `params`, `edit` and `remove`, and `add`, refuse with code
155
+ `desktop_dashboard`. `boards` and name lookup see web dashboards only; a
156
+ desktop dashboard is reachable by its full id. Placements on one show as
157
+ "Cinna Desktop".
158
+ - **Placement matches core.** A new tile goes at the top-left (`0,0`) and the
159
+ grid shifts the others down, as core's own Add dialog does. The size grid is
160
+ core's: `s` 3×2, `m` 6×2, `l` 6×4, `wide` 12×2, `tall` 3×4. The default is
161
+ the component's `size`, else `s`.
162
+ - **`add --new-board` creates only when nothing matches.** An ambiguous
163
+ name or a failed lookup stays an error; it never creates a duplicate.
164
+ - **`chat --board --resume` must resume that dashboard's chat.** Core would
165
+ silently drop the context on any other session, and the tile tools would
166
+ answer `no_dashboard`, so the CLI refuses.
167
+ - **The per-agent guide follows the environment.** `CLAUDE.md` §7b carries
168
+ the agent's own reference prefix and the path to the account's kit copy of
169
+ the `cinna-dashboards` skill, taken from the platform skills the building
170
+ context reports. If the environment doesn't list that skill, §7b says to
171
+ rebuild it.
172
+ - **Tile params are a whole set.** `tile params --set/--clear/--reset` merges
173
+ locally and sends the complete set. Core replaces it, and omitted keys go
174
+ back to their defaults.
175
+ - **No frame URLs.** The CLI never calls either `…/frame` route: a frame URL is
176
+ a 12-hour credential and a terminal has no use for one.
177
+ - **Dashboard chat context** follows the web panel's shape. It's capped at
178
+ 12,000 characters by dropping other agents' tiles first, then the agent's
179
+ other tiles, then cutting the summary. It's resent on every message (core
180
+ dedupes by hash). `--board` takes web dashboards only: a desktop dashboard's
181
+ chat runs in Cinna Desktop over A2A.
182
+ - **Import warns, never refuses.** It warns when the kit's static checker
183
+ reports errors (the checker comes from the account workspace's own
184
+ `context/local-kit/`, the kit the user's server shipped; a kit copy
185
+ inside the imported folder is never run, because that folder may be a
186
+ download), when a source reads `app-data/` (that data doesn't travel),
187
+ when a folder holds `package.json`/`node_modules/`, when `refresh.on_app_start`
188
+ is set (the cloud ignores it), and when `requires_credentials` names a
189
+ credential the manifest doesn't declare.
190
+
191
+ ## Architecture overview
192
+
193
+ ```
194
+ cinna dashboards <verb> → dashboards.py → AccountClient._dashboards_json → account api-proxy
195
+ → core: agents/{id}/dashboards/* · dashboards/* · …/component/*
196
+ → agent env (env-core /dashboards/*, the checker)
197
+ cinna dashboards check --run → dashboards.run_env_checker → cinna exec (per-agent token) → env's check_component.py
198
+ cinna chat --board → chat.run_chat → dashboards.prepare_dashboard_chat → POST dashboards/{id}/chat
199
+ → POST sessions/{id}/messages/stream {dashboard_context} → poll → "tiles" event
200
+ cinna agent import → local_import._report_components → dashboards.survey_local_components → kit check_component.py (static)
201
+ cinna agent sync / account refresh-context → GET agents/{id} → .cinna/config.json bundle_id → CLAUDE.md §7b
202
+ cinna agent sync → building context (platform_skills) → .cinna/config.json platform_skills → CLAUDE.md §7b skill path
203
+ ```
204
+
205
+ ## Integration points
206
+
207
+ - [Account workspace](../account_workspace/account_workspace.md): the
208
+ orchestrator `CLAUDE.md` has the Dashboards command table and the
209
+ webapp / component / artifact advice. `refresh-context` re-renders every
210
+ per-agent guide and backfills its bundle id.
211
+ - [Agent management](../agent_management/agent_management.md): `cinna agent sync`
212
+ records the bundle id. `cinna agent show` has a Dashboard components section.
213
+ `cinna agent rebuild-env` is the remedy for an environment that predates
214
+ components.
215
+ - [Live sync](../live_sync/live_sync.md): components sync like any workspace
216
+ file, and the dashboards verbs reuse its flush.
217
+ - [Remote exec](../remote_exec/remote_exec.md): the channel `check --run` runs
218
+ the checker through.
219
+ - [Remote chat](../remote_chat/remote_chat.md): `cinna chat --board` is a
220
+ dashboard chat on top of the same poll loop.
221
+ - [Local agent import](../local_agent_import/local_agent_import.md): components
222
+ travel with an import, which reports them.
223
+ - [Artifacts](../artifacts/artifacts.md): the frozen-copy alternative. Its
224
+ starter template is `artifact-sqlite-report/`.