@ekanos/cli 0.14.0 → 0.16.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 (115) hide show
  1. package/README.md +41 -4
  2. package/dist/auth/ekanos-api.d.ts +23 -0
  3. package/dist/auth/ekanos-api.js +33 -6
  4. package/dist/auth/ekanos-api.js.map +1 -1
  5. package/dist/commands/agents.d.ts +2 -2
  6. package/dist/commands/agents.js +14 -20
  7. package/dist/commands/agents.js.map +1 -1
  8. package/dist/commands/apps.d.ts +11 -3
  9. package/dist/commands/apps.js +86 -28
  10. package/dist/commands/apps.js.map +1 -1
  11. package/dist/commands/catalog.d.ts +4 -2
  12. package/dist/commands/catalog.js +166 -35
  13. package/dist/commands/catalog.js.map +1 -1
  14. package/dist/commands/login.d.ts +2 -0
  15. package/dist/commands/login.js +17 -0
  16. package/dist/commands/login.js.map +1 -1
  17. package/dist/commands/runs.d.ts +7 -3
  18. package/dist/commands/runs.js +24 -6
  19. package/dist/commands/runs.js.map +1 -1
  20. package/dist/commands/scope-notice.d.ts +7 -0
  21. package/dist/commands/scope-notice.js +4 -11
  22. package/dist/commands/scope-notice.js.map +1 -1
  23. package/dist/commands/sources-roles.d.ts +5 -0
  24. package/dist/commands/sources-roles.js +235 -0
  25. package/dist/commands/sources-roles.js.map +1 -0
  26. package/dist/commands/sources.d.ts +5 -0
  27. package/dist/commands/sources.js +6 -1
  28. package/dist/commands/sources.js.map +1 -1
  29. package/dist/commands/team-agent-readiness.d.ts +23 -17
  30. package/dist/commands/team-agent-readiness.js +57 -90
  31. package/dist/commands/team-agent-readiness.js.map +1 -1
  32. package/dist/commands/team-agents-agents.d.ts +8 -5
  33. package/dist/commands/team-agents-agents.js +173 -58
  34. package/dist/commands/team-agents-agents.js.map +1 -1
  35. package/dist/commands/team-agents-define.d.ts +31 -0
  36. package/dist/commands/team-agents-define.js +176 -0
  37. package/dist/commands/team-agents-define.js.map +1 -0
  38. package/dist/commands/team-agents-mcp.js +112 -10
  39. package/dist/commands/team-agents-mcp.js.map +1 -1
  40. package/dist/commands/team-agents-triggers.d.ts +1 -1
  41. package/dist/commands/team-agents-triggers.js +137 -5
  42. package/dist/commands/team-agents-triggers.js.map +1 -1
  43. package/dist/commands/team-agents.d.ts +4 -1
  44. package/dist/commands/team-agents.js +17 -4
  45. package/dist/commands/team-agents.js.map +1 -1
  46. package/dist/commands/team-llm-key.d.ts +14 -0
  47. package/dist/commands/team-llm-key.js +122 -0
  48. package/dist/commands/team-llm-key.js.map +1 -0
  49. package/dist/commands/teams-connect.js +123 -31
  50. package/dist/commands/teams-connect.js.map +1 -1
  51. package/dist/commands/teams-lifecycle.d.ts +90 -0
  52. package/dist/commands/teams-lifecycle.js +457 -0
  53. package/dist/commands/teams-lifecycle.js.map +1 -0
  54. package/dist/commands/teams-onboard.d.ts +14 -0
  55. package/dist/commands/teams-onboard.js +62 -13
  56. package/dist/commands/teams-onboard.js.map +1 -1
  57. package/dist/commands/teams-overview.js +7 -3
  58. package/dist/commands/teams-overview.js.map +1 -1
  59. package/dist/commands/teams.d.ts +25 -5
  60. package/dist/commands/teams.js +101 -39
  61. package/dist/commands/teams.js.map +1 -1
  62. package/dist/commands/workflows.d.ts +37 -0
  63. package/dist/commands/workflows.js +589 -0
  64. package/dist/commands/workflows.js.map +1 -0
  65. package/dist/connect-fields.d.ts +22 -0
  66. package/dist/connect-fields.js +115 -0
  67. package/dist/connect-fields.js.map +1 -0
  68. package/dist/context.d.ts +12 -0
  69. package/dist/context.js +32 -9
  70. package/dist/context.js.map +1 -1
  71. package/dist/index.d.ts +13 -0
  72. package/dist/index.js +367 -133
  73. package/dist/index.js.map +1 -1
  74. package/dist/invocation.d.ts +31 -0
  75. package/dist/invocation.js +58 -0
  76. package/dist/invocation.js.map +1 -0
  77. package/dist/runs-api.js +8 -3
  78. package/dist/runs-api.js.map +1 -1
  79. package/dist/safe-fs.d.ts +18 -0
  80. package/dist/safe-fs.js +57 -0
  81. package/dist/safe-fs.js.map +1 -1
  82. package/dist/secret-form.d.ts +48 -0
  83. package/dist/secret-form.js +212 -0
  84. package/dist/secret-form.js.map +1 -0
  85. package/dist/secret-input.d.ts +96 -0
  86. package/dist/secret-input.js +299 -0
  87. package/dist/secret-input.js.map +1 -0
  88. package/dist/team-connect-api.d.ts +78 -3
  89. package/dist/team-connect-api.js +17 -2
  90. package/dist/team-connect-api.js.map +1 -1
  91. package/dist/team-lifecycle-api.d.ts +435 -0
  92. package/dist/team-lifecycle-api.js +301 -0
  93. package/dist/team-lifecycle-api.js.map +1 -0
  94. package/dist/teams-api.d.ts +13 -1
  95. package/dist/teams-api.js +90 -31
  96. package/dist/teams-api.js.map +1 -1
  97. package/dist/unknown-command.d.ts +18 -0
  98. package/dist/unknown-command.js +50 -0
  99. package/dist/unknown-command.js.map +1 -0
  100. package/dist/workflows-api.d.ts +69 -0
  101. package/dist/workflows-api.js +182 -0
  102. package/dist/workflows-api.js.map +1 -0
  103. package/package.json +3 -3
  104. package/templates/AGENTS.md.tmpl +6 -4
  105. package/templates/claude-skill.md.tmpl +4 -1
  106. package/templates/package.json.tmpl +4 -4
  107. package/templates/skills/build-agent/SKILL.md +56 -22
  108. package/templates/skills/build-agent/references/agent-json.md +4 -1
  109. package/templates/skills/build-agent/references/app-setup.md +14 -7
  110. package/templates/skills/build-agent/references/rollout.md +40 -20
  111. package/templates/skills/build-agent/references/set-up-an-integration.md +46 -29
  112. package/templates/skills/build-agent/references/triggers.md +4 -3
  113. package/templates/skills/build-integration/references/widget-design.md +1 -1
  114. package/templates/skills/ekanos-platform/SKILL.md +77 -23
  115. package/templates/skills/polish-widgets/references/patterns.md +3 -3
