@agent-native/core 0.42.0 → 0.44.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 (139) hide show
  1. package/README.md +17 -56
  2. package/dist/chat-threads/store.d.ts.map +1 -1
  3. package/dist/chat-threads/store.js +71 -10
  4. package/dist/chat-threads/store.js.map +1 -1
  5. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  6. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  7. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  8. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  9. package/dist/cli/recap.d.ts.map +1 -1
  10. package/dist/cli/recap.js +13 -13
  11. package/dist/cli/recap.js.map +1 -1
  12. package/dist/cli/skills.d.ts +2 -6
  13. package/dist/cli/skills.d.ts.map +1 -1
  14. package/dist/cli/skills.js +21 -79
  15. package/dist/cli/skills.js.map +1 -1
  16. package/dist/client/AssistantChat.d.ts.map +1 -1
  17. package/dist/client/AssistantChat.js +76 -18
  18. package/dist/client/AssistantChat.js.map +1 -1
  19. package/dist/client/blocks/index.d.ts +9 -0
  20. package/dist/client/blocks/index.d.ts.map +1 -1
  21. package/dist/client/blocks/index.js +9 -0
  22. package/dist/client/blocks/index.js.map +1 -1
  23. package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
  24. package/dist/client/blocks/library/AnnotatedCodeBlock.js +3 -3
  25. package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
  26. package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
  27. package/dist/client/blocks/library/ApiEndpointBlock.js +1 -1
  28. package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
  29. package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
  30. package/dist/client/blocks/library/DiffBlock.js +128 -19
  31. package/dist/client/blocks/library/DiffBlock.js.map +1 -1
  32. package/dist/client/blocks/library/FileTreeBlock.d.ts.map +1 -1
  33. package/dist/client/blocks/library/FileTreeBlock.js +31 -4
  34. package/dist/client/blocks/library/FileTreeBlock.js.map +1 -1
  35. package/dist/client/blocks/library/JsonExplorerBlock.js +1 -1
  36. package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
  37. package/dist/client/blocks/library/MermaidBlock.js +1 -1
  38. package/dist/client/blocks/library/MermaidBlock.js.map +1 -1
  39. package/dist/client/blocks/library/callout.config.d.ts +29 -0
  40. package/dist/client/blocks/library/callout.config.d.ts.map +1 -0
  41. package/dist/client/blocks/library/callout.config.js +33 -0
  42. package/dist/client/blocks/library/callout.config.js.map +1 -0
  43. package/dist/client/blocks/library/callout.d.ts +20 -0
  44. package/dist/client/blocks/library/callout.d.ts.map +1 -0
  45. package/dist/client/blocks/library/callout.js +61 -0
  46. package/dist/client/blocks/library/callout.js.map +1 -0
  47. package/dist/client/blocks/library/checklist.d.ts.map +1 -1
  48. package/dist/client/blocks/library/checklist.js +3 -3
  49. package/dist/client/blocks/library/checklist.js.map +1 -1
  50. package/dist/client/blocks/library/code-tabs.js +1 -1
  51. package/dist/client/blocks/library/code-tabs.js.map +1 -1
  52. package/dist/client/blocks/library/diagram.config.d.ts +64 -0
  53. package/dist/client/blocks/library/diagram.config.d.ts.map +1 -0
  54. package/dist/client/blocks/library/diagram.config.js +111 -0
  55. package/dist/client/blocks/library/diagram.config.js.map +1 -0
  56. package/dist/client/blocks/library/diagram.d.ts +16 -0
  57. package/dist/client/blocks/library/diagram.d.ts.map +1 -0
  58. package/dist/client/blocks/library/diagram.js +261 -0
  59. package/dist/client/blocks/library/diagram.js.map +1 -0
  60. package/dist/client/blocks/library/question-form.config.d.ts +69 -0
  61. package/dist/client/blocks/library/question-form.config.d.ts.map +1 -0
  62. package/dist/client/blocks/library/question-form.config.js +58 -0
  63. package/dist/client/blocks/library/question-form.config.js.map +1 -0
  64. package/dist/client/blocks/library/question-form.d.ts +20 -0
  65. package/dist/client/blocks/library/question-form.d.ts.map +1 -0
  66. package/dist/client/blocks/library/question-form.js +286 -0
  67. package/dist/client/blocks/library/question-form.js.map +1 -0
  68. package/dist/client/blocks/library/sanitize-html.d.ts +5 -0
  69. package/dist/client/blocks/library/sanitize-html.d.ts.map +1 -0
  70. package/dist/client/blocks/library/sanitize-html.js +240 -0
  71. package/dist/client/blocks/library/sanitize-html.js.map +1 -0
  72. package/dist/client/blocks/library/server-specs.d.ts.map +1 -1
  73. package/dist/client/blocks/library/server-specs.js +49 -0
  74. package/dist/client/blocks/library/server-specs.js.map +1 -1
  75. package/dist/client/blocks/library/specs.d.ts.map +1 -1
  76. package/dist/client/blocks/library/specs.js +9 -0
  77. package/dist/client/blocks/library/specs.js.map +1 -1
  78. package/dist/client/blocks/library/tabs.d.ts.map +1 -1
  79. package/dist/client/blocks/library/tabs.js +12 -12
  80. package/dist/client/blocks/library/tabs.js.map +1 -1
  81. package/dist/client/blocks/library/wireframe-kit.d.ts +260 -0
  82. package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -0
  83. package/dist/client/blocks/library/wireframe-kit.js +920 -0
  84. package/dist/client/blocks/library/wireframe-kit.js.map +1 -0
  85. package/dist/client/blocks/library/wireframe.config.d.ts +123 -0
  86. package/dist/client/blocks/library/wireframe.config.d.ts.map +1 -0
  87. package/dist/client/blocks/library/wireframe.config.js +311 -0
  88. package/dist/client/blocks/library/wireframe.config.js.map +1 -0
  89. package/dist/client/blocks/library/wireframe.d.ts +15 -0
  90. package/dist/client/blocks/library/wireframe.d.ts.map +1 -0
  91. package/dist/client/blocks/library/wireframe.js +206 -0
  92. package/dist/client/blocks/library/wireframe.js.map +1 -0
  93. package/dist/client/blocks/mdx.d.ts.map +1 -1
  94. package/dist/client/blocks/mdx.js +11 -0
  95. package/dist/client/blocks/mdx.js.map +1 -1
  96. package/dist/client/blocks/registry.d.ts +9 -0
  97. package/dist/client/blocks/registry.d.ts.map +1 -1
  98. package/dist/client/blocks/registry.js +12 -5
  99. package/dist/client/blocks/registry.js.map +1 -1
  100. package/dist/client/blocks/server.d.ts +1 -0
  101. package/dist/client/blocks/server.d.ts.map +1 -1
  102. package/dist/client/blocks/server.js +1 -0
  103. package/dist/client/blocks/server.js.map +1 -1
  104. package/dist/client/blocks/types.d.ts +8 -0
  105. package/dist/client/blocks/types.d.ts.map +1 -1
  106. package/dist/client/blocks/types.js.map +1 -1
  107. package/dist/client/rich-markdown-editor/DragHandle.d.ts.map +1 -1
  108. package/dist/client/rich-markdown-editor/DragHandle.js +112 -84
  109. package/dist/client/rich-markdown-editor/DragHandle.js.map +1 -1
  110. package/dist/client/rich-markdown-editor/RegistryBlockNode.d.ts.map +1 -1
  111. package/dist/client/rich-markdown-editor/RegistryBlockNode.js +1 -1
  112. package/dist/client/rich-markdown-editor/RegistryBlockNode.js.map +1 -1
  113. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts +9 -1
  114. package/dist/client/rich-markdown-editor/SharedRichEditor.d.ts.map +1 -1
  115. package/dist/client/rich-markdown-editor/SharedRichEditor.js +3 -1
  116. package/dist/client/rich-markdown-editor/SharedRichEditor.js.map +1 -1
  117. package/dist/client/rich-markdown-editor/extensions.d.ts +13 -1
  118. package/dist/client/rich-markdown-editor/extensions.d.ts.map +1 -1
  119. package/dist/client/rich-markdown-editor/extensions.js +4 -2
  120. package/dist/client/rich-markdown-editor/extensions.js.map +1 -1
  121. package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
  122. package/dist/client/rich-markdown-editor/useCollabReconcile.js +11 -1
  123. package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
  124. package/dist/server/poll.d.ts.map +1 -1
  125. package/dist/server/poll.js +30 -14
  126. package/dist/server/poll.js.map +1 -1
  127. package/dist/styles/agent-native.css +1 -0
  128. package/dist/styles/blocks.css +1388 -0
  129. package/dist/templates/default/.agents/skills/storing-data/SKILL.md +2 -0
  130. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +141 -0
  131. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -0
  132. package/docs/content/plan-plugin.md +8 -8
  133. package/docs/content/pr-visual-recap.md +2 -2
  134. package/docs/content/template-plan.md +94 -17
  135. package/package.json +2 -1
  136. package/src/templates/default/.agents/skills/storing-data/SKILL.md +2 -0
  137. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +141 -0
  138. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -0
  139. package/docs/content/visual-plans.md +0 -82
