@ekanos/cli 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +25 -8
  2. package/dist/agents-api.d.ts +11 -2
  3. package/dist/agents-api.js +39 -3
  4. package/dist/agents-api.js.map +1 -1
  5. package/dist/apps-api.js +2 -2
  6. package/dist/apps-api.js.map +1 -1
  7. package/dist/auth/ekanos-api.d.ts +16 -2
  8. package/dist/auth/ekanos-api.js +101 -15
  9. package/dist/auth/ekanos-api.js.map +1 -1
  10. package/dist/auth/host-trust.d.ts +46 -0
  11. package/dist/auth/host-trust.js +79 -0
  12. package/dist/auth/host-trust.js.map +1 -0
  13. package/dist/auth/session.d.ts +10 -1
  14. package/dist/auth/session.js +28 -28
  15. package/dist/auth/session.js.map +1 -1
  16. package/dist/commands/agents-edit.d.ts +6 -2
  17. package/dist/commands/agents-edit.js +57 -26
  18. package/dist/commands/agents-edit.js.map +1 -1
  19. package/dist/commands/agents.d.ts +13 -2
  20. package/dist/commands/agents.js +140 -35
  21. package/dist/commands/agents.js.map +1 -1
  22. package/dist/commands/apps.d.ts +2 -0
  23. package/dist/commands/apps.js +16 -12
  24. package/dist/commands/apps.js.map +1 -1
  25. package/dist/commands/catalog.js +7 -6
  26. package/dist/commands/catalog.js.map +1 -1
  27. package/dist/commands/knowledge.d.ts +19 -0
  28. package/dist/commands/knowledge.js +119 -27
  29. package/dist/commands/knowledge.js.map +1 -1
  30. package/dist/commands/login.d.ts +4 -0
  31. package/dist/commands/login.js +30 -2
  32. package/dist/commands/login.js.map +1 -1
  33. package/dist/commands/logout.d.ts +9 -1
  34. package/dist/commands/logout.js +56 -7
  35. package/dist/commands/logout.js.map +1 -1
  36. package/dist/commands/publish.js +3 -3
  37. package/dist/commands/publish.js.map +1 -1
  38. package/dist/commands/reviewers.d.ts +2 -0
  39. package/dist/commands/reviewers.js +7 -3
  40. package/dist/commands/reviewers.js.map +1 -1
  41. package/dist/commands/routes.d.ts +2 -0
  42. package/dist/commands/routes.js +42 -9
  43. package/dist/commands/routes.js.map +1 -1
  44. package/dist/commands/runs.d.ts +13 -2
  45. package/dist/commands/runs.js +99 -16
  46. package/dist/commands/runs.js.map +1 -1
  47. package/dist/commands/scope-notice.d.ts +21 -0
  48. package/dist/commands/scope-notice.js +35 -0
  49. package/dist/commands/scope-notice.js.map +1 -0
  50. package/dist/commands/skills.d.ts +7 -1
  51. package/dist/commands/skills.js +80 -24
  52. package/dist/commands/skills.js.map +1 -1
  53. package/dist/commands/sources.d.ts +1 -1
  54. package/dist/commands/sources.js +126 -12
  55. package/dist/commands/sources.js.map +1 -1
  56. package/dist/commands/status.js +5 -4
  57. package/dist/commands/status.js.map +1 -1
  58. package/dist/commands/team-agent-readiness.d.ts +49 -0
  59. package/dist/commands/team-agent-readiness.js +308 -0
  60. package/dist/commands/team-agent-readiness.js.map +1 -0
  61. package/dist/commands/team-agents-agents.d.ts +24 -3
  62. package/dist/commands/team-agents-agents.js +314 -35
  63. package/dist/commands/team-agents-agents.js.map +1 -1
  64. package/dist/commands/team-agents-mcp.js +32 -3
  65. package/dist/commands/team-agents-mcp.js.map +1 -1
  66. package/dist/commands/team-agents-triggers.js +230 -55
  67. package/dist/commands/team-agents-triggers.js.map +1 -1
  68. package/dist/commands/team-agents.d.ts +3 -1
  69. package/dist/commands/team-agents.js +27 -7
  70. package/dist/commands/team-agents.js.map +1 -1
  71. package/dist/commands/teams-channel-install.d.ts +24 -0
  72. package/dist/commands/teams-channel-install.js +94 -0
  73. package/dist/commands/teams-channel-install.js.map +1 -0
  74. package/dist/commands/teams-connect.d.ts +41 -0
  75. package/dist/commands/teams-connect.js +212 -57
  76. package/dist/commands/teams-connect.js.map +1 -1
  77. package/dist/commands/teams-events.d.ts +12 -0
  78. package/dist/commands/teams-events.js +138 -0
  79. package/dist/commands/teams-events.js.map +1 -0
  80. package/dist/commands/teams-onboard.d.ts +11 -3
  81. package/dist/commands/teams-onboard.js +60 -7
  82. package/dist/commands/teams-onboard.js.map +1 -1
  83. package/dist/commands/teams-overview.d.ts +11 -0
  84. package/dist/commands/teams-overview.js +160 -0
  85. package/dist/commands/teams-overview.js.map +1 -0
  86. package/dist/commands/teams-scope.d.ts +10 -0
  87. package/dist/commands/teams-scope.js +109 -0
  88. package/dist/commands/teams-scope.js.map +1 -0
  89. package/dist/commands/teams.d.ts +4 -2
  90. package/dist/commands/teams.js +113 -14
  91. package/dist/commands/teams.js.map +1 -1
  92. package/dist/commands/upgrade.js +12 -2
  93. package/dist/commands/upgrade.js.map +1 -1
  94. package/dist/commands/use.js +2 -2
  95. package/dist/commands/use.js.map +1 -1
  96. package/dist/commands/whoami.js +1 -1
  97. package/dist/commands/whoami.js.map +1 -1
  98. package/dist/connections-api.js +1 -1
  99. package/dist/connections-api.js.map +1 -1
  100. package/dist/delegate.js +11 -4
  101. package/dist/delegate.js.map +1 -1
  102. package/dist/harness-scaffold.js +12 -0
  103. package/dist/harness-scaffold.js.map +1 -1
  104. package/dist/index.d.ts +6 -0
  105. package/dist/index.js +682 -167
  106. package/dist/index.js.map +1 -1
  107. package/dist/knowledge-api.d.ts +46 -0
  108. package/dist/knowledge-api.js +32 -1
  109. package/dist/knowledge-api.js.map +1 -1
  110. package/dist/open-url.d.ts +16 -0
  111. package/dist/open-url.js +73 -0
  112. package/dist/open-url.js.map +1 -0
  113. package/dist/parse-argv.d.ts +2 -0
  114. package/dist/parse-argv.js.map +1 -1
  115. package/dist/publish-api.d.ts +2 -1
  116. package/dist/publish-api.js +4 -3
  117. package/dist/publish-api.js.map +1 -1
  118. package/dist/pull-write.d.ts +27 -0
  119. package/dist/pull-write.js +60 -0
  120. package/dist/pull-write.js.map +1 -0
  121. package/dist/routes-api.d.ts +3 -0
  122. package/dist/routes-api.js +9 -4
  123. package/dist/routes-api.js.map +1 -1
  124. package/dist/runs-api.d.ts +7 -1
  125. package/dist/runs-api.js +21 -6
  126. package/dist/runs-api.js.map +1 -1
  127. package/dist/safe-fs.d.ts +2 -0
  128. package/dist/safe-fs.js +12 -6
  129. package/dist/safe-fs.js.map +1 -1
  130. package/dist/secret-file.d.ts +17 -0
  131. package/dist/secret-file.js +69 -0
  132. package/dist/secret-file.js.map +1 -0
  133. package/dist/skills-api.d.ts +10 -2
  134. package/dist/skills-api.js +37 -2
  135. package/dist/skills-api.js.map +1 -1
  136. package/dist/source-products-api.d.ts +4 -0
  137. package/dist/source-products-api.js +14 -4
  138. package/dist/source-products-api.js.map +1 -1
  139. package/dist/source-target.js +2 -1
  140. package/dist/source-target.js.map +1 -1
  141. package/dist/sources-api.d.ts +2 -1
  142. package/dist/sources-api.js +3 -2
  143. package/dist/sources-api.js.map +1 -1
  144. package/dist/team-connect-api.d.ts +44 -2
  145. package/dist/team-connect-api.js +19 -7
  146. package/dist/team-connect-api.js.map +1 -1
  147. package/dist/teams-api.d.ts +41 -1
  148. package/dist/teams-api.js +95 -19
  149. package/dist/teams-api.js.map +1 -1
  150. package/dist/toolchain-api.d.ts +9 -0
  151. package/dist/toolchain-api.js +17 -2
  152. package/dist/toolchain-api.js.map +1 -1
  153. package/dist/toolchain-resolve.d.ts +3 -0
  154. package/dist/toolchain-resolve.js +15 -1
  155. package/dist/toolchain-resolve.js.map +1 -1
  156. package/dist/toolchain.d.ts +6 -0
  157. package/dist/toolchain.js +19 -0
  158. package/dist/toolchain.js.map +1 -1
  159. package/dist/update-notice.js +2 -1
  160. package/dist/update-notice.js.map +1 -1
  161. package/package.json +2 -2
  162. package/templates/AGENTS.md.tmpl +6 -1
  163. package/templates/claude-skill.md.tmpl +5 -0
  164. package/templates/package.json.tmpl +4 -4
  165. package/templates/skills/build-agent/SKILL.md +104 -17
  166. package/templates/skills/build-agent/references/agent-json.md +4 -2
  167. package/templates/skills/build-agent/references/rollout.md +23 -4
  168. package/templates/skills/build-agent/references/set-up-an-integration.md +55 -7
  169. package/templates/skills/build-agent/references/skills.md +20 -1
  170. package/templates/skills/build-agent/references/triggers.md +47 -11
  171. package/templates/skills/build-integration/references/widget-design.md +3 -3
  172. package/templates/skills/ekanos-platform/SKILL.md +45 -16
  173. package/templates/skills/polish-widgets/references/patterns.md +2 -2