@@ -39,9 +39,15 @@ installed — so check it, every time (§ 4, "Make it reachable").
39
39
  ## Hard rules
40
40
 
41
41
  - Never ask for, accept or write a secret (API key, client secret, webhook
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.
42
+ signing secret), and never read one from a file or a variable yourself.
43
+ The user enters it, and it never passes through you: run the command with
44
+ `--browser` (`apps set`, `apps connect`, `teams app set`, `teams connect`,
45
+ `teams mcp token`, `teams llm-key set` take it) and the CLI opens a
46
+ one-time form in their browser on this computer — tell them to fill it in
47
+ there. If they would rather, they put it in an environment variable or a
48
+ file only they can read, and you pass `--secret-env <NAME>` or
49
+ `--secret-file <path>`. Or they type it at their own terminal, or a team
50
+ enters it in the Ekanos app. A secret is never a value on the command line.
45
51
  - Never `publish`, `rollback` or `archive` without the user's explicit yes to
46
52
  that version or agent, after they have seen it. `--yes` records that
47
53
  consent; it is never a way past a question.
@@ -105,7 +111,8 @@ list` to find the role holding `agents.review` for reviewers — see the
105
111
  `ekanos-platform` skill, "Onboarding a team"), and send the member who will
106
112
  sign in the link from `ekanos teams connect <team> <product>`. For the
107
113
  Source's app itself, `references/app-setup.md` has the console walk-through.
108
- Secrets are only ever entered at the user's terminal or in the app.
114
+ Secrets are only ever entered by the user — in the `--browser` form, at
115
+ their terminal, or in the app — never through you.
109
116
 
110
117
  ## 2. The interview
111
118
 
@@ -188,25 +195,52 @@ in parentheses are the recommendation when the user has no preference.
188
195
  new draft; publishing puts the team back to following.
189
196
  4. Ask: publish this version to every team now? Only on yes:
190
197
  `npx @ekanos/cli agents publish <key> --source <slug> --to <n> --yes`.
191
- When the user is the person the agent runs as on their teams, ask once
192
- whether to add `--confirm-access` (it confirms, as them, that the agent
193
- may use their connections there, and moves those teams at once; never
194
- add it without their yes). A version that reaches further than a team
195
- confirmed does not break that team: it is **held** on the version it
196
- runs until the person it runs as confirms. The output lists each held
197
- team, what the new version adds, who confirms and the `teams agents
198
- confirm` command (which moves it) — relay it; never send them to the app
199
- for it.
198
+ The publish is the confirmation: every team that follows the agent
199
+ moves to the new version, and one that had confirmed what it may use
200
+ stays confirmed, now in the publisher's name — even when the version
201
+ reaches further. No team is held. Ask once whether to add
202
+ `--confirm-access` (it also confirms, as the user, every team on that
203
+ version that was never confirmed; never add it without their yes). The
204
+ output lists any team pinned to another version, what the new version
205
+ would add to it, and the `teams agents unpin` command that moves it —
206
+ relay it.
200
207
  5. If anything waits for approval, name its reviewers (**Reviewers**
201
208
  below) before teams turn it on — a draft nobody may decide just waits.
202
209
  6. Hand over the team-side checklist (`references/triggers.md` has the
203
210
  per-integration parts): find it under Agents → "Provided for your team",
204
211
  Turn on, connect what it needs, **install the channel's agent for a
205
- channel trigger**, confirm access (`teams agents confirm <team> <key>`,
206
- by the person it runs as, or `teams agents enable … --confirm-access`
207
- when that is the user), add triggers. Suggest one team pilots
212
+ channel trigger**, confirm access (`teams agents confirm <team> <key>`
213
+ or `teams agents enable … --confirm-access`, as the user; or a team
214
+ manager in the app — never a plain member), add triggers. Suggest one
215
+ team pilots
208
216
  it first, and do § 4 with them.
209
217
 
218
+ ## 3b. Only one team, or only the user: a team's own or a personal agent
219
+
220
+ When the agent is for one team only, or for the user alone (§ 2's rollout
221
+ question, `references/rollout.md`), skip the template: the same files make a
222
+ team's own agent, or with `--personal` the user's own.
223
+
224
+ 1. On their go: `npx @ekanos/cli teams agents create <team> --from agents/<key> --source <slug> --json`
225
+ (add `--personal` for the user's own). The user becomes its creator, so
226
+ they must be an active member of that team; a `NOT_A_TEAM_MEMBER` refusal
227
+ names the command that adds them. Skill folders beside it are pushed as
228
+ that team's skills. Drop any field only a template has (exit 3 lists them).
229
+ 2. It starts as a draft:
230
+ `npx @ekanos/cli teams agents enable <team> <key> --source <slug> --json`.
231
+ Confirm what it may use only with the user's yes (`--confirm-access` on
232
+ `create` or `enable`, or `teams agents confirm <team> <key>`); a personal
233
+ agent's creator alone may.
234
+ 3. Start it from a schedule or a webhook:
235
+ `npx @ekanos/cli teams triggers add <team> <key> schedule --cron "0 8 * * 1-5" --timezone <zone> --prompt "…" --json`
236
+ or `… webhook --prompt "…"`. The webhook's token is saved to a file only
237
+ the user can read — never open or print it; tell them a personal agent's
238
+ token lets whoever holds it make the agent act as them.
239
+ 4. Later changes: edit the files and
240
+ `npx @ekanos/cli teams agents apply <team> agents/<key> --base-version <n> --json`
241
+ (`<n>` from `teams agents show`). Never `--overwrite` a conflict you have
242
+ not shown the user.
243
+
210
244
  ## 4. Make it reachable, and prove it end to end
211
245
 
212
246
  For each team that turns on an agent with a channel trigger, start with
@@ -224,12 +258,12 @@ screen). For the detail behind it:
224
258
  and `agent` (`credentialsSaved`, `connected` = installed, `neededBy`),
225
259
  and the `agent-events` webhook in `teamApps[].webhooks` must have an
226
260
  `endpoint`. Read the state back to the user in those words.
227
- 3. Not installed: the user runs, **in their own terminal** (it asks for the
228
- Linear app's secrets, which you never handle):
229
- `npx @ekanos/cli teams connect <team> linear --connection agent --source <slug>`.
230
- It asks for the app's client ID, secret and webhook signing secret if
231
- missing, opens the install (a Linear workspace admin approves it) and
232
- waits. No webhook URL yet: `npx @ekanos/cli teams webhook <team> linear
261
+ 3. Not installed: run
262
+ `npx @ekanos/cli teams connect <team> linear --connection agent --browser --source <slug>`
263
+ (or the user runs it without `--browser` in their own terminal). If the
264
+ app's client ID, secret or webhook signing secret is missing, it opens a
265
+ form in the user's browser for them to fill — you never handle those —
266
+ then opens the install (a Linear workspace admin approves it) and waits. No webhook URL yet: `npx @ekanos/cli teams webhook <team> linear
233
267
  agent-events --source <slug>` (shown once, and saved to a file only the
234
268
  user can read — the output names it; the user copies it into the Linear
235
269
  app. Never open or print that file yourself).