@@ -14,6 +14,8 @@ metadata:
14
14
 
15
15
  All application data lives in **SQL** (SQLite locally, persistent database in production). The agent and UI share the same database. Do not store durable app data in the filesystem.
16
16
 
17
+ When you add a data model, a list, or a read path, also follow the `performance` skill: project only the columns a list renders, index the columns hot queries filter/sort on, and avoid query waterfalls — so apps stay fast as data grows.
18
+
17
19
  ## How It Works
18
20
 
19
21
  Agent-native apps use Drizzle ORM over the configured SQL backend. Local development works out of the box with a SQLite file at `data/app.db`; production and shared preview deploys need a persistent `DATABASE_URL` because container/serverless filesystems can reset. The code should behave the same across backends, but the local SQLite file is not durable once deployed.
@@ -0,0 +1,141 @@
1
+ ---
2
+ name: performance
3
+ description: >-
4
+ Keep apps and templates loading fast. Read when adding a data model, a
5
+ list/read action, a page or sidebar that loads data, or when something loads
6
+ slowly. Covers column projection, indexing hot-path queries, avoiding N+1 and
7
+ round-trip waterfalls, cheap polling, and not recomputing on every read.
8
+ metadata:
9
+ internal: true
10
+ ---
11
+
12
+ # Performance — Keep Loads Fast
13
+
14
+ ## Rule
15
+
16
+ Treat every list, every read, and every page load as a latency budget. Two
17
+ things dominate it: **how much data crosses the wire**, and **how many
18
+ round-trips and table scans it takes**. On a hosted/serverless SQL backend each
19
+ query is a network round-trip, and an unindexed filter scans the whole — often
20
+ shared and growing — table. So default to **projected columns**, **indexed
21
+ hot-path queries**, and **parallel/batched** fetches. These rules are
22
+ provider-agnostic: they hold on SQLite, Postgres, or any managed SQL backend.
23
+
24
+ This skill is about the data and load path. See the `storing-data` skill for the schema
25
+ and migration mechanics it references, and the `real-time-sync` skill for how updates
26
+ already reach the UI without polling.
27
+
28
+ ## 1. Project columns — never `SELECT *` on a list
29
+
30
+ A list/index query should select only the columns the list actually renders.
31
+
32
+ - **Never return heavy columns in a list**: large JSON/text blobs such as
33
+ document bodies, rendered HTML, `config`/`layout`/`spec`/`data`/`tracks`,
34
+ tool results, or base64 attachments. Pulling them for every row is the single
35
+ most common cause of a slow list.
36
+ - Heavy/full columns belong on the **single-item GET/detail** path only.
37
+ - Need a preview from a big column? Select a **truncated substring at the DB**,
38
+ not the whole column — and it stays portable:
39
+
40
+ ```ts
41
+ // Drizzle — project, and truncate the heavy column for the preview
42
+ const rows = await db
43
+ .select({
44
+ id: docs.id,
45
+ title: docs.title,
46
+ updatedAt: docs.updatedAt,
47
+ // substr/length work on both SQLite and Postgres
48
+ preview: sql<string>`substr(${docs.content}, 1, 400)`,
49
+ })
50
+ .from(docs)
51
+ .where(accessFilter(docs, docShares))
52
+ .orderBy(desc(docs.updatedAt));
53
+ ```
54
+
55
+ - After narrowing the projection, update the row mapper and its return type so a
56
+ dropped column is provably unused on the list path. If the list genuinely
57
+ renders a heavy column (a thumbnail, an inline preview the UI shows), keep it —
58
+ don't break behavior to chase a payload win.
59
+
60
+ ## 2. Index the hot paths
61
+
62
+ Indexes are added through the **versioned migration array** in
63
+ `server/plugins/db.ts` as `CREATE INDEX IF NOT EXISTS …` — not through a
64
+ schema-level `index()` helper (the framework applies indexes via migrations; see
65
+ the `storing-data` skill). Add an index for any column a hot query **filters or sorts**
66
+ on. The recurring ones:
67
+
68
+ - **Ownable tables** → `(owner_email, org_id, <the list's ORDER BY column>)`.
69
+ Access scoping filters by owner/org and lists sort by `updated_at`/`created_at`.
70
+ - **Shares tables** (`{resource}_shares`) → `(resource_id, principal_type, principal_id)`.
71
+ Access checks run correlated `EXISTS` subqueries against these on every list.
72
+ - **Child / foreign-key columns** used to load children (e.g. `responses.form_id`,
73
+ `comments.parent_id`, an events log's `*_id`) → index the FK, plus its sort
74
+ column when the children are ordered. An unindexed FK means a full scan of the
75
+ child table on every parent open. **A foreign-key reference does not create an
76
+ index automatically** — add it explicitly.
77
+ - **Status-filtered lists** → match the real `WHERE`, e.g. `(owner_email, status)`
78
+ or `(status, <sort>)`.
79
+
80
+ Keep index DDL **dialect-agnostic and idempotent**:
81
+
82
+ ```sql
83
+ CREATE INDEX IF NOT EXISTS forms_owner_org_updated_idx ON forms (owner_email, org_id, updated_at)
84
+ ```
85
+
86
+ No `DESC`, no partial `WHERE`, no provider-specific syntax — it then runs on
87
+ SQLite and Postgres alike, is safe to re-run, and applies on next startup.
88
+ Indexes mostly bite **as data grows** and on **unbounded child tables** (a
89
+ seq-scan of 10 rows is instant; of a shared, ever-growing log it is not), so
90
+ index the growing tables first.
91
+
92
+ ## 3. Don't fan out queries — batch and parallelize
93
+
94
+ - **No N+1.** Never loop issuing one query per item. Load children for many
95
+ parents in one `inArray(child.parentId, ids)` query, then group in memory.
96
+ - **Count in SQL** (`count()`), never "select all rows then `.length`".
97
+ - **Parallelize independent queries** with `Promise.all` rather than sequential
98
+ `await`s — each `await` is another round-trip.
99
+ - Prefer **one composed endpoint** over several dependent calls.
100
+
101
+ ## 4. Avoid client-side waterfalls
102
+
103
+ - Don't gate query B on query A's result unless B truly needs it. Fire
104
+ independent `useActionQuery` / `useQuery` hooks **in parallel**; never make the
105
+ loading skeleton wait on a serial chain.
106
+ - Load the visible page from one read where possible, and **lazy-load**
107
+ secondary / below-the-fold data after first paint.
108
+
109
+ ## 5. Poll cheaply; compute once
110
+
111
+ - Updates already reach the UI through the `real-time-sync` skill (`useDbSync` / SSE).
112
+ Don't add an aggressive `refetchInterval` that re-runs a heavy list/read every
113
+ couple of seconds. If you must poll, use a **wide interval** and a **cheap**
114
+ endpoint.
115
+ - **Never do expensive per-request work on a read that runs on every load/poll**:
116
+ re-rendering HTML/markdown, pretty-printing, re-parsing / migrating /
117
+ normalizing / sanitizing stored JSON. Do that work at **write time** (store the
118
+ result) or compute it **lazily only for the caller that needs it**. Reads on
119
+ the hot path must be cheap.
120
+ - Data the UI doesn't display (export formats, alternate renderings) belongs in a
121
+ separate on-demand action, not baked into the hot read.
122
+
123
+ ## 6. Big payloads and long lists
124
+
125
+ - **Paginate or window** unbounded lists (messages, responses, events, activity).
126
+ Don't load the entire history on open; load a recent window and fetch older on
127
+ demand.
128
+ - Don't store **unbounded blobs inline** in a row that a list/load pulls.
129
+ Reference large content separately so opening the parent stays cheap.
130
+ - **Virtualize** very long rendered lists on the client so off-screen rows aren't
131
+ parsed/rendered every update.
132
+
133
+ ## Checklist — run before shipping a list/read or a new table
134
+
135
+ - [ ] List selects only displayed columns; heavy blobs excluded or `substr`-truncated.
136
+ - [ ] Every hot-path `WHERE` / `ORDER BY` column is indexed (owner/org/sort,
137
+ shares `resource_id`, child FKs, status filters) via a `db.ts` migration.
138
+ - [ ] No N+1; independent queries parallelized; counts via SQL `count()`.
139
+ - [ ] Client fires independent queries in parallel, not a waterfall.
140
+ - [ ] No heavy recompute on every read; no aggressive polling of heavy endpoints.
141
+ - [ ] Unbounded lists are paginated/windowed; large blobs aren't inlined on the hot path.
@@ -14,6 +14,8 @@ metadata:
14
14
 
15
15
  All application data lives in **SQL** (SQLite locally, persistent database in production). The agent and UI share the same database. Do not store durable app data in the filesystem.
16
16
 
17
+ When you add a data model, a list, or a read path, also follow the `performance` skill: project only the columns a list renders, index the columns hot queries filter/sort on, and avoid query waterfalls — so apps stay fast as data grows.
18
+
17
19
  ## How It Works
18
20
 
19
21
  Agent-native apps use Drizzle ORM over the configured SQL backend. Local development works out of the box with a SQLite file at `data/app.db`; production and shared preview deploys need a persistent `DATABASE_URL` because container/serverless filesystems can reset. The code should behave the same across backends, but the local SQLite file is not durable once deployed.
@@ -1,20 +1,20 @@
1
1
  ---
2
2
  title: "Plan plugin & marketplace"
3
- description: "Install the Agent-Native Plan skills (/visual-plan, /visual-recap, /ui-plan, /prototype-plan, /plan-design, /visual-questions) plus the hosted Plan MCP connector as a Claude Code or Codex plugin, or with the universal CLI. How updates work and whether you need to submit anything."
3
+ description: "Install the Agent-Native Plan skills (/visual-plan, /visual-recap) plus the hosted Plan MCP connector as a Claude Code or Codex plugin, or with the universal CLI. How updates work and whether you need to submit anything."
4
4
  ---
5
5
 
6
6
  # Plan plugin & marketplace
7
7
 
8
- The Agent-Native **Plan** app ships as one installable bundle. A single install adds all six Plan slash-command skills **and** wires up the hosted Plan MCP connector, so the agent can generate plans and the skills can publish them straight into the Plan app.
8
+ The Agent-Native **Plan** app ships as one installable bundle. A single install adds both Plan slash-command skills **and** wires up the hosted Plan MCP connector, so the agent can generate plans and the skills can publish them straight into the Plan app.
9
9
 
10
10
  ## What you get {#what-you-get}
11
11
 
12
12
  One install gives you:
13
13
 
14
- - **Six skills** — `/visual-plan` (the canonical entry point), `/visual-recap`, `/ui-plan`, `/prototype-plan`, `/plan-design`, and `/visual-questions`.
14
+ - **Two skills** — `/visual-plan` (the canonical entry point) and `/visual-recap`.
15
15
  - **The Plan MCP connector** — registered against the hosted app at `https://plan.agent-native.com` (MCP endpoint `https://plan.agent-native.com/_agent-native/mcp`, server name `agent-native-plans`).
16
16
 
17
- All six skills **always publish to the hosted Plan app** — they create a plan via the MCP connector and hand you a link or inline plan to review. They never dump an inline Markdown/ASCII plan into chat as the deliverable. If a Plan tool returns `needs auth`, `Unauthorized`, or `Session terminated`, authenticate the connector (see each route below) instead of falling back to inline output.
17
+ Both skills **always publish to the hosted Plan app** — they create a plan via the MCP connector and hand you a link or inline plan to review. They never dump an inline Markdown/ASCII plan into chat as the deliverable. If a Plan tool returns `needs auth`, `Unauthorized`, or `Session terminated`, authenticate the connector (see each route below) instead of falling back to inline output.
18
18
 
19
19
  > The plugin (`agent-native-visual-plans`) carries app id `visual-plans`, which is why the Claude Code plugin name and Codex plugin name are both `agent-native-visual-plans`. The Plan app's display name is "Agent-Native Plan".
20
20
 
@@ -24,7 +24,7 @@ There are three ways in. The **universal CLI route** is the one we recommend by
24
24
 
25
25
  ### Universal skill route (any MCP host) {#universal}
26
26
 
27
- Works for any host — Claude Code, Codex, Cursor, Cline, Goose, ChatGPT custom MCP apps, Claude Cowork, and anything else MCP-compatible. The Agent-Native CLI installs the six skills, registers the hosted Plan MCP connector, **and authenticates it in the same step**, so your first tool call does not hit an OAuth wall:
27
+ Works for any host — Claude Code, Codex, Cursor, Cline, Goose, ChatGPT custom MCP apps, Claude Cowork, and anything else MCP-compatible. The Agent-Native CLI installs both skills, registers the hosted Plan MCP connector, **and authenticates it in the same step**, so your first tool call does not hit an OAuth wall:
28
28
 
29
29
  ```bash
30
30
  npx @agent-native/core@latest skills add visual-plan
@@ -32,7 +32,7 @@ npx @agent-native/core@latest skills add visual-plan
32
32
  agent-native skills add visual-plan
33
33
  ```
34
34
 
35
- This installs `visual-plan` plus the companion `visual-recap`, `visual-questions`, `ui-plan`, `prototype-plan`, and `plan-design` skills, then registers the `agent-native-plans` connector and runs auth (OAuth prompt for hosted/account-backed sharing). Useful flags:
35
+ This installs `visual-plan` plus the companion `visual-recap` skill, then registers the `agent-native-plans` connector and runs auth (OAuth prompt for hosted/account-backed sharing). Useful flags:
36
36
 
37
37
  - `--client codex|claude-code|claude-code-cli|cowork|all` — which local agents to write the MCP config for (default `codex`).
38
38
  - `--no-connect` — register the connector without authenticating; run `agent-native connect https://plan.agent-native.com` later.
@@ -54,7 +54,7 @@ The public `BuilderIO/agent-native` repo is itself a Claude Code plugin marketpl
54
54
  /mcp # authenticate the Plan connector (one OAuth approval)
55
55
  ```
56
56
 
57
- `/plugin install` adds the six Plan skills and a **URL-only** MCP config (no secrets in the package); `/mcp` → **Authenticate** completes the OAuth handshake.
57
+ `/plugin install` adds both Plan skills and a **URL-only** MCP config (no secrets in the package); `/mcp` → **Authenticate** completes the OAuth handshake.
58
58
 
59
59
  > The marketplace catalog is named `agent-native-apps` and the Plan plugin is `agent-native-visual-plans`, so the install target is always `agent-native-visual-plans@agent-native-apps`.
60
60
 
@@ -101,7 +101,7 @@ Under the hood, all three routes are produced from the same source by the `agent
101
101
 
102
102
  ## What's next {#whats-next}
103
103
 
104
- - [**Visual Plans**](/docs/visual-plans) — what the skills do and how to use them
104
+ - [**Visual Plans**](/docs/template-plan) — what the skills do and how to use them
105
105
  - [**PR Visual Recap**](/docs/pr-visual-recap) — run `/visual-recap` automatically on every pull request
106
106
  - [**Skills Guide**](/docs/skills-guide) — app-backed skills and the manifest format
107
107
  - [**External Agents**](/docs/external-agents) — connect any MCP host and round-trip artifacts
@@ -5,7 +5,7 @@ description: "A GitHub Action that runs your repo's visual-recap skill on every
5
5
 
6
6
  # PR Visual Recap
7
7
 
8
- PR Visual Recap is a GitHub Action that turns every pull request into a **visual code review**. On each push, an LLM coding agent runs your repo's [`visual-recap`](/docs/visual-plans) skill against the PR diff, publishes a structured recap plan to the hosted Plans app, and upserts **one sticky PR comment** that links to the interactive plan with an **inline screenshot** embedded right in the comment.
8
+ PR Visual Recap is a GitHub Action that turns every pull request into a **visual code review**. On each push, an LLM coding agent runs your repo's [`visual-recap`](/docs/template-plan) skill against the PR diff, publishes a structured recap plan to the hosted Plans app, and upserts **one sticky PR comment** that links to the interactive plan with an **inline screenshot** embedded right in the comment.
9
9
 
10
10
  This is not a deterministic diff renderer. The action invokes a real coding agent (Claude Code CLI by default, or OpenAI Codex CLI) that reads the change, decides what matters, and authors the recap by calling the Plans MCP tool `create-visual-recap` — the same tool the `/visual-recap` slash command uses. You get a high-altitude, schema/API/before-after view of the change instead of a wall of raw diff.
11
11
 
@@ -99,5 +99,5 @@ The recap is a review aid layered on top of the normal PR flow:
99
99
 
100
100
  ## Related
101
101
 
102
- - [Visual Plans](/docs/visual-plans) — the `/visual-plan` and `/visual-recap` skills, the hosted Plans connector, and the interactive review surface this action publishes to.
102
+ - [Visual Plans](/docs/template-plan) — the `/visual-plan` and `/visual-recap` skills, the hosted Plans connector, and the interactive review surface this action publishes to.
103
103
  - [Skills](/docs/skills-guide) — installing agent-native skills into your coding agent.
@@ -1,9 +1,9 @@
1
1
  ---
2
- title: "Plans"
3
- description: "Install Agent-Native Plans as an app-backed skill for Codex, Claude Code, and other coding agents. Create structured visual plans with diagrams, wireframes, annotations, comments, and share links."
2
+ title: "Visual Plans"
3
+ description: "Agent-Native Plans turns your coding agent's plan into a structured, reviewable document diagrams, wireframes, annotated code, comments, and share links. Install once from the CLI; reviewers you share with edit as a guest and sign in only to save or share."
4
4
  ---
5
5
 
6
- # Plans
6
+ # Visual Plans
7
7
 
8
8
  Agent-Native Plans is visual plan mode for coding agents. It turns an ordinary
9
9
  Codex, Claude Code, Markdown, or pasted implementation plan into a structured
@@ -18,11 +18,20 @@ agent the same way.
18
18
 
19
19
  ![Agent-Native Plans review surface](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fdd73f749f8c54dbcb577420ab1a18788)
20
20
 
21
- ## Install the skill
21
+ There are two ways into Plans:
22
+
23
+ - **From your coding agent (CLI)** — one command installs the skill, registers
24
+ the hosted Plans connector, and authenticates it.
25
+ - **In the browser** — anyone you share with can open the editor and create or
26
+ edit as a **guest, with no sign-up**. They sign in only when they want to save
27
+ or share.
28
+
29
+ ## Install the skill {#install}
22
30
 
23
31
  Use the Agent-Native CLI. This is the recommended setup because it installs the
24
- Plans skill instructions, registers the hosted Plans MCP connector, and runs the
25
- client-specific auth/setup flow in one step:
32
+ Plans skill instructions, registers the hosted Plans MCP connector, **and** runs
33
+ the client-specific auth/setup flow in one step, so your first tool call does not
34
+ hit an OAuth wall:
26
35
 
27
36
  ```bash
28
37
  npx @agent-native/core@latest skills add visual-plan
@@ -36,10 +45,16 @@ agent-native skills add visual-plan
36
45
 
37
46
  The command installs both commands: `/visual-plan` and `/visual-recap`.
38
47
 
39
- Use `/visual-plan` for both fresh plans and existing Codex, Claude Code,
40
- Markdown, or pasted plans; when source plan text already exists, the agent builds
41
- from that plan instead of starting over. Use `/visual-recap` to review a change
42
- that already landed instead of writing one up by hand.
48
+ Authentication is a one-time browser sign-in at setup this is intended, and it
49
+ is what lets the agent persist and share the plans it generates. What the auth
50
+ step does depends on your client:
51
+
52
+ - **OAuth-capable hosts** (Claude Code) get a URL-only MCP entry plus a prompt to
53
+ run `/mcp` and choose **Authenticate**.
54
+ - **Codex / Cowork** run a short browser device-code flow: the CLI prints a code,
55
+ opens the verification page, and writes the connector once you approve.
56
+ - In a **non-interactive shell or CI**, the auth step is skipped and the exact
57
+ command to run later is printed for you.
43
58
 
44
59
  By default the CLI targets Codex. Add `--client claude-code` or `--client all`
45
60
  when you want to configure another host:
@@ -48,6 +63,22 @@ when you want to configure another host:
48
63
  npx @agent-native/core@latest skills add visual-plan --client all
49
64
  ```
50
65
 
66
+ Pass `--no-connect` to register the connector without authenticating, then run
67
+ `agent-native connect https://plan.agent-native.com` whenever you are ready:
68
+
69
+ ```bash
70
+ npx @agent-native/core@latest skills add visual-plan --no-connect
71
+ ```
72
+
73
+ To auto-generate a recap on **every pull request**, pass `--with-github-action`.
74
+ This writes a GitHub Action that runs the `visual-recap` skill on each PR and
75
+ posts an interactive recap plan with an inline screenshot as a sticky comment —
76
+ see [PR Visual Recap](/docs/pr-visual-recap).
77
+
78
+ ```bash
79
+ npx @agent-native/core@latest skills add visual-plan --with-github-action
80
+ ```
81
+
51
82
  If you only want the portable instruction file through the open Skills CLI, use:
52
83
 
53
84
  ```bash
@@ -57,6 +88,11 @@ npx skills add BuilderIO/agent-native --skill visual-plan
57
88
  That installs the skill instructions only. It does not register the hosted MCP
58
89
  connector, so use the Agent-Native CLI path when you want the one-command setup.
59
90
 
91
+ > **Prefer a one-install plugin?** Claude Code and Codex can add
92
+ > `BuilderIO/agent-native` directly as a plugin marketplace, which bundles the
93
+ > Plan skills _and_ the connector in one install and auto-updates as the skills
94
+ > improve — see [Plan plugin & marketplace](/docs/plan-plugin).
95
+
60
96
  ## Use it from your coding agent
61
97
 
62
98
  After installation, ask your agent for the command that fits the work:
@@ -74,6 +110,10 @@ wrong direction would be costly. The returned Plans link opens the review UI so
74
110
  you can annotate, correct, choose options, and ask for updates before code
75
111
  changes begin.
76
112
 
113
+ When a Codex, Claude Code, Markdown, or pasted plan already exists, use
114
+ `/visual-plan`; the agent preserves that source plan and builds the richer review
115
+ surface from it instead of starting over.
116
+
77
117
  If the first pass still has answerable decisions, the agent can place an
78
118
  **Open Questions** form at the bottom of the same plan. Answering it and sending
79
119
  it to the agent starts a revision turn against the existing plan.
@@ -91,14 +131,36 @@ it to the agent starts a revision turn against the existing plan.
91
131
  prose block, visual comments include exact target metadata, and browser
92
132
  handoff includes focused screenshots for a small set of visual/canvas comment
93
133
  locations instead of one hard-to-read giant image.
94
- - **Share with reviewers.** Hosted Plans can create private review links and
95
- account-backed sharing. Viewing shared plans works from the browser; saving
96
- and sharing require sign-in.
97
134
  - **Export the result.** Keep an HTML, Markdown, or JSON receipt of the plan
98
135
  when you need a source-control-friendly handoff.
99
- - **Run locally when needed.** The template can be self-hosted for development
100
- or offline workflows, while the hosted skill is the easiest path for normal
101
- coding-agent use.
136
+
137
+ ## Editing in the browser as a guest {#guest}
138
+
139
+ People you share a plan with do not need to install anything. They open the Plans
140
+ editor and **create and edit with no sign-up** — they work as a guest. Signing in
141
+ is only required when someone wants to **save or share** their own work.
142
+
143
+ When a guest signs in, the plans they created as a guest are **claimed** into
144
+ their account, so nothing they built is lost.
145
+
146
+ Plan prose edits inline: click into any text section, type, format with the rich
147
+ editor toolbar or slash menu, and Plans autosaves the underlying markdown. Review
148
+ annotation mode temporarily turns text sections read-only so clicks can pin
149
+ feedback; leave review mode to keep editing prose.
150
+
151
+ ## Sharing and commenting {#sharing}
152
+
153
+ Sharing and commenting are the workflows that need an account:
154
+
155
+ - **Viewing** a public or shared plan works for anyone with the link — no account
156
+ required.
157
+ - **Commenting** on a shared plan requires an agent-native account.
158
+ - **Sharing** a plan (publishing it to a link, private sharing, reviewer access,
159
+ cross-device or team review) requires signing in. Google sign-in appears when
160
+ the standard Google OAuth env vars are configured.
161
+
162
+ The hosted Plans connector lives at `https://plan.agent-native.com/_agent-native/mcp`.
163
+ Never put shared secrets in skill files.
102
164
 
103
165
  ## Useful prompts
104
166
 
@@ -108,6 +170,14 @@ it to the agent starts a revision turn against the existing plan.
108
170
  - "Run `/visual-recap` on this PR so I can review the shape of the change first."
109
171
  - "Use `/visual-recap` on the diff between `main` and this branch."
110
172
 
173
+ ## Recovering from auth errors {#auth-errors}
174
+
175
+ If a Plans tool ever returns `needs auth`, `Unauthorized`, or `Session
176
+ terminated`, do not keep retrying it. Authenticate the connector with
177
+ `agent-native connect https://plan.agent-native.com` (or re-run `/mcp` →
178
+ **Authenticate** in an OAuth-capable host), then continue once the connector is
179
+ available.
180
+
111
181
  ## For developers
112
182
 
113
183
  The rest of this doc is for anyone forking or self-hosting the Plans template.
@@ -130,10 +200,17 @@ The hosted app-backed skill uses:
130
200
  The local template is useful when you are developing Plans itself, testing local
131
201
  persistence, or running a fully self-hosted review surface.
132
202
 
203
+ ### Local mode (advanced, offline)
204
+
205
+ For fully offline, no-account use, you can run the Plans app locally and sync
206
+ your plans to your repo as MDX. This local mode is a separate, advanced path —
207
+ not the default hosted flow — and is best when you need everything to stay on
208
+ your machine and in version control.
209
+
133
210
  ## What's next
134
211
 
135
- - [**Visual Plans**](/docs/visual-plans) — the full skill flow and auth details
136
212
  - [**PR Visual Recap**](/docs/pr-visual-recap) — run `/visual-recap` automatically on every pull request
213
+ - [**Plan plugin & marketplace**](/docs/plan-plugin) — install the Plan skills as a Claude Code or Codex plugin
137
214
  - [**Skills**](/docs/skills-guide) — how Agent-Native installs skills
138
215
  - [**MCP Clients**](/docs/mcp-clients) — configuring hosted MCP connectors
139
216
  - [**Templates**](/docs/cloneable-saas) — the clone-and-own model
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.42.0",
3
+ "version": "0.44.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -198,6 +198,7 @@
198
198
  "react-router": "^7.16.0",
199
199
  "recharts": "3.8.1",
200
200
  "remark-gfm": "^4.0.1",
201
+ "roughjs": "4.6.6",
201
202
  "shiki": "^4.0.2",
202
203
  "tailwind-merge": "^3.5.0",
203
204
  "tiptap-markdown": "^0.9.0",
@@ -14,6 +14,8 @@ metadata:
14
14
 
15
15
  All application data lives in **SQL** (SQLite locally, persistent database in production). The agent and UI share the same database. Do not store durable app data in the filesystem.
16
16
 
17
+ When you add a data model, a list, or a read path, also follow the `performance` skill: project only the columns a list renders, index the columns hot queries filter/sort on, and avoid query waterfalls — so apps stay fast as data grows.
18
+
17
19
  ## How It Works
18
20
 
19
21
  Agent-native apps use Drizzle ORM over the configured SQL backend. Local development works out of the box with a SQLite file at `data/app.db`; production and shared preview deploys need a persistent `DATABASE_URL` because container/serverless filesystems can reset. The code should behave the same across backends, but the local SQLite file is not durable once deployed.
@@ -0,0 +1,141 @@
1
+ ---
2
+ name: performance
3
+ description: >-
4
+ Keep apps and templates loading fast. Read when adding a data model, a
5
+ list/read action, a page or sidebar that loads data, or when something loads
6
+ slowly. Covers column projection, indexing hot-path queries, avoiding N+1 and
7
+ round-trip waterfalls, cheap polling, and not recomputing on every read.
8
+ metadata:
9
+ internal: true
10
+ ---
11
+
12
+ # Performance — Keep Loads Fast
13
+
14
+ ## Rule
15
+
16
+ Treat every list, every read, and every page load as a latency budget. Two
17
+ things dominate it: **how much data crosses the wire**, and **how many
18
+ round-trips and table scans it takes**. On a hosted/serverless SQL backend each
19
+ query is a network round-trip, and an unindexed filter scans the whole — often
20
+ shared and growing — table. So default to **projected columns**, **indexed
21
+ hot-path queries**, and **parallel/batched** fetches. These rules are
22
+ provider-agnostic: they hold on SQLite, Postgres, or any managed SQL backend.
23
+
24
+ This skill is about the data and load path. See the `storing-data` skill for the schema
25
+ and migration mechanics it references, and the `real-time-sync` skill for how updates
26
+ already reach the UI without polling.
27
+
28
+ ## 1. Project columns — never `SELECT *` on a list
29
+
30
+ A list/index query should select only the columns the list actually renders.
31
+
32
+ - **Never return heavy columns in a list**: large JSON/text blobs such as
33
+ document bodies, rendered HTML, `config`/`layout`/`spec`/`data`/`tracks`,
34
+ tool results, or base64 attachments. Pulling them for every row is the single
35
+ most common cause of a slow list.
36
+ - Heavy/full columns belong on the **single-item GET/detail** path only.
37
+ - Need a preview from a big column? Select a **truncated substring at the DB**,
38
+ not the whole column — and it stays portable:
39
+
40
+ ```ts
41
+ // Drizzle — project, and truncate the heavy column for the preview
42
+ const rows = await db
43
+ .select({
44
+ id: docs.id,
45
+ title: docs.title,
46
+ updatedAt: docs.updatedAt,
47
+ // substr/length work on both SQLite and Postgres
48
+ preview: sql<string>`substr(${docs.content}, 1, 400)`,
49
+ })
50
+ .from(docs)
51
+ .where(accessFilter(docs, docShares))
52
+ .orderBy(desc(docs.updatedAt));
53
+ ```
54
+
55
+ - After narrowing the projection, update the row mapper and its return type so a
56
+ dropped column is provably unused on the list path. If the list genuinely
57
+ renders a heavy column (a thumbnail, an inline preview the UI shows), keep it —
58
+ don't break behavior to chase a payload win.
59
+
60
+ ## 2. Index the hot paths
61
+
62
+ Indexes are added through the **versioned migration array** in
63
+ `server/plugins/db.ts` as `CREATE INDEX IF NOT EXISTS …` — not through a
64
+ schema-level `index()` helper (the framework applies indexes via migrations; see
65
+ the `storing-data` skill). Add an index for any column a hot query **filters or sorts**
66
+ on. The recurring ones:
67
+
68
+ - **Ownable tables** → `(owner_email, org_id, <the list's ORDER BY column>)`.
69
+ Access scoping filters by owner/org and lists sort by `updated_at`/`created_at`.
70
+ - **Shares tables** (`{resource}_shares`) → `(resource_id, principal_type, principal_id)`.
71
+ Access checks run correlated `EXISTS` subqueries against these on every list.
72
+ - **Child / foreign-key columns** used to load children (e.g. `responses.form_id`,
73
+ `comments.parent_id`, an events log's `*_id`) → index the FK, plus its sort
74
+ column when the children are ordered. An unindexed FK means a full scan of the
75
+ child table on every parent open. **A foreign-key reference does not create an
76
+ index automatically** — add it explicitly.
77
+ - **Status-filtered lists** → match the real `WHERE`, e.g. `(owner_email, status)`
78
+ or `(status, <sort>)`.
79
+
80
+ Keep index DDL **dialect-agnostic and idempotent**:
81
+
82
+ ```sql
83
+ CREATE INDEX IF NOT EXISTS forms_owner_org_updated_idx ON forms (owner_email, org_id, updated_at)
84
+ ```
85
+
86
+ No `DESC`, no partial `WHERE`, no provider-specific syntax — it then runs on
87
+ SQLite and Postgres alike, is safe to re-run, and applies on next startup.
88
+ Indexes mostly bite **as data grows** and on **unbounded child tables** (a
89
+ seq-scan of 10 rows is instant; of a shared, ever-growing log it is not), so
90
+ index the growing tables first.
91
+
92
+ ## 3. Don't fan out queries — batch and parallelize
93
+
94
+ - **No N+1.** Never loop issuing one query per item. Load children for many
95
+ parents in one `inArray(child.parentId, ids)` query, then group in memory.
96
+ - **Count in SQL** (`count()`), never "select all rows then `.length`".
97
+ - **Parallelize independent queries** with `Promise.all` rather than sequential
98
+ `await`s — each `await` is another round-trip.
99
+ - Prefer **one composed endpoint** over several dependent calls.
100
+
101
+ ## 4. Avoid client-side waterfalls
102
+
103
+ - Don't gate query B on query A's result unless B truly needs it. Fire
104
+ independent `useActionQuery` / `useQuery` hooks **in parallel**; never make the
105
+ loading skeleton wait on a serial chain.
106
+ - Load the visible page from one read where possible, and **lazy-load**
107
+ secondary / below-the-fold data after first paint.
108
+
109
+ ## 5. Poll cheaply; compute once
110
+
111
+ - Updates already reach the UI through the `real-time-sync` skill (`useDbSync` / SSE).
112
+ Don't add an aggressive `refetchInterval` that re-runs a heavy list/read every
113
+ couple of seconds. If you must poll, use a **wide interval** and a **cheap**
114
+ endpoint.
115
+ - **Never do expensive per-request work on a read that runs on every load/poll**:
116
+ re-rendering HTML/markdown, pretty-printing, re-parsing / migrating /
117
+ normalizing / sanitizing stored JSON. Do that work at **write time** (store the
118
+ result) or compute it **lazily only for the caller that needs it**. Reads on
119
+ the hot path must be cheap.
120
+ - Data the UI doesn't display (export formats, alternate renderings) belongs in a
121
+ separate on-demand action, not baked into the hot read.
122
+
123
+ ## 6. Big payloads and long lists
124
+
125
+ - **Paginate or window** unbounded lists (messages, responses, events, activity).
126
+ Don't load the entire history on open; load a recent window and fetch older on
127
+ demand.
128
+ - Don't store **unbounded blobs inline** in a row that a list/load pulls.
129
+ Reference large content separately so opening the parent stays cheap.
130
+ - **Virtualize** very long rendered lists on the client so off-screen rows aren't
131
+ parsed/rendered every update.
132
+
133
+ ## Checklist — run before shipping a list/read or a new table
134
+
135
+ - [ ] List selects only displayed columns; heavy blobs excluded or `substr`-truncated.
136
+ - [ ] Every hot-path `WHERE` / `ORDER BY` column is indexed (owner/org/sort,
137
+ shares `resource_id`, child FKs, status filters) via a `db.ts` migration.
138
+ - [ ] No N+1; independent queries parallelized; counts via SQL `count()`.
139
+ - [ ] Client fires independent queries in parallel, not a waterfall.
140
+ - [ ] No heavy recompute on every read; no aggressive polling of heavy endpoints.
141
+ - [ ] Unbounded lists are paginated/windowed; large blobs aren't inlined on the hot path.
@@ -14,6 +14,8 @@ metadata:
14
14
 
15
15
  All application data lives in **SQL** (SQLite locally, persistent database in production). The agent and UI share the same database. Do not store durable app data in the filesystem.
16
16
 
17
+ When you add a data model, a list, or a read path, also follow the `performance` skill: project only the columns a list renders, index the columns hot queries filter/sort on, and avoid query waterfalls — so apps stay fast as data grows.
18
+
17
19
  ## How It Works
18
20
 
19
21
  Agent-native apps use Drizzle ORM over the configured SQL backend. Local development works out of the box with a SQLite file at `data/app.db`; production and shared preview deploys need a persistent `DATABASE_URL` because container/serverless filesystems can reset. The code should behave the same across backends, but the local SQLite file is not durable once deployed.