agent-trellis 0.9.0 → 0.10.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 (180) hide show
  1. package/dist/adapters/mcpPlan.d.ts +5 -0
  2. package/dist/adapters/mcpPlan.js +7 -1
  3. package/dist/cli.js +11 -5
  4. package/dist/commands/mcp.d.ts +41 -2
  5. package/dist/commands/mcp.js +111 -14
  6. package/dist/commands/mcpAuth.js +28 -0
  7. package/dist/core/canonical.d.ts +15 -12
  8. package/dist/core/canonical.js +86 -18
  9. package/dist/core/types.d.ts +28 -2
  10. package/dist/core/types.js +19 -0
  11. package/dist/lib/oauth/flow.d.ts +13 -0
  12. package/dist/lib/oauth/flow.js +48 -3
  13. package/dist/lib/secretEnv.d.ts +5 -0
  14. package/dist/lib/secretEnv.js +8 -0
  15. package/dist/pi-bridge/bundle.js +738 -680
  16. package/dist/pi-bridge/index.js +2 -2
  17. package/docs/architecture.md +19 -0
  18. package/docs/mcp-oauth-matrix.md +140 -0
  19. package/docs/research.md +11 -0
  20. package/package.json +4 -2
  21. package/schema/servers.example.yaml +18 -0
  22. package/docs/video/README.md +0 -76
  23. package/docs/video/build/audio/01-opening.aiff +0 -0
  24. package/docs/video/build/audio/01-opening.mp3 +0 -0
  25. package/docs/video/build/audio/02-pain.aiff +0 -0
  26. package/docs/video/build/audio/02-pain.mp3 +0 -0
  27. package/docs/video/build/audio/03-solution.aiff +0 -0
  28. package/docs/video/build/audio/03-solution.mp3 +0 -0
  29. package/docs/video/build/audio/04-install.aiff +0 -0
  30. package/docs/video/build/audio/04-install.mp3 +0 -0
  31. package/docs/video/build/audio/04-setup.mp3 +0 -0
  32. package/docs/video/build/audio/05-dryrun.mp3 +0 -0
  33. package/docs/video/build/audio/05-init.aiff +0 -0
  34. package/docs/video/build/audio/05-init.mp3 +0 -0
  35. package/docs/video/build/audio/05-interactive.mp3 +0 -0
  36. package/docs/video/build/audio/06-dryrun.aiff +0 -0
  37. package/docs/video/build/audio/06-dryrun.mp3 +0 -0
  38. package/docs/video/build/audio/06-onboard.mp3 +0 -0
  39. package/docs/video/build/audio/06-run.mp3 +0 -0
  40. package/docs/video/build/audio/07-onboard.aiff +0 -0
  41. package/docs/video/build/audio/07-onboard.mp3 +0 -0
  42. package/docs/video/build/audio/07-verify.mp3 +0 -0
  43. package/docs/video/build/audio/08-closing.mp3 +0 -0
  44. package/docs/video/build/audio/08-doctor.aiff +0 -0
  45. package/docs/video/build/audio/08-doctor.mp3 +0 -0
  46. package/docs/video/build/audio/09-rollback.aiff +0 -0
  47. package/docs/video/build/audio/09-rollback.mp3 +0 -0
  48. package/docs/video/build/audio/10-principles.aiff +0 -0
  49. package/docs/video/build/audio/10-principles.mp3 +0 -0
  50. package/docs/video/build/audio/11-closing.aiff +0 -0
  51. package/docs/video/build/audio/11-closing.mp3 +0 -0
  52. package/docs/video/build/frames/01-opening-0.png +0 -0
  53. package/docs/video/build/frames/02-pain-1.png +0 -0
  54. package/docs/video/build/frames/02-pain-2.png +0 -0
  55. package/docs/video/build/frames/03-solution-3.png +0 -0
  56. package/docs/video/build/frames/04-install-4.png +0 -0
  57. package/docs/video/build/frames/04-setup-4.png +0 -0
  58. package/docs/video/build/frames/04-setup-5.png +0 -0
  59. package/docs/video/build/frames/05-dryrun-6.png +0 -0
  60. package/docs/video/build/frames/05-init-5.png +0 -0
  61. package/docs/video/build/frames/05-interactive-5.png +0 -0
  62. package/docs/video/build/frames/05-interactive-6.png +0 -0
  63. package/docs/video/build/frames/06-dryrun-6.png +0 -0
  64. package/docs/video/build/frames/06-dryrun-7.png +0 -0
  65. package/docs/video/build/frames/06-onboard-7.png +0 -0
  66. package/docs/video/build/frames/06-onboard-8.png +0 -0
  67. package/docs/video/build/frames/06-run-7.png +0 -0
  68. package/docs/video/build/frames/06-run-8.png +0 -0
  69. package/docs/video/build/frames/07-onboard-10.png +0 -0
  70. package/docs/video/build/frames/07-onboard-7.png +0 -0
  71. package/docs/video/build/frames/07-onboard-8.png +0 -0
  72. package/docs/video/build/frames/07-onboard-9.png +0 -0
  73. package/docs/video/build/frames/07-verify-10.png +0 -0
  74. package/docs/video/build/frames/07-verify-8.png +0 -0
  75. package/docs/video/build/frames/07-verify-9.png +0 -0
  76. package/docs/video/build/frames/08-closing-10.png +0 -0
  77. package/docs/video/build/frames/08-closing-11.png +0 -0
  78. package/docs/video/build/frames/08-doctor-11.png +0 -0
  79. package/docs/video/build/frames/08-doctor-9.png +0 -0
  80. package/docs/video/build/frames/09-rollback-10.png +0 -0
  81. package/docs/video/build/frames/09-rollback-12.png +0 -0
  82. package/docs/video/build/frames/10-principles-11.png +0 -0
  83. package/docs/video/build/frames/10-principles-13.png +0 -0
  84. package/docs/video/build/frames/11-closing-12.png +0 -0
  85. package/docs/video/build/frames/11-closing-14.png +0 -0
  86. package/docs/video/build/segments/01-opening.mp4 +0 -0
  87. package/docs/video/build/segments/01-opening.txt +0 -3
  88. package/docs/video/build/segments/02-pain.mp4 +0 -0
  89. package/docs/video/build/segments/02-pain.txt +0 -5
  90. package/docs/video/build/segments/03-solution.mp4 +0 -0
  91. package/docs/video/build/segments/03-solution.txt +0 -3
  92. package/docs/video/build/segments/04-install.mp4 +0 -0
  93. package/docs/video/build/segments/04-install.txt +0 -3
  94. package/docs/video/build/segments/04-setup.mp4 +0 -0
  95. package/docs/video/build/segments/04-setup.txt +0 -3
  96. package/docs/video/build/segments/05-dryrun.mp4 +0 -0
  97. package/docs/video/build/segments/05-dryrun.txt +0 -3
  98. package/docs/video/build/segments/05-init.mp4 +0 -0
  99. package/docs/video/build/segments/05-init.txt +0 -3
  100. package/docs/video/build/segments/05-interactive.mp4 +0 -0
  101. package/docs/video/build/segments/05-interactive.txt +0 -5
  102. package/docs/video/build/segments/06-dryrun.mp4 +0 -0
  103. package/docs/video/build/segments/06-dryrun.txt +0 -3
  104. package/docs/video/build/segments/06-onboard.mp4 +0 -0
  105. package/docs/video/build/segments/06-onboard.txt +0 -5
  106. package/docs/video/build/segments/06-run.mp4 +0 -0
  107. package/docs/video/build/segments/06-run.txt +0 -3
  108. package/docs/video/build/segments/07-onboard.mp4 +0 -0
  109. package/docs/video/build/segments/07-onboard.txt +0 -5
  110. package/docs/video/build/segments/07-verify.mp4 +0 -0
  111. package/docs/video/build/segments/07-verify.txt +0 -5
  112. package/docs/video/build/segments/08-closing.mp4 +0 -0
  113. package/docs/video/build/segments/08-closing.txt +0 -3
  114. package/docs/video/build/segments/08-doctor.mp4 +0 -0
  115. package/docs/video/build/segments/08-doctor.txt +0 -3
  116. package/docs/video/build/segments/09-rollback.mp4 +0 -0
  117. package/docs/video/build/segments/09-rollback.txt +0 -3
  118. package/docs/video/build/segments/10-principles.mp4 +0 -0
  119. package/docs/video/build/segments/10-principles.txt +0 -3
  120. package/docs/video/build/segments/11-closing.mp4 +0 -0
  121. package/docs/video/build/segments/11-closing.txt +0 -3
  122. package/docs/video/build/segments/final.txt +0 -8
  123. package/docs/video/build-ai/audio/01-hook.mp3 +0 -0
  124. package/docs/video/build-ai/audio/02-pain.mp3 +0 -0
  125. package/docs/video/build-ai/audio/03-solution.mp3 +0 -0
  126. package/docs/video/build-ai/audio/04-how.mp3 +0 -0
  127. package/docs/video/build-ai/audio/05-safe.mp3 +0 -0
  128. package/docs/video/build-ai/audio/06-closing.mp3 +0 -0
  129. package/docs/video/build-ai/clips/01-hook.mp4 +0 -0
  130. package/docs/video/build-ai/clips/02-pain.mp4 +0 -0
  131. package/docs/video/build-ai/clips/03-solution.mp4 +0 -0
  132. package/docs/video/build-ai/clips/04-how.mp4 +0 -0
  133. package/docs/video/build-ai/clips/05-safe.mp4 +0 -0
  134. package/docs/video/build-ai/clips/06-closing.mp4 +0 -0
  135. package/docs/video/build-ai/first-frame-02-pain.png +0 -0
  136. package/docs/video/build-ai/first-frame-03-solution.png +0 -0
  137. package/docs/video/build-ai/first-frame-04-how.png +0 -0
  138. package/docs/video/build-ai/first-frame-05-safe.png +0 -0
  139. package/docs/video/build-ai/segments/01-hook.caption.txt +0 -2
  140. package/docs/video/build-ai/segments/01-hook.mp4 +0 -0
  141. package/docs/video/build-ai/segments/02-pain.mp4 +0 -0
  142. package/docs/video/build-ai/segments/03-solution.mp4 +0 -0
  143. package/docs/video/build-ai/segments/04-how.mp4 +0 -0
  144. package/docs/video/build-ai/segments/05-safe.mp4 +0 -0
  145. package/docs/video/build-ai/segments/06-closing.mp4 +0 -0
  146. package/docs/video/build-ai/segments/cap-01-hook.png +0 -0
  147. package/docs/video/build-ai/segments/cap-02-pain.png +0 -0
  148. package/docs/video/build-ai/segments/cap-03-solution.png +0 -0
  149. package/docs/video/build-ai/segments/cap-04-how.png +0 -0
  150. package/docs/video/build-ai/segments/cap-05-safe.png +0 -0
  151. package/docs/video/build-ai/segments/cap-06-closing.png +0 -0
  152. package/docs/video/build-ai/segments/final.txt +0 -6
  153. package/docs/video/build-posters/audio/01-hook.mp3 +0 -0
  154. package/docs/video/build-posters/audio/02-pain.mp3 +0 -0
  155. package/docs/video/build-posters/audio/03-solution.mp3 +0 -0
  156. package/docs/video/build-posters/audio/04-how.mp3 +0 -0
  157. package/docs/video/build-posters/audio/05-safe.mp3 +0 -0
  158. package/docs/video/build-posters/audio/06-closing.mp3 +0 -0
  159. package/docs/video/build-posters/cap-01-hook.png +0 -0
  160. package/docs/video/build-posters/cap-02-pain.png +0 -0
  161. package/docs/video/build-posters/cap-03-solution.png +0 -0
  162. package/docs/video/build-posters/cap-04-how.png +0 -0
  163. package/docs/video/build-posters/cap-05-safe.png +0 -0
  164. package/docs/video/build-posters/cap-06-closing.png +0 -0
  165. package/docs/video/build-posters/card-01-hook.png +0 -0
  166. package/docs/video/build-posters/card-06-closing.png +0 -0
  167. package/docs/video/build-posters/segments/01-hook.mp4 +0 -0
  168. package/docs/video/build-posters/segments/02-pain.mp4 +0 -0
  169. package/docs/video/build-posters/segments/03-solution.mp4 +0 -0
  170. package/docs/video/build-posters/segments/04-how.mp4 +0 -0
  171. package/docs/video/build-posters/segments/05-safe.mp4 +0 -0
  172. package/docs/video/build-posters/segments/06-closing.mp4 +0 -0
  173. package/docs/video/build-posters/segments/final.txt +0 -6
  174. package/docs/video/generate-video-ai.mjs +0 -334
  175. package/docs/video/generate-video-posters.mjs +0 -204
  176. package/docs/video/generate-video.mjs +0 -426
  177. package/docs/video/outline.zh-CN.md +0 -102
  178. package/docs/video/trellis-demo-video-ai.mp4 +0 -0
  179. package/docs/video/trellis-demo-video.mp4 +0 -0
  180. package/docs/video/voiceover.zh-CN.md +0 -49