@@ -56,7 +56,10 @@ conflicting change unless `--overwrite`. Unknown fields are refused.
56
56
  ```
57
57
 
58
58
  The tool names above are illustrations. Take real ones from
59
- `ekanos catalog --json`.
59
+ `ekanos catalog --json`; `ekanos catalog <product> --json` gives each tool's
60
+ `inputSchema` (when a tool needs an id, another tool of the product returns
61
+ it) and the product's `connection` (`connectedBy`, `runsUse`,
62
+ `sourceConnection`).
60
63
 
61
64
  ## Fields
62
65
 
@@ -41,23 +41,30 @@ working from those rather than from Ekanos.
41
41
  the provider's docs rather than guessing.
42
42
  - The last console step is always "copy the client ID and the secret".
43
43
  **Never ask them to paste the secret into the chat.** For the Source's app,
44
- have them run, **in their own terminal**:
44
+ run this yourself, and tell them a form is opening in their browser:
45
45
 
46
46
  ```bash
47
- npx @ekanos/cli apps set <product> --source <slug>
47
+ npx @ekanos/cli apps set <product> --browser --source <slug>
48
48
  ```
49
49
 
50
- It asks for the client ID, then the secret with hidden input; Enter keeps
51
- a saved value, so either can be changed on its own. For a team's
52
- app, they enter the fields in the team's setup panel in the Ekanos app.
50
+ The form asks for the client ID and the secret; a field left empty keeps
51
+ its saved value, so either can be changed on its own. What they type goes
52
+ from their browser to the CLI and on to Ekanos, never to you. (Or they run
53
+ `npx @ekanos/cli apps set <product> --source <slug>` in their own terminal,
54
+ which asks with hidden input.) For a team's app,
55
+ `npx @ekanos/cli teams app set <team> <product> --browser --source <slug>`
56
+ does the same, or they enter the fields in the team's setup panel in the
57
+ Ekanos app.
53
58
  - Then check: `apps show <product> --source <slug> --json` should say
54
59
  `configured: true`, and the catalog's step should be `done`. Tell them
55
60
  teams can now connect, and what the team-side steps are.
56
61
 
57
62
  ## When it goes wrong
58
63
 
59
- - `apps set` says it needs a terminal: it was run inside Claude or a script.
60
- Ask them to run it in a terminal tab themselves.
64
+ - `apps set` says there is no terminal to ask at: add `--browser`. If
65
+ `--browser` is refused (CI, SSH, no display), ask them to run it in a
66
+ terminal tab themselves. The form gives up after five minutes; run it
67
+ again for a fresh one.
61
68
  - `apps set` asks which host: they are signed in to more than one Ekanos;
62
69
  add `--host <url>` (the Source's site) or log out of the other.
63
70
  - Sign-in later fails with a redirect mismatch: the app is missing one of the
@@ -31,25 +31,21 @@ Built with `ekanos agents` by a Source admin.
31
31
  - **What stays the team's:** whether it is on, its triggers, its own
32
32
  connections, its run history, and whatever `teamCustomization` lets it add.
33
33
  - **Confirming access.** The agent uses the connections of the person it
34
- runs as, and in runs no one watches only once that person confirms it may:
35
- `ekanos teams agents confirm <team> <key>`, signed in as themselves (or
36
- `teams agents enable <team> <key> --confirm-access` to turn it on as
37
- yourself and confirm at once). Nobody confirms for anyone else.
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.
38
41
  - **When a new version needs more access** than a team confirmed (a new
39
42
  product or tool, `custom` → `read_only`/`all`, a tool that now runs without
40
- approval), that team is **held**: it keeps running the version it is on,
41
- confirmed and working, and the new one waits until the person it runs as
42
- confirms it — `ekanos teams agents confirm <team> <key>`, which prints the
43
- version it confirms and moves the team to it at once (or **Confirm and
44
- update** on the agent's page); a version published after that is refused,
45
- not confirmed unseen. Nobody
46
- else can move it. Skills, instructions, model, triggers and links never
47
- hold a team. `agents publish` lists every held team, what the version adds,
48
- who confirms and the command; `agents publish --confirm-access` confirms,
49
- and moves, every team where the agent runs as the publisher. `teams agents
50
- list|show` say "held on vN, vM waiting for confirmation" — the agent is
51
- still live. A held team that gets another publish waits for the newest; a
52
- team that never confirmed simply moves; a pinned team stays on its pin.
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.
53
49
 
54
50
  Good for: the same job done by several teams; a central owner who improves
55
51
  it over time; consistent behaviour and approvals.
@@ -57,7 +53,7 @@ it over time; consistent behaviour and approvals.
57
53
  **A Source admin can do a team's part from the terminal**:
58
54
  `ekanos teams agents enable <team> <key> [--as <member-email>]` turns it on
59
55
  for the team (running as that member, the team's owner by default; with
60
- `--confirm-access`, as you, confirmed in the same step),
56
+ `--confirm-access`, you confirm it in the same step),
61
57
  `ekanos teams agents pin|unpin`, `ekanos teams agents policy`, and
62
58
  `ekanos teams triggers|links|mcp` set up the rest. `ekanos teams agents list