@@ -18,13 +18,33 @@ Run the CLI as `npx @ekanos/cli … --json` and read the envelope
18
18
  every `hint`. Look things up in the `ekanos-sdk-docs` MCP server
19
19
  (https://sdk.ekanos.dev) rather than guessing.
20
20
 
21
+ ## The goal: an agent that can be reached and answers
22
+
23
+ The user wants an agent that **responds and does things** where their people
24
+ work — someone @mentions it in Linear (or assigns it an issue, or writes in
25
+ Slack) and it picks the work up, acts with its tools and answers in that
26
+ thread. "Published", "turned on" and "connected" are steps toward that, not
27
+ the finish. Whenever the agent has a channel trigger (`linear.mentioned`,
28
+ `linear.assigned`, any Linear event, a Slack trigger), the job is not done
29
+ until a real mention has started a run and the reply has landed.
30
+
31
+ A channel trigger fires only once that channel is **installed for the team**,
32
+ and for Linear that is a second identity beside the personal connection: the
33
+ team's own Linear app installed as a workspace member (the `agent`
34
+ connection). The personal connection lets the agent's tools act; only the
35
+ installed Linear agent makes Linear send the mention. Nothing stops a team
36
+ from turning the agent on with the trigger saved and the agent never
37
+ installed — so check it, every time (§ 4, "Make it reachable").
38
+
21
39
  ## Hard rules
22
40
 
23
41
  - Never ask for, accept or write a secret (API key, client secret, webhook
24
- signing secret). Teams enter those in the Ekanos app.
25
- - Never `publish` or `rollback` without the user's explicit yes to that
26
- version, after they have seen it. `--yes` records that consent; it is never
27
- a way past a question.
42
+ signing secret). The user types it at their own terminal — `apps set`,
43
+ `apps connect`, `teams app set` and `teams connect` ask with hidden input
44
+ and refuse an agent run — or a team enters it in the Ekanos app.
45
+ - Never `publish`, `rollback` or `archive` without the user's explicit yes to
46
+ that version or agent, after they have seen it. `--yes` records that
47
+ consent; it is never a way past a question.
28
48
  - Never `--overwrite` a version conflict (exit 7) you have not shown the user:
29
49
  someone else changed the agent; pull it and reconcile.
30
50
  - Use product and tool names exactly as the catalog lists them.
@@ -53,7 +73,8 @@ every `hint`. Look things up in the `ekanos-sdk-docs` MCP server
53
73
  agent's docs, policies or FAQs should live, offer **Knowledge** first:
54
74
  Ekanos's own knowledge base, nothing to sign up for. One collection per
55
75
  team plus the Source's General one; load a folder of markdown with