@@ -17,7 +17,7 @@ import { resolveMcpPlan } from "../adapters/mcpPlan.js";
17
17
  import { connectServer, withTimeout, DEFAULT_CONNECT_TIMEOUT_MS } from "../lib/mcpConnect.js";
18
18
  import { McpToolRegistry } from "../lib/mcpToolRegistry.js";
19
19
  import { withOAuthHeader } from "../lib/gatewayBackend.js";
20
- import { ALL_AGENTS } from "../core/types.js";
20
+ import { ALL_AGENTS, isOAuthAuth } from "../core/types.js";
21
21
  import { toParametersSchema, toPiContent } from "./schemaTranslate.js";
22
22
  /** Re-exported so `trellis-mcp-connect-timeout`'s existing test keeps
23
23
  * importing it from the module it was written against — proving the
@@ -75,7 +75,7 @@ export default async function trellisMcpBridge(pi, homeDir = homedir(), connectT
75
75
  const discovered = await Promise.all(desired.map(async ({ name, def }) => {
76
76
  let client;
77
77
  try {
78
- const effectiveDef = def.auth === "oauth" && def.url
78
+ const effectiveDef = isOAuthAuth(def.auth) && def.url
79
79
  ? await withOAuthHeader(name, def, homeDir)
80
80
  : def;
81
81
  client = await connectServer(effectiveDef, canonical.secretsPolicy, connectTimeoutMs, CLIENT_INFO);
@@ -266,6 +266,25 @@ flow for Claude Code/Codex/Kiro; Pi's bridge is the client for its direct OAuth
266
266
  connection and may use Trellis's own OAuth store. Trellis never infers this
267
267
  classification from a URL or a transient 401.
268
268
 
269
+ The classification optionally carries pre-registered client metadata, for
270
+ providers that refuse Dynamic Client Registration and require an allowlisted
271
+ client instead:
272
+
273
+ ```yaml
274
+ auth:
275
+ kind: oauth
276
+ client_id: "<provider-published-id>" # public by design, literal
277
+ client_secret_env: PROVIDER_CLIENT_SECRET # a NAME, resolved via secrets.policy.yaml
278
+ ```
279
+
280
+ `client_id` wins over DCR when present; DCR stays the fallback when it is
281
+ absent. There is deliberately no literal secret field — a secret enters only
282
+ as a variable name, the same `env`-style discipline everything else follows.
283
+ See docs/mcp-oauth-matrix.md for which providers are open to registration and
284
+ which are not, and for the distribution rule: examples, docs, and seed data
285
+ ship placeholders only, and only provider-**published** identifiers may ever
286
+ be pre-filled.
287
+
269
288
  Trellis still implements the client half itself — discovery (RFC 8414 /
270
289
  RFC 9728), dynamic client registration (RFC 7591), authorization code with
271
290
  PKCE S256 (RFC 7636), and the refresh grant — in `src/lib/oauth/`, but that
@@ -0,0 +1,140 @@
1
+ # Remote MCP providers — how OAuth identity works, and where Trellis can help
2
+
3
+ `trellis mcp auth <name>` can only complete an authorization-code grant if it
4
+ is allowed to *have* a client identity. Whether it may is entirely the
5
+ provider's decision, and that decision splits remote MCP providers into two
6
+ families. This page records which family each known provider is in, what
7
+ evidence that rests on, and what Trellis does in each case.
8
+
9
+ Read alongside docs/architecture.md §"Static header auth vs. real OAuth",
10
+ which covers the *other* shape — a long-lived bearer token or API key in a
11
+ `headers` field — and why Trellis builds for both.
12
+
13
+ ## The two families
14
+
15
+ **DCR-open.** The provider implements RFC 7591 Dynamic Client Registration.
16
+ Trellis POSTs its own metadata, receives a `client_id`, and holds its own
17
+ identity per installation. Nothing a user has to supply; nothing Trellis has
18
+ to distribute. This already works: it is what `trellis mcp auth` has done
19
+ since `trellis-mcp-gateway-hosting`.
20
+
21
+ **Allowlist.** The provider refuses registration — either by not advertising a
22
+ `registration_endpoint`, or by answering it with `unauthorized_client` — and
23
+ requires clients to be pre-registered with the provider. There is no
24
+ self-service path: the user obtains a `client_id` out of band and supplies it.
25
+ That is what the `auth.client_id` / `auth.client_secret_env` fields exist for
26
+ (trellis-mcp-oauth-static-client design.md D1–D3).
27
+
28
+ The 2026-07-28 MCP authorization spec moved in the allowlist direction,
29
+ downgrading Dynamic Client Registration from a MUST to a MAY in favour of
30
+ pre-registration. Expect the second family to grow; the mechanism, not the
31
+ per-provider list, is what Trellis commits to.
32
+
33
+ ## Matrix
34
+
35
+ | Provider | Family | What identifies the client | Evidence | Confidence |
36
+ |---|---|---|---|---|
37
+ | Sentry | DCR-open | `client_id` from DCR | Local successful grant against the real server; secondary sources describing its DCR endpoint | Medium — see the note below |
38
+ | Supabase | DCR-open | `client_id` from DCR | Same | Medium |
39
+ | Morphix | DCR-open | `client_id` from DCR | Same | Medium |
40
+ | GitHub | DCR-open | `client_id` from DCR | Same | Medium |
41
+ | Notion | DCR-open | `client_id` from DCR | Same | Medium |
42
+ | Linear | DCR-open | `client_id` from DCR | Same | Medium |
43
+ | Cloudflare | DCR-open | `client_id` from DCR | Same | Medium |
44
+ | Figma | Allowlist | Provider-published `client_id`, supplied by the user | Registration refused with `unauthorized_client` — observed directly, and the reason this change exists | High |
45
+
46
+ **On confidence.** "High" means the behavior was observed directly against the
47
+ live provider and the failure (or success) is reproducible from this
48
+ repository's own test fixtures. "Medium" means the status rests on a working
49
+ local grant plus secondary sources rather than a first-party policy statement —
50
+ the *observed* behavior is solid, but a provider is free to change its
51
+ registration policy at any time, and none of these have published a
52
+ contractual commitment either way. Sentry is explicitly in this bucket
53
+ (trellis-mcp-oauth-static-client design.md D6): the local grant proves
54
+ registration works today, not that it will next quarter.
55
+
56
+ Treat the whole table as a snapshot of observed behavior, not as provider
57
+ policy. `trellis mcp auth` reports the actual failure when a row goes stale —
58
+ see "When a provider refuses" below.
59
+
60
+ ## What actually identifies a client
61
+
62
+ There is no magic header and no provider-specific handshake. Any OAuth 2.0
63
+ authorization server that speaks the MCP authorization profile identifies a
64
+ client by a combination of:
65
+
66
+ - **`client_id`** — the identity itself. Public by design for a public client:
67
+ it travels in the browser URL on every authorization (`?client_id=...`), so
68
+ it is visible to the user, their browser history, and any proxy in between.
69
+ Its security rests on the *other* factors here, never on its secrecy.
70
+ - **Exact `redirect_uri` match** — registered with the client and required to
71
+ match byte-for-byte. This is why Trellis's loopback callback is what it is:
72
+ `http://127.0.0.1:<port>/callback`, with the port chosen by the OS at bind
73
+ time. A pre-registered client whose provider pins one specific port is the
74
+ one case where a fixed `callbackPort` is needed.
75
+ - **PKCE (RFC 7636, `S256`)** — the proof that whoever redeems the code is
76
+ whoever started the flow. The verifier never travels through the browser;
77
+ only its SHA-256 challenge does. Trellis's fake Authorization Server in the
78
+ test suite *enforces* this rather than rubber-stamping it, so the tests
79
+ cannot pass for a client that gets PKCE wrong.
80
+ - **`resource` parameter** — binds the grant to the MCP server it was issued
81
+ for, so a token minted for one server is not replayable against another.
82
+
83
+ Nothing in that list is a secret for a public client, which is exactly why
84
+ `client_id` is a plain literal in canonical YAML and `client_secret_env` — the
85
+ one field that *is* a credential — is a variable NAME resolved through
86
+ `secrets.policy.yaml` and never a value (design.md D2).
87
+
88
+ ## When a provider refuses
89
+
90
+ `trellis mcp auth <name>` tries pre-registered metadata first, then DCR. When
91
+ both are unavailable it fails with the remediation rather than a bare status
92
+ code:
93
+
94
+ ```
95
+ "figma": dynamic client registration was refused (unauthorized_client) —
96
+ register a client with the provider and set auth.client_id (plus
97
+ auth.client_secret_env if the provider requires a secret) under this server in
98
+ ~/.trellis/mcp/servers.yaml
99
+ ```
100
+
101
+ The fix is then two commands:
102
+
103
+ ```sh
104
+ trellis mcp set figma --auth oauth --client-id <provider-published-id>
105
+ trellis mcp auth figma
106
+ ```
107
+
108
+ The id comes from the provider. Trellis does not ship one, look one up for
109
+ you, or read another client's stored credentials to borrow an identity —
110
+ that last option is rejected structurally, not just by policy (design.md D5:
111
+ borrowing a refresh token makes both clients fight over rotation, and reading
112
+ another tool's credential store would mean decrypting files Trellis does not
113
+ own).
114
+
115
+ ## Distribution boundary
116
+
117
+ Trellis is open source. What it distributes is a mechanism — the schema field,
118
+ the flow, the tests. It does not distribute an identity.
119
+
120
+ A user who obtains a `client_id` and pastes it into their own
121
+ `~/.trellis/mcp/servers.yaml` is making their own decision under the provider's
122
+ terms, in the same position as anyone running `mcp-remote
123
+ --static-oauth-client-info`. Trellis shipping that same id in
124
+ `schema/servers.example.yaml`, in this page, or in seed data would instead make
125
+ the project itself the distributor of a whitelist-bypass tool. So:
126
+
127
+ - Examples and docs use placeholders only — see the commented block in
128
+ `schema/servers.example.yaml`.
129
+ - Only provider-**published** identifiers may ever be pre-filled. None exist
130
+ today, so nothing is pre-filled.
131
+ - A literal that matches `reject_patterns` is refused at load and at write, so
132
+ a pasted credential cannot quietly become part of the canonical source.
133
+
134
+ ## See also
135
+
136
+ - docs/architecture.md §"Static header auth vs. real OAuth" — the other shape.
137
+ - `schema/servers.example.yaml` — the object form, with placeholders.
138
+ - trellis-mcp-oauth-static-client design.md — D1 (field shape), D2 (literal vs.
139
+ name), D3 (metadata wins over DCR), D4 (distribution boundary), D5 (no token
140
+ borrowing), D6 (this matrix's confidence notes).
package/docs/research.md CHANGED
@@ -216,6 +216,17 @@ every agent's adapter renders it through the exact same reference mechanism
216
216
  `env` already uses, and the pi bridge resolves it through the exact same
217
217
  `resolveSecretEnv` call.
218
218
 
219
+ The same reference-not-value rule is what shapes OAuth client metadata
220
+ (trellis-mcp-oauth-static-client). A public client's `client_id` is published
221
+ by design — it rides in the browser URL on every authorization — so it is a
222
+ plain literal, comparable to how `mcp-remote --static-oauth-client-info` and
223
+ `claude mcp add --client-id` already treat it. A `client_secret` is the
224
+ opposite kind of thing, so it enters only as `client_secret_env`, a variable
225
+ NAME resolved through this same machinery; there is deliberately no literal
226
+ secret field. Which providers accept an unregistered client at all is a
227
+ per-provider question — see docs/mcp-oauth-matrix.md, including its note that
228
+ that matrix records observed behavior, not provider policy.
229
+
219
230
  ## pi coding agent — the one place we write real code, not config generation
220
231
 
221
232
  Reverse-engineered directly from the installed binary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-trellis",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "A unified Code Agent Runtime for Skills, MCP, Memory, and shared instructions across Claude Code, Codex, Kiro, pi, Kimi Code, and ZCode.",
5
5
  "license": "MIT",
6
6
  "author": "Paul Leo",
@@ -23,7 +23,9 @@
23
23
  "files": [
24
24
  "dist",
25
25
  "schema",
26
- "docs"
26
+ "docs/*.md",
27
+ "docs/assets/brand-v3",
28
+ "docs/assets/poster-series-v3"
27
29
  ],
28
30
  "scripts": {
29
31
  "build": "tsc -p tsconfig.json && node scripts/build-pi-bridge.mjs",
@@ -118,6 +118,24 @@ servers:
118
118
  # Explicit OAuth classification keeps this server direct when an Agent
119
119
  # uses gateway mode. Trellis never infers OAuth from a URL or 401.
120
120
  # auth: oauth
121
+ #
122
+ # Object form (trellis-mcp-oauth-static-client): for a provider that
123
+ # rejects Dynamic Client Registration (Figma does — `unauthorized_client`)
124
+ # and requires a pre-registered client. `kind: oauth` is the only
125
+ # discriminator and the only required key; a bare `auth: oauth` above and
126
+ # a metadata-less `{ kind: oauth }` are exactly equivalent.
127
+ # - `client_id` is a PUBLIC literal by design — fine to commit. Use the
128
+ # identifier the PROVIDER published for this client; a self-registered
129
+ # one from your own account only if you accept managing it.
130
+ # - `client_secret_env` is a variable NAME, resolved through
131
+ # secrets.policy.yaml at `trellis mcp auth` time — never a secret
132
+ # value, and never a literal secret field (there is none).
133
+ # Placeholders below on purpose: only provider-published identifiers may
134
+ # ever be pre-filled in a distribution artifact.
135
+ # auth:
136
+ # kind: oauth
137
+ # client_id: "<provider-published-client-id>"
138
+ # client_secret_env: FIGMA_CLIENT_SECRET
121
139
 
122
140
  # Example of a private/agent-specific server: only Claude Code has a use
123
141
  # for this one, so the other three agents never see it defined at all.
@@ -1,76 +0,0 @@
1
- # Trellis 分享视频 · 素材与录制清单
2
-
3
- > 本目录(`docs/video/`)在 `.gitignore` 中,所有内容只存在于本地,
4
- > 不会进入开源仓库。
5
-
6
- ## 自动生成视频
7
-
8
- ```bash
9
- node docs/video/generate-video.mjs # 输出 docs/video/trellis-demo-video.mp4
10
- ```
11
-
12
- 一条命令完成:重置沙盒 → 真实跑一遍 CLI 并捕获输出 → 渲染终端帧与卡片
13
- (qlmanage)→ 系统 TTS 生成中文口播(Ting-Ting Enhanced)→ ffmpeg 合成
14
- 1920×1080 mp4。改口播文案直接编辑脚本里的 `blocks[].narration`;终端帧
15
- 内容来自真实命令输出,无需手改。依赖:ffmpeg(`brew install ffmpeg`)、
16
- macOS 自带的 qlmanage/sips/say/afinfo。
17
-
18
- ## 演示沙盒(不碰真实配置)
19
-
20
- ```bash
21
- bash scripts/video-demo-setup.sh # 生成/重置演示环境到 /tmp/trellis-demo-home
22
- export HOME=/tmp/trellis-demo-home # 之后所有 trellis 命令都在沙盒里运行
23
- ```
24
-
25
- 沙盒内容:Claude Code(1 份指令 + 2 个 Skill + 2 个 MCP 服务器)、
26
- Codex(config.toml + 1 个 MCP 服务器)。每次重录前重跑 setup 脚本即可
27
- 回到初始状态。已验证全流程可跑通:`init → onboard --dry-run → onboard →
28
- doctor → rollback`。
29
-
30
- 录制用命令(已跳过交互选择,流程不打断):
31
-
32
- ```bash
33
- trellis init
34
- trellis onboard --dry-run --agent claude-code --manage codex
35
- trellis onboard --agent claude-code --manage codex
36
- trellis doctor
37
- trellis rollback
38
- ```
39
-
40
- ## 终端与录屏设置
41
-
42
- | 项 | 建议 |
43
- |---|---|
44
- | 终端主题 | 浅色(手机端观看对比度更好) |
45
- | 字号 | 20–24pt,观众多用手机看 |
46
- | 提示符 | `export PS1='$ '`,干净无干扰 |
47
- | 窗口 | 1280×720 或 1440×810 逻辑分辨率 |
48
- | 录屏 | Kap / QuickTime;每条 take 前 `clear` |
49
- | 导出 | 横屏 1920×1080(B 站/YouTube);竖屏 1080×1920(视频号/小红书)则后期裁切,注意命令别超出安全区 |
50
-
51
- ## 分镜与素材对照
52
-
53
- | 场景 | 画面 | 素材 |
54
- |---|---|---|
55
- | 1 开场 | 终端/编辑器随意状态 | 现场录 |
56
- | 2 痛点 | `ls ~/.claude` `ls ~/.codex`(真实目录,只读) | 现场录 |
57
- | 3 方案 | 海报全屏 | [`../assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.png`](../assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.png) |
58
- | 4 演示 | 终端实录 | 沙盒命令(见上) |
59
- | 5 设计点 | README Design principles 滚动 | github.com/paul-leo/Trellis |
60
- | 6 收尾 | GitHub 仓库首页 + Star 按钮停留 2 秒 | 同上 |
61
-
62
- ## 其他可用素材
63
-
64
- - 封面图/片尾卡:[`../assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.png`](../assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.png)
65
- - Logo 叠层(角标):[`../assets/brand-v3/trellis-mark-v3-a.svg`](../assets/brand-v3/trellis-mark-v3-a.svg)
66
- - 口播逐字稿:[voiceover.zh-CN.md](voiceover.zh-CN.md)
67
- - 场景大纲:[outline.zh-CN.md](outline.zh-CN.md)
68
- - 60 秒极简版:见 [outline.zh-CN.md](outline.zh-CN.md) 末尾
69
-
70
- ## 录制前 Checklist
71
-
72
- - [ ] 重跑 `bash scripts/video-demo-setup.sh` 重置沙盒
73
- - [ ] `export HOME=/tmp/trellis-demo-home && export PS1='$ ' && clear`
74
- - [ ] 终端字号调大,关闭通知(勿扰模式)
75
- - [ ] 预演一遍场景 4,确认输出与口播一致
76
- - [ ] 麦克风电平测试 5 秒
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/01-opening-0.png'
2
- duration 11.053
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/01-opening-0.png'
@@ -1,5 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/02-pain-1.png'
2
- duration 2.172
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/02-pain-2.png'
4
- duration 5.068
5
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/02-pain-2.png'
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/03-solution-3.png'
2
- duration 6.482
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/03-solution-3.png'
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/04-install-4.png'
2
- duration 2.407
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/04-install-4.png'
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/04-setup-4.png'
2
- duration 4.131
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/04-setup-4.png'
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/05-dryrun-6.png'
2
- duration 7.031
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/05-dryrun-6.png'
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/05-init-5.png'
2
- duration 6.587
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/05-init-5.png'
@@ -1,5 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/05-interactive-5.png'
2
- duration 1.952
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/05-interactive-6.png'
4
- duration 4.556
5
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/05-interactive-6.png'
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/06-dryrun-6.png'
2
- duration 14.763
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/06-dryrun-6.png'
@@ -1,5 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/06-onboard-7.png'
2
- duration 1.537
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/06-onboard-8.png'
4
- duration 3.587
5
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/06-onboard-8.png'
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/06-run-7.png'
2
- duration 6.874
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/06-run-7.png'
@@ -1,5 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/07-onboard-7.png'
2
- duration 2.195
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/07-onboard-8.png'
4
- duration 5.123
5
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/07-onboard-8.png'
@@ -1,5 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/07-verify-8.png'
2
- duration 1.184
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/07-verify-9.png'
4
- duration 2.764
5
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/07-verify-9.png'
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/08-closing-10.png'
2
- duration 9.591
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/08-closing-10.png'
@@ -1,3 +0,0 @@
1
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/08-doctor-9.png'
2
- duration 5.620
3
- file '/Users/pengzai/www/Trellis/docs/video/build/frames/08-doctor-9.png'