63
59
  <team>` shows where each team stands and what it still needs connected.
@@ -69,11 +65,35 @@ plan is ready.
69
65
 
70
66
  ## A team's own agent
71
67
 
72
- Built by a team in the app (Agents → New). Only that team has it; the Source
73
- cannot update or roll it back, and nothing about it is visible to other teams.
68
+ Built for one team, in the app (Agents → New) or from the terminal with the
69
+ same `agent.json` a template uses:
70
+ `ekanos teams agents create <team> --from agents/<key>` (then
71
+ `ekanos teams agents enable <team> <key>` — it starts as a draft), and
72
+ `ekanos teams agents apply <team> agents/<key> --base-version <n>` to change
73
+ it from the file later. Only that team has it; the Source cannot update or
74
+ roll it back, and nothing about it is visible to other teams. Whoever creates
75
+ it is its creator — its tools run as them — so they must be a member of the
76
+ team who manages its agents. A field only a template has (`connections`,
77
+ `mcpServers`, `teamCustomization`, `triggers`, `links`, `teamOverrides`) is
78
+ refused; add triggers with `ekanos teams triggers add`.
74
79
 
75
80
  Good for: one team's own process; experiments a team owns.
76
81
 
82
+ ## A personal agent
83
+
84
+ One person's agent for themselves: `ekanos teams agents create <team> --from
85
+ agents/<key> --personal`, by a member of that team. It acts for its creator,
86
+ with their own connections, on every trigger, so it is theirs alone: nobody
87
+ else changes it, runs it, decides its approvals or cancels its runs — not a
88
+ team manager, not the Source admin (`PERSONAL_AGENT_CREATOR_ONLY`). Others see
89
+ that it exists, not what its runs read or did. It starts from a schedule or a
90
+ webhook (`ekanos teams triggers add <team> <key> schedule --cron "…" --prompt
91
+ "…"`); whoever holds its webhook token can make it act as its creator, so the
92
+ token goes to a file only they can read, never into a chat.
93
+
94
+ Good for: "brief me on my day", "draft replies to my inbox" — one person's
95
+ own work on their own accounts.
96
+
77
97
  ## Questions that decide it
78
98
 
79
99
  - How many teams do this work? The same way?
@@ -60,19 +60,32 @@ connect nothing for it.
60
60
  `teams show` (or `catalog`) and say what changed ("Ekanos sees the client ID
61
61
  and secret now"). If the check disagrees with what they said, look at the
62
62
  difference with them; don't move on.
63
- - **Secrets never pass through the chat.** Client secrets and signing
64
- secrets go in at the user's own terminal (`ekanos apps set`,
65
- `ekanos teams app set`, with hidden input) or in the team's page in the app.
66
- If they paste one into the chat anyway, tell them to rotate it in the
67
- provider's console and enter the new one at the terminal.
68
- - **Connect with `teams connect <team> <product>`, run by the user in their
69
- own terminal.** It does whatever the integration needs: asks a form's fields
63
+ - **Secrets never pass through the chat, or through you.** Client secrets
64
+ and signing secrets go in through a form in the user's browser that you
65
+ start with `--browser` (`ekanos apps set <product> --browser`,
66
+ `ekanos teams app set <team> <product> --browser`), at the user's own
67
+ terminal with hidden input, or in the team's page in the app. Never read
68
+ one from a file or an environment variable yourself; if the user has put
69
+ one there, pass its name with `--secret-env <NAME>` or its path with
70
+ `--secret-file <path>` and let the CLI read it. If they paste one into the
71
+ chat anyway, tell them to rotate it in the provider's console and enter
72
+ the new one through the form.
73
+ - **Connect with `teams connect <team> <product>`** — add `--browser` when
74
+ you run it, so any field it needs opens as a form in the user's browser;
75
+ without it the user runs it in their own terminal. It does whatever the
76
+ integration needs: asks a form's fields
70
77
  (secrets hidden), runs the team-app prompts first when the team's own app is
71
78
  missing, or opens a one-time sign-in link and waits until the team is
72
- connected. The provider's consent is still a person's click, by a member of
73
- the team (owner/admin for a team-wide connection): the user when they are
74
- one, else `--as <email>` prints a link to send that member. `--link-only`
75
- prints just the team's page. Tell them who should sign in: the account the
79
+ connected. Non-secret fields of any type can be passed with
80
+ `--set <field>=<value>` (a list as `a,b`; secrets and JSON values only at a prompt), so
81
+ it also runs in a script; optional ones can be left out. The provider's
82
+ consent is still a person's click, by a member of the team (owner/admin for
83
+ a team-wide connection): the user when they are one, else `--as <email>`
84
+ prints a link to send that member. A Source admin who is not on the team
85
+ joins it first with `ekanos teams members add <team> --self` (no email). A
86
+ personal product (each person connects their own, such as ROAM) connects
87
+ the account of whoever runs `teams connect`. `--link-only` prints just the
88
+ team's page. Tell them who should sign in: the account the
76
89
  integration acts as. If the product is not enabled for the Source, a
77
90
  super-admin enables it (`sources products` shows what the Source has). A dedicated seat such as "Support agent" makes its replies easy
78
91
  to recognise.
@@ -88,11 +101,12 @@ pilot), the team-side steps can be done from the CLI:
88
101
  1. `npx @ekanos/cli teams show <team> <product> --source <slug>`: the
89
102
  callback URL to register and the integration's steps.
90
103
  2. They create the app in the provider's console, step by step as above.
91
- 3. **In their own terminal:**
92
- `npx @ekanos/cli teams app set <team> <product> --source <slug>`. It asks
93
- for each field and hides the secret ones; Enter keeps a saved value. It
94
- refuses to run inside Claude; that is deliberate. To change one value
95
- later, they need not re-enter the rest:
104
+ 3. Run `npx @ekanos/cli teams app set <team> <product> --browser --source <slug>`
105
+ and tell them a form is opening in their browser: it has every field,
106
+ secrets as password inputs, and a field left empty keeps its saved value.
107
+ What they type never reaches you. (Without `--browser`, they run it in
108
+ their own terminal, which asks for each field and hides the secret ones.)
109
+ To change one value later, they need not re-enter the rest:
96
110
  `teams app set <team> <product> --field <name>` asks for just that field
97
111
  (names are in brackets in `teams show`), `--set <name>=<value>` sets a
98
112
  non-secret field (a subdomain, a client ID) without a prompt — you may run
@@ -122,10 +136,11 @@ mentions arrive. When the agent has any Linear trigger:
122
136
  redirect URIs, webhooks on with **Agent session events** and **Issues**.
123
137
  3. Its webhook URL: `teams webhook <team> linear agent-events` (once; paste
124
138
  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
139
+ 4. `npx @ekanos/cli teams connect <team> linear --connection agent --browser --source <slug>`
140
+ — opens a form in the user's browser for the client ID, secret and
141
+ webhook signing secret if any is missing (without `--browser`, the user
142
+ runs it in their own terminal and it asks there), opens the install for a
143
+ Linear workspace admin to approve, and
129
144
  waits until it is installed. (`teams connect <team> linear` with no
130
145
  `--connection` offers this itself once the personal connection is made,
131
146
  when the team has agents with Linear triggers.)
@@ -146,11 +161,12 @@ the Source's connection.
146
161
  1. **Connect, once, as the Source.** For an integration where each customer
147
162
  brings its own app (Zendesk), first create that app in the shared account,
148
163
  exactly as in the worked example below (OAuth client, Confidential), but
149
- once, for the Source. Then, **in their own terminal**:
150
- `npx @ekanos/cli apps connect <product> --source <slug>`. It asks for the
164
+ once, for the Source. Then run
165
+ `npx @ekanos/cli apps connect <product> --browser --source <slug>` (or the
166
+ user runs it without `--browser` in their own terminal). It asks for the
151
167
  app's fields it doesn't have yet (Zendesk: subdomain, client ID, client
152
- secret, webhook signing secret; secrets hidden, never as flags, and it
153
- refuses to run inside Claude), prints the redirect URL to register and the
168
+ secret, webhook signing secret) in a form in the user's browser — never
169
+ through you, never as values on the command line — prints the redirect URL to register and the
154
170
  consent link, then waits up to ten minutes until it is connected. Whoever
155
171
  clicks the link is the account the integration acts as for every team, so
156
172
  suggest a dedicated seat ("Support agent"). `apps list` shows every
@@ -201,9 +217,9 @@ from `teams show zendesk`.
201
217
  Center › Apps and integrations › Webhooks › Create webhook › Trigger or
202
218
  automation: that URL, POST, JSON, no authentication. Open it and Reveal
203
219
  secret.
204
- 3. **Credentials into Ekanos.** `ekanos teams app set <team> zendesk` in
205
- their terminal: subdomain, client ID, client secret, webhook signing
206
- secret. Any of them can be entered or changed later on its own
220
+ 3. **Credentials into Ekanos.** `ekanos teams app set <team> zendesk --browser`
221
+ (a form in their browser; or without `--browser`, in their terminal):
222
+ subdomain, client ID, client secret, webhook signing secret. Any of them can be entered or changed later on its own
207
223
  (`--field <name>`); `teams show` says which are saved.
208
224
  4. **Connect.** `npx @ekanos/cli teams connect <team> zendesk --source <slug>`
209
225
  opens the sign-in and waits; whoever approves it should be the Zendesk
@@ -244,5 +260,6 @@ from `teams show zendesk`.
244
260
  not installed for this team", or no webhook URL) and the command that
245
261
  fixes it. Installed and still silent: the Linear app's webhook must send
246
262
  **Agent session events** to the latest URL from `teams webhook`.
247
- - **A command says it needs a terminal:** it was run inside Claude. Ask them
248
- to run it in a terminal tab themselves.
263
+ - **A command says there is no terminal to ask at:** run it again with
264
+ `--browser`. If `--browser` is refused (CI, SSH, no display), ask them to
265
+ run it in a terminal tab themselves.
@@ -123,9 +123,10 @@ brands, groups and organizations match by name or id. Where the answer goes
123
123
  webhook URL), for a Slack trigger the team's Slack. `teams agents list