56
- `ekanos knowledge push <dir> [--team <team>]`, check with
76
+ `ekanos knowledge push <dir> [--team <team>]` (add `--prune` on the
77
+ user's yes to delete the ones whose files they removed), check with
57
78
  `ekanos knowledge search "<words>" --team <team>`, and grant the agent
58
79
  `search_knowledge` + `read_knowledge_article` (`references/agent-json.md`
59
80
  → `tools`). Keep skills for how-to-work instructions; Knowledge for the
@@ -122,7 +143,10 @@ in parentheses are the recommendation when the user has no preference.
122
143
  event a product declares (Linear also has `linear.issue_labeled`,
123
144
  `linear.issue_created` and `linear.assigned`; Zendesk also has
124
145
  `zendesk.comment_added`) — map an old trigger onto the matching event
125
- rather than onto an @mention. Say what each team needs connected first.
146
+ rather than onto an @mention. Say what each team needs connected first —
147
+ and for a channel trigger, that each team also installs that channel's
148
+ agent (Linear: `teams connect <team> linear --connection agent`), or the
149
+ trigger never fires.
126
150
  8. **Who it works with** — other agents of this Source it may ask or hand
127
151
  work to (`links`). A link only exists in a team that runs both agents.
128
152
  9. **What teams may change** — `teamOverrides` per area (approvals,
@@ -150,21 +174,81 @@ in parentheses are the recommendation when the user has no preference.
150
174
  `skills` the output reports as created or changed.
151
175
  3. `npx @ekanos/cli agents show <key> --source <slug>` — review the stored draft
152
176
  with the user.
153
- Then test it on one team that has turned the agent on, without publishing:
177
+ Then test it on **one** team, without publishing. Put that team on the
178
+ draft first — this works before anything is published, and lets the test
179
+ use tools the draft adds:
180
+ `npx @ekanos/cli teams agents enable <team> <key> --draft --json` (agent
181
+ not on that team yet) or `teams agents pin <team> <key> --draft --json`
182
+ (already on). Then
154
183
  `npx @ekanos/cli agents test <key> --team <team> --prompt "…" --follow --json`
155
- (or `--input example.json` for a real ticket or event). It runs the latest
156
- version on that team as a test run — same tools, approvals and audit; the
157
- team's current agent still bounds what it may do, so a draft can only do
158
- less. A write waits for an approval like any run (see "Running, watching
159
- and deciding" below).
184
+ (or `--input example.json` for a real ticket or event). Only that team runs
185
+ the draft, only when started by hand — its triggers don't start it — and
186
+ every write waits for an approval (see "Running, watching and deciding"
187
+ below). After the next `agents apply`, run `pin --draft` again to test the
188
+ new draft; publishing puts the team back to following.
160
189
  4. Ask: publish this version to every team now? Only on yes:
161
190
  `npx @ekanos/cli agents publish <key> --source <slug> --to <n> --yes`.
191
+ The publish is the confirmation: every team that follows the agent
192
+ moves to the new version, and one that had confirmed what it may use
193
+ stays confirmed, now in the publisher's name — even when the version
194
+ reaches further. No team is held. Ask once whether to add
195
+ `--confirm-access` (it also confirms, as the user, every team on that
196
+ version that was never confirmed; never add it without their yes). The
197
+ output lists any team pinned to another version, what the new version
198
+ would add to it, and the `teams agents unpin` command that moves it —
199
+ relay it.
162
200
  5. If anything waits for approval, name its reviewers (**Reviewers**
163
201
  below) before teams turn it on — a draft nobody may decide just waits.
164
202
  6. Hand over the team-side checklist (`references/triggers.md` has the
165
203
  per-integration parts): find it under Agents → "Provided for your team",
166
- Turn on, connect what it needs, confirm access, add triggers. Suggest one
167
- team pilots it first, and plan a first test run with them.
204
+ Turn on, connect what it needs, **install the channel's agent for a
205
+ channel trigger**, confirm access (`teams agents confirm <team> <key>`
206
+ or `teams agents enable … --confirm-access`, as the user; or a team
207
+ manager in the app — never a plain member), add triggers. Suggest one
208
+ team pilots
209
+ it first, and do § 4 with them.
210
+
211
+ ## 4. Make it reachable, and prove it end to end
212
+
213
+ For each team that turns on an agent with a channel trigger, start with
214
+ `npx @ekanos/cli teams agents show <team> <key> --source <slug>`: it says
215
+ whether the agent is live on that team and, if not, the one next step
216
+ (`npx @ekanos/cli teams show <team> --source <slug>` is the whole team on one
217
+ screen). For the detail behind it:
218
+
219
+ 1. `npx @ekanos/cli teams agents list <team> --json` — each agent's
220
+ `channels` says what its triggers need installed (`ready`, `problem`).
221
+ A `ready: false` entry is a trigger that can never fire; its `problem`
222
+ reads "Linear agent not installed for this team".
223
+ 2. `npx @ekanos/cli teams show <team> linear --json` — `connections` has one
224
+ entry per connection: `default` (the personal connection: `connected`)
225
+ and `agent` (`credentialsSaved`, `connected` = installed, `neededBy`),
226
+ and the `agent-events` webhook in `teamApps[].webhooks` must have an
227
+ `endpoint`. Read the state back to the user in those words.
228
+ 3. Not installed: the user runs, **in their own terminal** (it asks for the
229
+ Linear app's secrets, which you never handle):
230
+ `npx @ekanos/cli teams connect <team> linear --connection agent --source <slug>`.
231
+ It asks for the app's client ID, secret and webhook signing secret if
232
+ missing, opens the install (a Linear workspace admin approves it) and
233
+ waits. No webhook URL yet: `npx @ekanos/cli teams webhook <team> linear
234
+ agent-events --source <slug>` (shown once, and saved to a file only the
235
+ user can read — the output names it; the user copies it into the Linear
236
+ app. Never open or print that file yourself).
237
+ `references/set-up-an-integration.md` § 4 has the app walk-through. Then
238
+ run step 2 again until `agent` reads `connected: true` with a webhook.
239
+ 4. The real check, never skipped: ask the user to @mention the agent on a
240
+ Linear issue (or assign it one). Then
241
+ `npx @ekanos/cli runs list --team <team> --json` shows a run whose
242
+ `trigger` is the event (`integration_event`), started in the last minute;
243
+ `npx @ekanos/cli runs show <run-id> --team <team> --json` shows its work,
244
+ and the user confirms the reply landed in the Linear thread. No run:
245
+ go back to step 1 — the trigger, its filter (`teamKeys`), the webhook
246
+ events ticked in the Linear app (**Agent session events**), the latest
247
+ webhook URL.
248
+
249
+ `agents test` and `runs start` run the agent by hand: they pass without the
250
+ channel, so they never prove it. When the agent's real trigger could never
251
+ fire they print a `Warning:` (and `warnings` in `--json`) — act on it.
168
252
 
169
253
  ## Reviewers
170
254
 
@@ -181,7 +265,7 @@ notified of every draft in their reach.
181
265
  - `npx @ekanos/cli reviewers add <email> --reach team --team <team-slug> --source <slug>`
182
266
  — decides one team's drafts, from the same review queue (they need not be
183
267
  a member of that team).
184
- - `npx @ekanos/cli reviewers remove <email> [--team <team-slug>] --source <slug>`
268
+ - `npx @ekanos/cli reviewers remove <email> [--team <team-slug>] --source <slug> --yes`
185
269
  — every reach, or just that team's.
186
270
 
187
271
  The first decision settles a draft for everyone. Recommend one or two
@@ -192,7 +276,8 @@ reviewers where a team wants its own people deciding. A refusal with
192
276
  ## Changing it later
193
277
 
194
278
  `npx @ekanos/cli agents pull <key> --source <slug>` writes the latest version to
195
- `agents/<key>/`; edit, `apply` (a new draft), `show`, then `publish` on the
279
+ `agents/<key>/` (it refuses to overwrite a local file that differs; `--force`
280
+ replaces it); edit, `apply` (a new draft), `show`, then `publish` on the
196
281
  user's yes. For one small change, edit the stored draft directly — `agents
197
282
  policy <key> set <tool> approve`, `agents triggers <key> add|remove …`,
198
283
  `agents links <key> add|remove …`, `agents overrides <key> enable|disable
@@ -219,7 +304,9 @@ names them). Add `--json` for a stable record a script can assert on.
219
304
  - `npx @ekanos/cli approvals list --team <team>` — what is waiting.
220
305
  - `npx @ekanos/cli approvals approve <id> --team <team> [--reason "…"]` /
221
306
  `approvals reject <id> --team <team> --reason "…"` — decided as you, with
222
- the authority a team's agent manager has in the app.
307
+ the authority a team's agent manager has in the app. A team's own agent
308
+ (not provided) is the team's: you decide its approvals only as a member of
309
+ that team who manages its agents (`NOT_A_TEAM_APPROVER` otherwise).
223
310
  - `npx @ekanos/cli approvals edit <id> --team <team> --body ./reply.md` — Edit &
224
311
  send a reply draft: approves it with your text instead. Only reply drafts
225
312
  take an edit.
@@ -126,7 +126,8 @@ The tool names above are illustrations. Take real ones from
126
126
  - `schedule` — `cron` (5 fields, on a 5-minute boundary) and `timezone`
127
127
  (IANA, default `UTC`); give it a `prompt`.
128
128
  - `webhook` — each team gets its **own** URL and secret, created or
129
- rotated by the team in the app. A template never holds a webhook secret.
129
+ rotated by the team in the app or by a Source admin with
130
+ `ekanos teams triggers rotate`. A template never holds a webhook secret.
130
131
  - **`links`** — other agents of this Source it may ask (`kind: "talk"`) or
131
132
  hand work to (`kind: "delegate"`, `mode: "await"` to wait for the answer,
132
133
  default, or `"handoff"` to let go). `to` is the other agent's key. A link
@@ -146,7 +147,8 @@ The tool names above are illustrations. Take real ones from
146
147
 
147
148
  Each of these reads the latest version, changes one thing, and stores the
148
149
  result as a new **draft** version (`--publish` also rolls it out, with
149
- `--yes`). A pulled `agent.json` is left alone; `agents pull` refreshes it.
150
+ `--yes`). A pulled `agent.json` is left alone; `agents pull --force` refreshes
151
+ it (without `--force`, a pull refuses to overwrite a file that differs).
150
152
 
151
153
  ```
152
154
  ekanos agents policy <key> # show
@@ -22,19 +22,38 @@ Built with `ekanos agents` by a Source admin.
22
22
  when a newer one is published.
23
23
  - **Rollback.** `ekanos agents rollback <key> --to <n> --yes` publishes an
24
24
  earlier version to every team that follows it.
25
+ - **Retiring it.** `ekanos agents archive <key> --yes` stops every team from
26
+ turning it on; it cannot be applied over or published until
27
+ `ekanos agents unarchive <key>`. It is refused while any team has it on,
28
+ and the refusal lists each team with the `teams agents disable` command
29
+ that turns it off there. `agents list` hides archived agents (`--all`
30
+ shows them). Archive only on the user's explicit yes.
25
31
  - **What stays the team's:** whether it is on, its triggers, its own
26
32
  connections, its run history, and whatever `teamCustomization` lets it add.
33
+ - **Confirming access.** The agent uses the connections of the person it
34
+ runs as, and in runs no one watches only once someone who sets it up
35
+ confirms it may: the Source admin with `ekanos teams agents confirm <team>
36
+ <key>` (or `teams agents enable <team> <key> --confirm-access` to turn it
37
+ on and confirm at once), or one of the team's agent managers with
38
+ **Confirm access** in the app. Each confirms as themselves; a plain team
39
+ member never does. It confirms only the version it printed: a newer
40
+ publish since is refused, not confirmed unseen.
27
41
  - **When a new version needs more access** than a team confirmed (a new
28
- product, a tool that now runs without approval), the team's owner is asked
29
- to confirm again; until then the agent keeps only what needs no new
30
- confirmation.
42
+ product or tool, `custom` → `read_only`/`all`, a tool that now runs without
43
+ approval), the publish is the confirmation: every following team moves to
44
+ it and stays confirmed, now in the publisher's name. No team is held.
45
+ `agents publish --confirm-access` also confirms every team on that version
46
+ that was never confirmed. A team that never confirmed moves unconfirmed; a
47
+ pinned team stays on its pin, and `agents publish` lists it with what the
48
+ new version would add and the `teams agents unpin` command.
31
49
 
32
50
  Good for: the same job done by several teams; a central owner who improves
33
51
  it over time; consistent behaviour and approvals.
34
52
 
35
53
  **A Source admin can do a team's part from the terminal**:
36
54
  `ekanos teams agents enable <team> <key> [--as <member-email>]` turns it on
37
- for the team (running as that member, the team's owner by default),
55
+ for the team (running as that member, the team's owner by default; with
56
+ `--confirm-access`, you confirm it in the same step),
38
57
  `ekanos teams agents pin|unpin`, `ekanos teams agents policy`, and
39
58
  `ekanos teams triggers|links|mcp` set up the rest. `ekanos teams agents list
40
59
  <team>` shows where each team stands and what it still needs connected.
@@ -18,7 +18,10 @@ guess.
18
18
  3. For a team: `npx @ekanos/cli teams show <team> <product> --source <slug> --json`
19
19
  shows what that team has already done (app fields entered, webhook URL
20
20
  minted, connected, who connected and when) and the link to the team's page
21
- in the app.
21
+ in the app. If it says the product is hidden from the team by its product
22
+ scope, the team cannot see it in the app however connected it is: show
23
+ the user the fix it prints (`ekanos sources scopes add <scope> <product>`,
24
+ or `ekanos teams scope set <team> <scope>`) and run it on their yes.
22
25
 
23
26
  Then tell the user, in two or three lines, what is done, what is left, and
24
27
  who does each remaining step. If a step needs Ekanos (the product is not
@@ -102,6 +105,34 @@ pilot), the team-side steps can be done from the CLI:
102
105
  5. Someone on the team opens the link from `teams show` and clicks Connect.
103
106
  6. `teams show` again: every step ✓.
104
107
 
108
+ ### A channel's own install: the Linear agent
109
+
110
+ Some integrations have a second connection beside the main one, and an
111
+ agent's channel trigger fires only once it is installed. Linear's is
112
+ `agent`: the team's own Linear app, installed in the team's Linear workspace
113
+ as a member people can @mention and assign. The personal connection
114
+ (`teams connect <team> linear`) is a different identity and does not make
115
+ mentions arrive. When the agent has any Linear trigger:
116
+
117
+ 1. `teams show <team> linear --json` → `connections`: the `agent` entry's
118
+ `credentialsSaved`, `connected` (installed) and `neededBy` (the agents
119
+ waiting on it), and in `teamApps` the `agent-events` webhook's `endpoint`.
120
+ 2. The Linear app itself (Linear › Settings › API › Applications › New): the
121
+ steps are in `teams show` under "Team app: Linear agent (agent)" —
122
+ redirect URIs, webhooks on with **Agent session events** and **Issues**.
123
+ 3. Its webhook URL: `teams webhook <team> linear agent-events` (once; paste
124
+ it into the Linear app's webhook URL).
125
+ 4. **In their own terminal:**
126
+ `npx @ekanos/cli teams connect <team> linear --connection agent --source <slug>`
127
+ — asks for the client ID, secret and webhook signing secret if any is
128
+ missing, opens the install for a Linear workspace admin to approve, and
129
+ waits until it is installed. (`teams connect <team> linear` with no
130
+ `--connection` offers this itself once the personal connection is made,
131
+ when the team has agents with Linear triggers.)
132
+ 5. `teams show` again: `✓ Linear agent (agent): app credentials saved ·
133
+ installed … · webhook URL made`. Then the end-to-end check in the
134
+ build-agent skill, § 4: a real @mention starts a run and the reply lands.
135
+
105
136
  ## 5. One connection for the whole Source
106
137
 
107
138
  Use it when one account at the provider serves many teams: one Zendesk where
@@ -130,6 +161,9 @@ the Source's connection.
130
161
  2. **The Source's webhook.** `npx @ekanos/cli routes webhook <product> --source <slug>`
131
162
  prints one URL, **once**, for the whole Source. Paste it into the
132
163
  provider at that moment (for Zendesk, the webhook the triggers notify).
164
+ Once a URL is live the command refuses to mint another: a new one
165
+ revokes it for every routed team. Add `--yes` only when the user is
166
+ ready to paste the new URL into the provider.
133
167
  The team webhooks from § 4 are not used for this connection.
134
168
  3. **Map values to teams.** `npx @ekanos/cli routes options <product> --source <slug>`
135
169
  lists what can be mapped (Zendesk organizations, with names), then one
@@ -171,16 +205,23 @@ from `teams show zendesk`.
171
205
  their terminal: subdomain, client ID, client secret, webhook signing
172
206
  secret. Any of them can be entered or changed later on its own
173
207
  (`--field <name>`); `teams show` says which are saved.
174
- 4. **Connect.** Someone on the team opens the link and connects, as the
175
- Zendesk agent the integration should reply as.
208
+ 4. **Connect.** `npx @ekanos/cli teams connect <team> zendesk --source <slug>`
209
+ opens the sign-in and waits; whoever approves it should be the Zendesk
210
+ agent the integration replies as (`--as <member-email>` to send the link
211
+ to that member instead). A team member can also connect from the team's
212
+ page in the app.
176
213
  5. **Zendesk triggers.** Objects and rules › Triggers: one for *Ticket is
177
214
  Created* and one for a customer's public reply, each notifying the webhook
178
215
  with the body from the steps. `"reply_as": "internal"` makes the agent's
179
216
  answer an internal note a person reviews before the customer sees it.
180
217
  Recommend that until the team trusts the agent; `"public"` lets it answer
181
218
  the customer directly.
182
- 6. **The agent's trigger.** In the app, on the agent: *A ticket is created*
183
- (and *A customer replies*), with any filters.
219
+ 6. **The agent's trigger.** In the template, for every team:
220
+ `npx @ekanos/cli agents triggers <key> add event new-tickets --event zendesk.ticket_created --source <slug>`
221
+ (and `zendesk.comment_added` for a customer's reply), with any
222
+ `--filter field=a,b`. For one team only, where the template lets teams
223
+ change triggers:
224
+ `npx @ekanos/cli teams triggers add <team> <key> event zendesk.ticket_created --source <slug>`.
184
225
  7. **Try it.** Open a test ticket as a customer and watch: the agent reads
185
226
  the ticket, looks things up, and answers on it. If it wants to change the
186
227
  ticket (status, priority, assignee), it leaves an internal note saying
@@ -194,7 +235,14 @@ from `teams show zendesk`.
194
235
  - **Tickets don't start the agent:** `teams show` should list a live webhook
195
236
  that has been used recently. If it has never been used, the provider is not
196
237
  calling it: check the Zendesk trigger's conditions and that it notifies the
197
- right webhook. If it has been used but nothing ran, check that the agent has
198
- a trigger for that event and that the team connected the product.
238
+ right webhook. If it has been used but nothing ran, run
239
+ `teams events <team> zendesk --since 24h`: each event says whether it
240
+ started a run, and if not, why (no enabled trigger subscribes to it, none
241
+ matched its filter, or it failed with the error shown).
242
+ - **Mentions in Linear do nothing:** `teams agents list <team>` — a
243
+ `channels` entry with `ready: false` names what is missing ("Linear agent
244
+ not installed for this team", or no webhook URL) and the command that
245
+ fixes it. Installed and still silent: the Linear app's webhook must send
246
+ **Agent session events** to the latest URL from `teams webhook`.
199
247
  - **A command says it needs a terminal:** it was run inside Claude. Ask them
200
248
  to run it in a terminal tab themselves.
@@ -37,6 +37,19 @@ as "what it is — when to use it".
37
37
  | **Source** (default) | `ekanos skills push <dir>` | Every team on the Source. An agent template may name it in `skills`. |
38
38
  | **Team** | `ekanos skills push <dir> --team <team-slug>` | That one team only. For content another team must not see (one bank's own guide). |
39
39
 
40
+ A template can't name a team skill, so a provided agent reads one only once
41
+ it is **attached** on that team, and only when the template allows team
42
+ skills (`"teamCustomization": { "skills": true }` in `agent.json`, applied
43
+ and published):
44
+
45
+ ```bash
46
+ npx @ekanos/cli teams agents skills <team> <key> --source <slug> # what it reads, and whether the team may add
47
+ npx @ekanos/cli teams agents skills <team> <key> add <skill-slug> --source <slug> # attach (team, Source or platform skill)
48
+ npx @ekanos/cli teams agents skills <team> <key> remove <skill-slug> --source <slug>
49
+ ```
50
+
51
+ The template's own skills stay; `remove` refuses them.
52
+
40
53
  Pushing is a Source admin's. A push is **live at once**: there is no draft
41
54
  and no publish step, and every agent naming the skill reads the new version
42
55
  on its next run. Show the user the folder before pushing it.
@@ -48,13 +61,19 @@ npx @ekanos/cli skills list --source <slug> --json # the Source's +
48
61
  npx @ekanos/cli skills list --team <team> --source <slug> # one team's own
49
62
  npx @ekanos/cli skills show <slug> --source <slug> # files, versions
50
63
  npx @ekanos/cli skills push agents/<key>/skills/<slug> --source <slug> --json
51
- npx @ekanos/cli skills pull <slug> --source <slug> [--out <dir>]
64
+ npx @ekanos/cli skills pull <slug> --source <slug> [--out <dir>] [--force] # --force: overwrite local edits
52
65
  ```
53
66
 
54
67
  `push` prints what changed (files added, changed, removed) and the new
55
68
  version; an identical folder is `unchanged` and stores nothing — safe to run
56
69
  again.
57
70
 
71
+ `npx @ekanos/cli skills archive <slug> [--team <team>] --source <slug> --yes`
72
+ retires a skill (only on the user's explicit yes): no agent can name it and a
73
+ push to it is refused until `skills unarchive <slug>`. It is refused while an
74
+ agent names it or a team agent has it attached; the refusal lists each use
75
+ and the command that stops it. Platform skills cannot be archived.
76
+
58
77
  ## With `agents apply`
59
78
 
60
79
  `ekanos agents apply agents/<key>` pushes every `agents/<key>/skills/<slug>/`
@@ -13,7 +13,11 @@ Ask in the interview: should the Source set what starts the agent for every
13
13
  team (recommended when every team works the same way), or each team? Either
14
14
  way say what each team must connect first, so the checklist is complete.
15
15
  A webhook trigger's secret is always per team: the template declares the
16
- trigger, each team creates or rotates its own secret in the app.
16
+ trigger, each team creates or rotates its own secret in the app, or a
17
+ Source admin does with `ekanos teams triggers rotate <team> <key> <trigger-key>`
18
+ (shown once, saved to a file only the user can read and named in the
19
+ output — the user copies it to the sender; never open or print that file
20
+ yourself; replacing a live one needs `--yes`).
17
21
 
18
22
  A Source admin can add them for the team from the terminal instead:
19
23
  `ekanos teams triggers list|add|remove <team> <key> …` — for example
@@ -22,9 +26,15 @@ A Source admin can add them for the team from the terminal instead:
22
26
  `… webhook --prompt "…"` (prints the URL and token once) or `… manual`.
23
27
  Any event in a connected integration's `agentEvents` is added this way,
24
28
  including every Linear integration event (`event linear.issue_labeled
25
- --filter '{"labels":["feedback"]}'`). Only two trigger *types* are app-only:
26
- a **Slack** trigger, and a **Linear (Agents app)** trigger — Ekanos's own
27
- Linear app, which answers @mentions and assignments only. That app is not
29
+ --filter '{"labels":["feedback"]}'`). A **Slack** trigger and a **Linear
30
+ (Agents app)** trigger — Ekanos's own Linear app, which answers @mentions
31
+ and assignments — answer through an install the team makes first:
32
+ `ekanos teams connect <team> slack` or `ekanos teams connect <team>
33
+ linear-app` (a one-time link for a team member, opened and waited on like
34
+ any `teams connect`). Then `ekanos teams triggers add <team> <key> slack
35
+ --channel '#support' [--dms] --yes` (the bot must be in each channel; `--yes`
36
+ confirms that anyone there can ask the agent to act) or `… linear [--label
37
+ <name>]… [--no-mention]`. That app is not
28
38
  the Linear integration, and its limits are not the integration's: an agent
29
39
  that should start when a label is applied uses `linear.issue_labeled`, not an
30
40
  @mention. When a provided agent's
@@ -58,11 +68,28 @@ finishes that event's own setup on the provider's side. That is a setup
58
68
  step, not a missing event — say which step, as below.
59
69
 
60
70
  **Linear** — the agent becomes a teammate in Linear. Each team needs two
61
- things in the app: each person's own Linear connection (for the tools), and
62
- the team's own Linear app for the agent (client id, secret and webhook
63
- signing secret, entered in Ekanos).
71
+ identities, and they are not the same thing:
72
+
73
+ - **The personal connection** (`default`): someone's own Linear sign-in, for
74
+ the agent's tools. `teams connect <team> linear`.
75
+ - **The Linear agent** (`agent`): the team's own Linear app, installed in its
76
+ workspace as a member people can @mention and assign. Linear sends every
77
+ agent event below only to an installed app, so **without it no Linear
78
+ trigger ever fires** — the trigger is saved, on, and silent.
79
+ `teams connect <team> linear --connection agent` (asks for the app's client
80
+ id, secret and webhook signing secret, opens the install, waits), plus the
81
+ webhook URL: `teams webhook <team> linear agent-events`.
82
+
83
+ Check both with `teams show <team> linear`: under **Connections**, `default`
84
+ connected, and `agent` with app credentials saved, installed and its webhook
85
+ URL made. `teams agents list <team>` lists a Linear-triggered agent whose
86
+ agent is not installed as missing ("Linear agent not installed for this
87
+ team"), and the agent's Setup tab in the app says the same.
64
88
  Guide: https://sdk.ekanos.dev/guides/linear-agent
65
89
 
90
+ Every event needs the Linear agent installed; the last column is what the
91
+ installed app's webhook must also send.
92
+
66
93
  | Event | Starts when | Filter keys | Needs on the team's Linear app |
67
94
  |---|---|---|---|
68
95
  | `linear.mentioned` | someone @mentions the agent, or writes to it again in that conversation | `teamKeys` | webhook with **Agent session events** ticked |
@@ -91,7 +118,16 @@ brands, groups and organizations match by name or id. Where the answer goes
91
118
  1. Agents → "Provided for your team" → Turn on.
92
119
  2. Connect every `required` product and sign in to any MCP server that needs
93
120
  it (the agent shows what is missing).
94
- 3. Do each integration's own setup (team app, webhook) from its guide.
95
- 4. Confirm access if asked.
96
- 5. Add the triggers above — unless the template already sets them — then
97
- run one real example and review it.
121
+ 3. Install the channel each trigger listens on: for any Linear trigger the
122
+ Linear agent (`teams connect <team> linear --connection agent`, and its
123
+ webhook URL), for a Slack trigger the team's Slack. `teams agents list
124
+ <team>` shows each agent's `channels`; none may be `ready: false`.
125
+ 4. Do each integration's own setup (team app, webhook) from its guide.
126
+ 5. Confirm access: the Source admin runs `npx @ekanos/cli teams agents
127
+ confirm <team> <key> --source <slug>` (or turned it on with
128
+ `--confirm-access`), or a team manager confirms in the app. `teams agents
129
+ list <team>` shows any agent still unconfirmed.
130
+ 6. Add the triggers above — unless the template already sets them.
131
+ 7. Prove it end to end: a real @mention (or the real event) → a run in
132
+ `runs list --team <team>` → the agent's reply where it was asked. A test
133
+ run started by hand does not count; it passes without the channel.
@@ -77,9 +77,9 @@ import {
77
77
  </Stat>;
78
78
  ```
79
79
 
80
- - `StatLabel` is uppercase `text-xs` — the one place `text-xs` is a primary
81
- label. `StatValue` is the heading face at `text-2xl`, `tracking-tight`,
82
- `tabular-nums`. Do not override those sizes.
80
+ - `StatLabel` is the uppercase `text-eyebrow` overline. `StatValue` is
81
+ `figure`: the heading face at the Headline tier, tabular. Do not override
82
+ those sizes.
83
83
  - `StatChange`'s `tone` is the READING, not the direction: expenses falling is
84
84
  `positive`. It pairs an arrow glyph with the color, so the tone never rides
85
85
  on hue alone.
@@ -48,6 +48,7 @@ command takes `--source <slug>` (else the Source `ekanos use` set) and
48
48
  ```sh
49
49
  npx @ekanos/cli teams create "Bank A" --slug bank-a # you are its owner
50
50
  npx @ekanos/cli teams create "Bank A" --owner ana@bank-a.com # ana is invited as owner
51
+ npx @ekanos/cli teams rename bank-a "Bank A Support" # the slug follows the name
51
52
  npx @ekanos/cli teams roles list bank-a # roles + permissions (e.g. agents.review)
52
53
  npx @ekanos/cli teams members invite bank-a raj@bank-a.com --role admin # default role: member
53
54
  npx @ekanos/cli teams members list bank-a # members and pending invitations
@@ -92,7 +93,12 @@ Everything in the catalog (`npx @ekanos/cli catalog --source <slug> --json`) is
92
93
  `linear.issue_labeled` and `linear.issue_created`; Zendesk declares
93
94
  `zendesk.ticket_created` and `zendesk.comment_added`. The catalog's
94
95
  `agentEvents` is the authority: read it before concluding a product lacks
95
- an event, never infer the set from an example.
96
+ an event, never infer the set from an example. An event can also need a
97
+ **channel install** before it ever fires: every Linear event arrives only
98
+ through the team's Linear agent (`teams connect <team> linear --connection
99
+ agent`), a second identity beside the personal connection. `teams agents
100
+ list` names any agent whose trigger waits on one (`channels`, `ready:
101
+ false`).
96
102
  - **Experience** — an Ekanos-native capability (Agents, Workflows, Home…).
97
103
  Never "connected"; it is simply on or off for the Source.
98
104
 
@@ -161,9 +167,11 @@ every team can use them, with `--team <slug>` only that team can.
161
167
 
162
168
  **Knowledge** is Ekanos's own knowledge base (no outside account): markdown
163
169
  articles, one collection per team plus the Source's **General** collection
164
- every team reads. A Source admin loads folders of `.md` with
165
- `ekanos knowledge push <dir> [--team <slug>]`; team members edit theirs in
166
- the app (Agents → Knowledge). Agents granted `search_knowledge` /
170
+ that every team's agents granted `search_knowledge` also read. A Source admin loads folders of `.md` with
171
+ `ekanos knowledge push <dir> [--team <slug>]` (`--prune` also deletes the
172
+ articles an earlier push of that folder made whose files are gone, never
173
+ ones written or edited in the app); team members edit theirs in the app
174
+ (Agents → Knowledge). Agents granted `search_knowledge` /
167
175
  `read_knowledge_article` search their own team's collection and General.
168
176
  Skills say *how* to work; Knowledge holds the facts an agent looks up.
169
177
 
@@ -176,21 +184,38 @@ always `ekanos teams <area> <verb> <team> …`:
176
184
  - `ekanos teams agents list <team>` — provided agents, on or off, the version
177
185
  each runs (pinned or following), triggers, links, the team's MCP servers,
178
186
  and what each still needs connected.
179
- - `ekanos teams agents enable <team> <key> [--as <member-email>]` /
180
- `disable <team> <key>` — the app's "Turn on" / "Turn off". The agent runs
181
- as a team member who manages agents (the team's owner by default); that
182
- person confirms in the app that it may use their connections.
187
+ - `ekanos teams agents enable <team> <key> [--as <member-email>]
188
+ [--confirm-access]` / `disable <team> <key>` — the app's "Turn on" /
189
+ "Turn off". The agent runs as a team member who manages agents (the
190
+ team's owner by default); `--confirm-access` also confirms it, as you.
191
+ - `ekanos teams agents confirm <team> <key>` — you confirm, as yourself,
192
+ that the agent may use its connections (the person it runs as's) in runs
193
+ no one watches; the output says which products' connections that covers.
194
+ Whoever sets an agent up confirms it — the Source admin, or a team
195
+ manager in the app — never a plain team member. It confirms only the
196
+ version it printed: a newer publish since is refused, to be reviewed and
197
+ confirmed again.
183
198
  - `ekanos teams agents pin <team> <key> <version>` / `unpin <team> <key>`.
184
199
  - `ekanos teams agents policy <team> <key>` — every tool the agent can call,
185
200
  read or write, and whether it runs on its own or waits for approval;
186
201
  `… policy <team> <key> set <tool> auto|approve`, `unset <tool>`,
187
202
  `--reads auto|approve --writes auto|approve`. A provided agent's policy
188
203
  follows its template unless the template turns on team overrides for it.
204
+ On any agent, a change that lets more run on its own drops the
205
+ confirmation, and the agent uses only what needs none until someone who
206
+ sets it up confirms again (`--confirm-access` does it in the same step).
207
+ - `ekanos teams agents skills <team> <key> [add|remove <skill>]` — the
208
+ skills the agent reads; attach a team skill (pushed with
209
+ `skills push --team`) or a Source one. A provided agent takes them only
210
+ when its template's `teamCustomization.skills` is on; its own stay.
189
211
  - `ekanos teams triggers list|add|remove <team> <key> …` — manual, schedule
190
- (`--cron`, `--timezone`), webhook (URL and token shown once) and
212
+ (`--cron`, `--timezone`), webhook (the token goes to a file only the
213
+ user can read, never the output) and
191
214
  integration events (`event zendesk.ticket_created --filter '{…}'`, or any
192
215
  other id in the product's `agentEvents`, e.g. `event linear.issue_labeled
193
- --filter '{"labels":["feedback"]}'`).
216
+ --filter '{"labels":["feedback"]}'`), plus `slack --channel '#name' [--dms]
217
+ --yes` and `linear [--label <name>]` once the team has installed Slack or
218
+ Ekanos's Linear app with `ekanos teams connect <team> slack|linear-app`.
194
219
  - `ekanos teams links list|add|remove <team> <from-key> [<to-key>] --kind
195
220
  talk|delegate [--mode await|handoff]`.
196
221
  - `ekanos teams mcp list|add|status|token|effect <team> [<server-key> …]` — a
@@ -222,7 +247,7 @@ reviewer's queue.
222
247
  npx @ekanos/cli reviewers list --source <slug> --json
223
248
  npx @ekanos/cli reviewers add <email> --reach source --source <slug>
224
249
  npx @ekanos/cli reviewers add <email> --reach team --team <team-slug> --source <slug>
225
- npx @ekanos/cli reviewers remove <email> [--team <team-slug>] --source <slug>
250
+ npx @ekanos/cli reviewers remove <email> [--team <team-slug>] --source <slug> --yes
226
251
  ```
227
252
 
228
253
  `remove` without `--team` takes the person off at every reach; with it, only
@@ -235,11 +260,11 @@ is refused (`USER_NOT_IN_SOURCE`): `ekanos teams list` shows the teams.
235
260
  |---|---|
236
261
  | Making a product available to a Source; granting seats | Ekanos super admin, in Ekanos's admin |
237
262
  | Building or updating an integration | A developer, with `ekanos validate` / `ekanos publish` |
238
- | Agents provided for every team | A Source admin, with `ekanos agents` |
239
- | Testing an unpublished agent version on one team | A Source admin, with `ekanos agents test <key> --team <slug>` |
263
+ | Agents provided for every team | A Source admin, with `ekanos agents` (`agents archive <key>` retires one once no team has it on) |
264
+ | Testing an unpublished agent version on one team | A Source admin: `ekanos teams agents enable\|pin <team> <key> --draft`, then `ekanos agents test <key> --team <slug>` |
240
265
  | Running a team's agent, reading its runs (transcript, tool calls) | A team's agent manager in the app, or a Source admin with `ekanos runs` |
241
- | Deciding what an agent run waits on (approve, reject, edit & send a reply) | A team's agent manager in the app, or a Source admin with `ekanos approvals` |
242
- | Skills (SKILL.md folders) for every team, or one team's own | A Source admin, with `ekanos skills push` (`--team <slug>` for one team) |
266
+ | Deciding what an agent run waits on (approve, reject, edit & send a reply) | A team's agent manager in the app, or a Source admin with `ekanos approvals` (for a team's own agent, only a Source admin who manages that team's agents) |
267
+ | Skills (SKILL.md folders) for every team, or one team's own | A Source admin, with `ekanos skills push` (`--team <slug>` for one team); `ekanos skills archive` retires one nothing uses |
243
268
  | Knowledge articles for every team (General), or one team's own | A Source admin, with `ekanos knowledge push` (`--team <slug>` for one team); a team's members in the app |
244
269
  | Who decides agent drafts that wait for a person | A Source admin, with `ekanos reviewers` |
245
270
  | An integration's app for the whole Source (client ID and secret) | A Source admin, with `ekanos apps set` at their own terminal |
@@ -248,5 +273,9 @@ is refused (`USER_NOT_IN_SOURCE`): `ekanos teams list` shows the teams.
248
273
  | A team's own app for an integration (client ID, secrets, webhook URL) | The team in the app, or a Source admin with `ekanos teams` |
249
274
  | A provided agent's triggers, links and approvals | A Source admin, in the template (`ekanos agents triggers / links / policy / overrides`); teams change them only where `teamOverrides` allows |
250
275
  | Creating a team, inviting its members, changing their roles | A Source admin, with `ekanos teams create` / `ekanos teams members` (or the team's owner in the app) |
251
- | Connecting an integration (signing in) | Each team, in the app |
276
+ | Connecting an integration for a team (signing in) | A team member in the app, or a Source admin with `ekanos teams connect <team> <product>` (`--as <member-email>` when the connection is a person's own) |
252
277
  | Turning on a provided agent for a team, pinning its version, its triggers, links, MCP servers and approval policy | Each team in the app, or a Source admin with `ekanos teams agents\|triggers\|links\|mcp` |
278
+ | Which products a team sees in the app (product scopes) | A Source admin: `ekanos sources scopes` (and `add`/`remove <scope> <product>`), `ekanos teams scope show\|set <team>`; creating a scope is in /admin |
279
+ | Is a team's agent live, and if not, what is the next step | A Source admin, with `ekanos teams agents show <team> <key>`; the whole team on one screen with `ekanos teams show <team>` |
280
+ | Disconnecting a team's integration, removing a team's MCP server | A Source admin, with `ekanos teams disconnect <team> <product> --yes` / `ekanos teams mcp remove <team> <server-key> --yes`, or the team in the app |
281
+ | Confirming an agent may use its connections | Whoever sets it up, as themselves: the Source admin with `ekanos teams agents confirm <team> <key>` (or `enable --confirm-access`, `agents publish --confirm-access`), or a team manager with **Confirm access** in the app — never a plain member. A publish is the confirmation for following teams: no team is held on an earlier version |
@@ -116,8 +116,8 @@ import {
116
116
  </div>
117
117
  ```
118
118
 
119
- `Stat` owns the sizes — the heading face, `text-2xl`, `tracking-tight`,
120
- `tabular-nums`, and the arrow glyph that pairs with `StatChange`'s color so
119
+ `Stat` owns the sizes — the `figure` value (heading face, Headline tier,
120
+ tabular), the `text-eyebrow` label, and the arrow glyph that pairs with `StatChange`'s color so
121
121
  the tone never rides on hue alone. Don't override them, and don't rebuild
122
122
  them by hand: a Source that swaps typefaces carries the component, not your
123
123
  spans.