124
124
  <team>` shows each agent's `channels`; none may be `ready: false`.
125
125
  4. Do each integration's own setup (team app, webhook) from its guide.
126
- 5. Confirm access: the person it runs as runs `npx @ekanos/cli teams agents
127
- confirm <team> <key> --source <slug>` as themselves (or turned it on with
128
- `--confirm-access`). `teams agents list <team>` shows anyone still to.
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.
129
130
  6. Add the triggers above — unless the template already sets them.
130
131
  7. Prove it end to end: a real @mention (or the real event) → a run in
131
132
  `runs list --team <team>` → the agent's reply where it was asked. A test
@@ -185,7 +185,7 @@ mock switch) so the harness can show all four; remove it before publish.
185
185
  `border-border`, `bg-primary`, `text-destructive`. NEVER raw palette
186
186
  classes (`bg-white`, `text-gray-500`, `bg-amber-400`) or hex/oklch
187
187
  literals — they break in dark mode and off-brand tenants.
188
- - **Accent discipline**: the primary (coral-orange) on ≤10% of the widget —
188
+ - **Accent discipline**: the `primary` token (the Source's accent) on ≤10% of the widget —
189
189
  one CTA, one highlighted value, one active state. Semantic status colors
190
190
  (success/warning/destructive) are not accents.
191
191
  - **Depth via shadow, not borders** where a surface needs lift.
@@ -54,6 +54,7 @@ npx @ekanos/cli teams members invite bank-a raj@bank-a.com --role admin # defa
54
54
  npx @ekanos/cli teams members list bank-a # members and pending invitations
55
55
  npx @ekanos/cli teams members role bank-a raj@bank-a.com member
56
56
  npx @ekanos/cli teams members remove bank-a raj@bank-a.com --yes
57
+ npx @ekanos/cli teams members resend bank-a lee@bank-a.com # resend, or renew an expired invitation
57
58
  npx @ekanos/cli teams connect bank-a zendesk # connect it for the team (asks, signs in, waits)
58
59
  npx @ekanos/cli teams connect bank-a linear --as raj@bank-a.com # a sign-in link for raj
59
60
  npx @ekanos/cli sources products # what the Source has enabled (super-admin enables)
@@ -68,10 +69,13 @@ npx @ekanos/cli sources products # what the Source h
68
69
  - Roles are the team roles (owner / admin / member, or the Source's own
69
70
  customized ones). Pick a reviewer for agents by the role holding
70
71
  `agents.review` in `teams roles list`. The primary owner's role cannot be
71
- changed here; ownership moves in the app.
72
+ changed here; ownership moves in the app. The Source's custom roles
73
+ themselves are `sources roles` (`create|update|delete`; owner, admin and
74
+ member are fixed).
72
75
  - `teams connect <team> <product>` does the connect: it asks a form's fields
73
- at the user's terminal (hidden for secrets — so the user runs it, never you
74
- with values), runs the team-app prompts first when needed (Zendesk), or
76
+ at the user's terminal (hidden for secrets) or, run by you with
77
+ `--browser`, in a one-time form in the user's browser — never with values
78
+ from you — runs the team-app prompts first when needed (Zendesk), or
75
79
  opens a one-time sign-in link and waits. The person who signs in is a team
76
80
  member (owner/admin for a team-wide connection): the user when they are
77
81
  one, else `--as <email>` prints a link to send that member. `--no-wait`,
@@ -81,6 +85,17 @@ npx @ekanos/cli sources products # what the Source h
81
85
  what it has. Enabling one is a super-admin grant (`sources products enable`)
82
86
  that an `ekanos login` session cannot make — the super-admin does it in
83
87
  /admin.
88
+ - The rest of a team's life: `teams leave <team> --yes` (the user's own
89
+ membership), `teams groups list|create|update|delete|members` (groups
90
+ narrow what their members see to `--products a,b`), `teams health <team>
91
+ [<product>] [--run]` (each connected integration's health; `--run` checks
92
+ one now; `<product> --mine` the user's own personal connection),
93
+ `teams workspace list|default <team> [<workspace>]`, and
94
+ `sources people` (everyone on the Source and their teams). Each one that
95
+ takes something away needs `--yes` when you run it, which you pass only
96
+ after the user says so. Transferring a team's ownership and deleting a team
97
+ are not in the CLI: the primary owner does them in the app, confirmed by a
98
+ code emailed to them.
84
99
 
85
100
  ## Products: integrations and experiences
86
101
 
@@ -136,8 +151,8 @@ connect (`setupSteps` step `provider-app`). It is the Source's own app — for a
136
151
  white-label Source, under its product name and company — and its admin
137
152
  creates it once in the provider's console. The integration ships the steps
138
153
  (the catalog's `instructions`, with the Source's exact callback URLs filled
139
- in); `ekanos apps set <product>`, run by the admin at their own terminal,
140
- takes the client ID and secret. The `build-agent` skill walks through it
154
+ in); `ekanos apps set <product>` takes the client ID and secret — at the
155
+ admin's own terminal, or in a browser form when you run it with `--browser`. The `build-agent` skill walks through it
141
156
  (`references/app-setup.md`). Integrations whose teams each bring their own
142
157
  app (Zendesk) have no Source app; each team follows that app's steps.
143
158
 
@@ -158,8 +173,13 @@ changed through the CLI or the app, with no deploy.
158
173
  (links) and which calls wait for approval, and — per area, with
159
174
  `teamOverrides` — whether a team may change them. The template wins unless
160
175
  an area is opened to teams.
161
- - **A team's own** — built by a team in the app (Agents → New). Only that team
162
- has it, and the Source cannot update it.
176
+ - **A team's own** — built for one team, in the app (Agents → New) or with
177
+ `ekanos teams agents create <team> --from <dir>` from the same `agent.json`.
178
+ Only that team has it, and the Source cannot update it.
179
+ - **A personal agent** — one member's own (`--personal`, or "Just you" in the
180
+ app). It acts for its creator, with their own connections, on every trigger,
181
+ so only they change it, run it, decide its approvals or cancel its runs —
182
+ not a team manager and not the Source admin.
163
183
 
164
184
  Skills are folders (`SKILL.md` + references) an agent loads when needed.
165
185
  A Source admin pushes them with `ekanos skills push <dir>`: at Source level
@@ -183,29 +203,46 @@ always `ekanos teams <area> <verb> <team> …`:
183
203
 
184
204
  - `ekanos teams agents list <team>` — provided agents, on or off, the version
185
205
  each runs (pinned or following), triggers, links, the team's MCP servers,
186
- and what each still needs connected.
206
+ and what each still needs connected; then the team's own and personal
207
+ agents and whose each is.
208
+ - `ekanos teams agents create <team> --from <dir> [--personal]` /
209
+ `apply <team> <dir> [--base-version <n>]` — the team's own agent, or your
210
+ own, from an `agent.json` (+ `AGENT.md`, + `skills/<slug>/`). You become
211
+ its creator, so you must be an active member of the team. It starts as a
212
+ draft; `enable` turns it on.
187
213
  - `ekanos teams agents enable <team> <key> [--as <member-email>]
188
214
  [--confirm-access]` / `disable <team> <key>` — the app's "Turn on" /
189
215
  "Turn off". The agent runs as a team member who manages agents (the
190
- team's owner by default; with `--confirm-access`, you).
191
- - `ekanos teams agents confirm <team> <key>` — the person the agent runs as
192
- confirms, as themselves, that it may use their connections in runs no one
193
- watches; the output says which products' connections that covers. It
194
- confirms only the version it printed: a newer publish since is refused, to
195
- be reviewed and confirmed again. Nobody confirms for anyone else.
216
+ team's owner by default): that member is its creator, whose personal
217
+ connections it uses. Who it runs as is chosen once, when it is turned
218
+ on; to change it, archive it and turn it on again with `--as`.
219
+ `--confirm-access` also confirms it, as you.
220
+ - `ekanos teams agents archive <team> <key> [--yes]` / `unarchive <team>
221
+ <key>` — the app's Archive: off the team's list, nothing starts it, its
222
+ runs and setup kept; `unarchive` brings it back paused, for `enable`.
223
+ - `ekanos teams agents confirm <team> <key>` — you confirm, as yourself,
224
+ that the agent may use its connections (the person it runs as's) in runs
225
+ no one watches; the output says which products' connections that covers.
226
+ Whoever sets an agent up confirms it — the Source admin, or a team
227
+ manager in the app — never a plain team member. It confirms only the
228
+ version it printed: a newer publish since is refused, to be reviewed and
229
+ confirmed again.
196
230
  - `ekanos teams agents pin <team> <key> <version>` / `unpin <team> <key>`.
197
231
  - `ekanos teams agents policy <team> <key>` — every tool the agent can call,
198
232
  read or write, and whether it runs on its own or waits for approval;
199
233
  `… policy <team> <key> set <tool> auto|approve`, `unset <tool>`,
200
234
  `--reads auto|approve --writes auto|approve`. A provided agent's policy
201
235
  follows its template unless the template turns on team overrides for it.
202
- On any agent, a change that lets more run on its own drops the confirmation
203
- of the person it runs as, and the agent waits for them to confirm again
204
- (`--confirm-access` when that person is you).
236
+ On any agent, a change that lets more run on its own drops the
237
+ confirmation, and the agent uses only what needs none until someone who
238
+ sets it up confirms again (`--confirm-access` does it in the same step).
205
239
  - `ekanos teams agents skills <team> <key> [add|remove <skill>]` — the
206
240
  skills the agent reads; attach a team skill (pushed with
207
241
  `skills push --team`) or a Source one. A provided agent takes them only
208
242
  when its template's `teamCustomization.skills` is on; its own stay.
243
+ - `ekanos teams agents tags <team> <key> [add|remove <tag>]` — labels that
244
+ organize the team's agents and grant nothing; `add` makes a tag the team
245
+ does not have yet.
209
246
  - `ekanos teams triggers list|add|remove <team> <key> …` — manual, schedule
210
247
  (`--cron`, `--timezone`), webhook (the token goes to a file only the
211
248
  user can read, never the output) and
@@ -214,12 +251,25 @@ always `ekanos teams <area> <verb> <team> …`:
214
251
  --filter '{"labels":["feedback"]}'`), plus `slack --channel '#name' [--dms]
215
252
  --yes` and `linear [--label <name>]` once the team has installed Slack or
216
253
  Ekanos's Linear app with `ekanos teams connect <team> slack|linear-app`.
254
+ - `ekanos teams triggers enable|disable <team> <key> <trigger-id|key>` and
255
+ `edit <team> <key> <trigger-id|key> [--prompt …] [--cron … --timezone …]
256
+ [--filter …] [--channel …] [--dms] [--label …]` — turn a trigger off
257
+ without removing it, or change it in place: a webhook keeps its URL and
258
+ token (only `rotate` makes a new one).
217
259
  - `ekanos teams links list|add|remove <team> <from-key> [<to-key>] --kind
218
260
  talk|delegate [--mode await|handoff]`.
219
261
  - `ekanos teams mcp list|add|status|token|effect <team> [<server-key> …]` — a
220
262
  team's own MCP server (`--url`, `--auth none|token|oauth`); a token is typed
221
- at the admin's terminal with hidden input, never in chat or arguments; OAuth
222
- prints a link for a team member to open.
263
+ at the admin's terminal with hidden input, or in the `--browser` form, never
264
+ in chat or arguments; OAuth prints a link for a team member to open.
265
+ `ekanos teams mcp attach|detach <team> <server-key> <agent-key>` gives one
266
+ agent a team server, or takes it away (where its template allows), and
267
+ `refresh <team> <server-key>` (or `--agent <key>`) lists its tools again.
268
+ - `ekanos teams llm-key show|set|remove <team>` — the team's own Anthropic
269
+ key, which its agents and assistant then use instead of the Source's.
270
+ `show` gives only whether one is saved and its last four characters; `set`
271
+ takes it like any secret (`--browser`, or `--secret-env <NAME>` /
272
+ `--secret-file <path>` the user prepared); `remove` needs `--yes`.
223
273
 
224
274
  Triggers, links and the policy of a provided agent follow its template by
225
275
  default; when the template has not turned on team overrides for that area,
@@ -261,19 +311,23 @@ is refused (`USER_NOT_IN_SOURCE`): `ekanos teams list` shows the teams.
261
311
  | Agents provided for every team | A Source admin, with `ekanos agents` (`agents archive <key>` retires one once no team has it on) |
262
312
  | 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>` |
263
313
  | 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` |
264
- | 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) |
314
+ | Deciding what an agent run waits on (approve, reject, edit & send a reply) | A team's agent manager in the app, or with `ekanos approvals`: a Source admin (for a team's own agent, only one who manages that team's agents), or any seat holder with that authority themselves — a member who manages (or, for reply drafts, reviews) the team's agents, a named reviewer, a personal agent's creator |
315
+ | A team's workflows: saving one, turning it on, running it, deciding its approval gates | A team member who configures integrations, in the app's editor; or a Source admin with `ekanos workflows apply\|enable\|run\|approvals --team <slug>` (Workflows must be on for the Source; a member's personal workflow is theirs alone). Custom Code that writes or reaches a host is approved by whoever turns the workflow on: `ekanos workflows enable <workflow> --team <slug> --confirm-access` |
265
316
  | 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 |
266
317
  | 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 |
267
318
  | Who decides agent drafts that wait for a person | A Source admin, with `ekanos reviewers` |
268
- | An integration's app for the whole Source (client ID and secret) | A Source admin, with `ekanos apps set` at their own terminal |
319
+ | An integration's app for the whole Source (client ID and secret) | A Source admin, with `ekanos apps set` (at their own terminal, or its `--browser` form) |
269
320
  | One connection for the whole Source, used by provided agents in every team | A Source admin, with `ekanos apps connect` (status: `ekanos apps show`), or **Shared integrations › Connections** in the Source admin area |
270
321
  | Which team gets which events on that connection (Zendesk organization → team) | A Source admin, with `ekanos routes` (`webhook`, `options`, `set`, `list`, `remove`, `unrouted`, `replay`), or **Shared integrations › Routing** in the Source admin area |
271
322
  | 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` |
272
323
  | 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 |
273
324
  | 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) |
325
+ | A team's groups and default workspace | A Source admin, with `ekanos teams groups` / `ekanos teams workspace default`, or the team's owner in the app |
326
+ | Transferring a team's ownership, deleting a team | The team's primary owner in the app (a code emailed to them confirms it), or a super-admin under /admin |
327
+ | The Source's custom roles and their permissions | A Source admin, with `ekanos sources roles`; owner, admin and member are fixed |
274
328
  | 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) |
275
329
  | 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` |
276
330
  | 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 |
277
331
  | 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>` |
278
- | 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 |
279
- | Confirming an agent may use a person's connections | Only the person it runs as, signed in as themselves: `ekanos teams agents confirm <team> <key>` (or `enable --confirm-access`, `agents publish --confirm-access`), or **Confirm access** in the app. On a team held on an earlier version (a newer one reaches further than they confirmed) it moves the team to the version waiting |
332
+ | 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. A personal connection: only its owner, `ekanos teams disconnect <team> <product> --mine --yes` |
333
+ | 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 |