@agent-native/core 0.2.7 → 0.3.1

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 (147) hide show
  1. package/README.md +59 -26
  2. package/dist/a2a/agent-card.d.ts +3 -0
  3. package/dist/a2a/agent-card.d.ts.map +1 -0
  4. package/dist/a2a/agent-card.js +26 -0
  5. package/dist/a2a/agent-card.js.map +1 -0
  6. package/dist/a2a/client.d.ts +25 -0
  7. package/dist/a2a/client.d.ts.map +1 -0
  8. package/dist/a2a/client.js +119 -0
  9. package/dist/a2a/client.js.map +1 -0
  10. package/dist/a2a/handlers.d.ts +4 -0
  11. package/dist/a2a/handlers.d.ts.map +1 -0
  12. package/dist/a2a/handlers.js +252 -0
  13. package/dist/a2a/handlers.js.map +1 -0
  14. package/dist/a2a/index.d.ts +4 -0
  15. package/dist/a2a/index.d.ts.map +1 -0
  16. package/dist/a2a/index.js +5 -0
  17. package/dist/a2a/index.js.map +1 -0
  18. package/dist/a2a/middleware.d.ts +3 -0
  19. package/dist/a2a/middleware.d.ts.map +1 -0
  20. package/dist/a2a/middleware.js +36 -0
  21. package/dist/a2a/middleware.js.map +1 -0
  22. package/dist/a2a/server.d.ts +4 -0
  23. package/dist/a2a/server.d.ts.map +1 -0
  24. package/dist/a2a/server.js +18 -0
  25. package/dist/a2a/server.js.map +1 -0
  26. package/dist/a2a/task-store.d.ts +10 -0
  27. package/dist/a2a/task-store.d.ts.map +1 -0
  28. package/dist/a2a/task-store.js +73 -0
  29. package/dist/a2a/task-store.js.map +1 -0
  30. package/dist/a2a/types.d.ts +109 -0
  31. package/dist/a2a/types.d.ts.map +1 -0
  32. package/dist/a2a/types.js +3 -0
  33. package/dist/a2a/types.js.map +1 -0
  34. package/dist/adapters/cli/index.d.ts +4 -0
  35. package/dist/adapters/cli/index.d.ts.map +1 -0
  36. package/dist/adapters/cli/index.js +3 -0
  37. package/dist/adapters/cli/index.js.map +1 -0
  38. package/dist/adapters/cli/registry.d.ts +33 -0
  39. package/dist/adapters/cli/registry.d.ts.map +1 -0
  40. package/dist/adapters/cli/registry.js +62 -0
  41. package/dist/adapters/cli/registry.js.map +1 -0
  42. package/dist/adapters/cli/shell-adapter.d.ts +42 -0
  43. package/dist/adapters/cli/shell-adapter.d.ts.map +1 -0
  44. package/dist/adapters/cli/shell-adapter.js +57 -0
  45. package/dist/adapters/cli/shell-adapter.js.map +1 -0
  46. package/dist/adapters/cli/types.d.ts +24 -0
  47. package/dist/adapters/cli/types.d.ts.map +1 -0
  48. package/dist/adapters/cli/types.js +2 -0
  49. package/dist/adapters/cli/types.js.map +1 -0
  50. package/dist/adapters/firestore/adapter.d.ts.map +1 -1
  51. package/dist/adapters/firestore/adapter.js.map +1 -1
  52. package/dist/adapters/neon/adapter.d.ts.map +1 -1
  53. package/dist/adapters/neon/adapter.js +37 -21
  54. package/dist/adapters/neon/adapter.js.map +1 -1
  55. package/dist/adapters/supabase/adapter.d.ts.map +1 -1
  56. package/dist/adapters/supabase/adapter.js +10 -2
  57. package/dist/adapters/supabase/adapter.js.map +1 -1
  58. package/dist/adapters/sync/file-sync.d.ts.map +1 -1
  59. package/dist/adapters/sync/file-sync.js.map +1 -1
  60. package/dist/adapters/sync/index.d.ts +2 -2
  61. package/dist/adapters/sync/index.d.ts.map +1 -1
  62. package/dist/adapters/sync/index.js +1 -1
  63. package/dist/adapters/sync/index.js.map +1 -1
  64. package/dist/adapters/sync/merge.js +1 -2
  65. package/dist/adapters/sync/merge.js.map +1 -1
  66. package/dist/adapters/sync/types.d.ts.map +1 -1
  67. package/dist/cli/create.d.ts.map +1 -1
  68. package/dist/cli/create.js.map +1 -1
  69. package/dist/cli/index.js +15 -13
  70. package/dist/cli/index.js.map +1 -1
  71. package/dist/client/components/ApiKeySettings.d.ts +1 -1
  72. package/dist/client/components/ApiKeySettings.d.ts.map +1 -1
  73. package/dist/client/components/ApiKeySettings.js +9 -4
  74. package/dist/client/components/ApiKeySettings.js.map +1 -1
  75. package/dist/client/components/MissingKeyCard.d.ts +1 -1
  76. package/dist/client/components/MissingKeyCard.d.ts.map +1 -1
  77. package/dist/client/components/MissingKeyCard.js +1 -1
  78. package/dist/client/components/MissingKeyCard.js.map +1 -1
  79. package/dist/client/harness.d.ts +10 -0
  80. package/dist/client/harness.d.ts.map +1 -1
  81. package/dist/client/harness.js +27 -0
  82. package/dist/client/harness.js.map +1 -1
  83. package/dist/client/index.d.ts +1 -1
  84. package/dist/client/index.d.ts.map +1 -1
  85. package/dist/client/index.js +1 -1
  86. package/dist/client/index.js.map +1 -1
  87. package/dist/client/use-file-watcher.d.ts.map +1 -1
  88. package/dist/client/use-file-watcher.js.map +1 -1
  89. package/dist/index.d.ts +1 -1
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +1 -1
  92. package/dist/index.js.map +1 -1
  93. package/dist/scripts/utils.d.ts.map +1 -1
  94. package/dist/scripts/utils.js +3 -1
  95. package/dist/scripts/utils.js.map +1 -1
  96. package/dist/server/create-server.d.ts.map +1 -1
  97. package/dist/server/create-server.js +2 -1
  98. package/dist/server/create-server.js.map +1 -1
  99. package/dist/server/index.d.ts +1 -1
  100. package/dist/server/index.d.ts.map +1 -1
  101. package/dist/server/index.js +1 -1
  102. package/dist/server/index.js.map +1 -1
  103. package/dist/server/missing-key.d.ts.map +1 -1
  104. package/dist/server/missing-key.js.map +1 -1
  105. package/dist/server/production.d.ts.map +1 -1
  106. package/dist/server/production.js.map +1 -1
  107. package/dist/server/sse.d.ts +1 -1
  108. package/dist/server/sse.d.ts.map +1 -1
  109. package/dist/server/sse.js.map +1 -1
  110. package/dist/shared/agent-chat.d.ts +18 -0
  111. package/dist/shared/agent-chat.d.ts.map +1 -1
  112. package/dist/shared/agent-chat.js +35 -0
  113. package/dist/shared/agent-chat.js.map +1 -1
  114. package/dist/shared/index.d.ts +1 -1
  115. package/dist/shared/index.d.ts.map +1 -1
  116. package/dist/shared/index.js +1 -1
  117. package/dist/shared/index.js.map +1 -1
  118. package/package.json +127 -125
  119. package/src/templates/default/.agents/skills/capture-learnings/SKILL.md +50 -0
  120. package/src/templates/default/.agents/skills/create-skill/SKILL.md +167 -0
  121. package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +90 -0
  122. package/src/templates/default/.agents/skills/files-as-database/SKILL.md +91 -0
  123. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +69 -0
  124. package/src/templates/default/.agents/skills/scripts/SKILL.md +118 -0
  125. package/src/templates/default/.agents/skills/self-modifying-code/SKILL.md +79 -0
  126. package/src/templates/default/.agents/skills/sse-file-watcher/SKILL.md +95 -0
  127. package/src/templates/default/.claude/settings.json +86 -68
  128. package/src/templates/default/.prettierrc +5 -5
  129. package/src/templates/default/AGENTS.md +86 -69
  130. package/src/templates/default/client/App.tsx +56 -54
  131. package/src/templates/default/client/global.css +75 -72
  132. package/src/templates/default/client/lib/utils.ts +1 -1
  133. package/src/templates/default/client/vite-env.d.ts +1 -1
  134. package/src/templates/default/components.json +20 -20
  135. package/src/templates/default/index.html +14 -14
  136. package/src/templates/default/package.json +43 -43
  137. package/src/templates/default/postcss.config.js +6 -6
  138. package/src/templates/default/scripts/hello.ts +20 -20
  139. package/src/templates/default/scripts/run.ts +9 -9
  140. package/src/templates/default/server/index.ts +22 -18
  141. package/src/templates/default/server/node-build.ts +4 -4
  142. package/src/templates/default/shared/api.ts +6 -6
  143. package/src/templates/default/tailwind.config.ts +7 -7
  144. package/src/templates/default/tsconfig.json +3 -3
  145. package/src/templates/default/vite.config.server.ts +3 -3
  146. package/src/templates/default/vite.config.ts +3 -3
  147. package/tsconfig.base.json +41 -41
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: frontend-design
3
+ description: >-
4
+ Create distinctive, production-grade frontend interfaces with high design
5
+ quality. Use when building web components, pages, artifacts, posters, or
6
+ applications (websites, landing pages, dashboards, React components,
7
+ HTML/CSS layouts, or when styling/beautifying any web UI). Generates
8
+ creative, polished UI that avoids generic AI aesthetics.
9
+ license: Complete terms in LICENSE.txt
10
+ source: https://github.com/anthropics/skills/blob/main/skills/frontend-design/SKILL.md
11
+ ---
12
+
13
+ # Frontend Design
14
+
15
+ This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
16
+
17
+ The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
18
+
19
+ ## Design Thinking
20
+
21
+ Before coding, understand the context and commit to a BOLD aesthetic direction:
22
+ - **Purpose**: What problem does this interface solve? Who uses it?
23
+ - **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
24
+ - **Constraints**: Technical requirements (framework, performance, accessibility).
25
+ - **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
26
+
27
+ **CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work — the key is intentionality, not intensity.
28
+
29
+ Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
30
+ - Production-grade and functional
31
+ - Visually striking and memorable
32
+ - Cohesive with a clear aesthetic point-of-view
33
+ - Meticulously refined in every detail
34
+
35
+ ## Frontend Aesthetics Guidelines
36
+
37
+ Focus on:
38
+ - **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
39
+ - **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
40
+ - **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (`animation-delay`) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
41
+ - **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
42
+ - **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
43
+
44
+ ## Anti-Patterns to Avoid
45
+
46
+ NEVER use generic AI-generated aesthetics like:
47
+ - Overused font families (Inter, Roboto, Arial, system fonts)
48
+ - Clichéd color schemes (particularly purple gradients on white backgrounds)
49
+ - Predictable layouts and component patterns
50
+ - Cookie-cutter design that lacks context-specific character
51
+
52
+ Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
53
+
54
+ ## Implementation Notes
55
+
56
+ **Match implementation complexity to the aesthetic vision.** Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
57
+
58
+ In the agent-native framework context:
59
+ - Agent-native apps use React 18, Vite, TailwindCSS, and shadcn/ui
60
+ - Custom styles go in component CSS or Tailwind classes — never inline styles
61
+ - For complex visual effects, use a `<style>` tag in the component or a dedicated CSS file
62
+ - Fonts can be loaded from Google Fonts via `@import` in a CSS file or `<link>` in `index.html`
63
+ - Animation libraries: prefer CSS transitions and keyframes; use Framer Motion for complex sequences
64
+ - All new UI components should be placed in `client/components/`
65
+
66
+ ## Related Skills
67
+
68
+ - **self-modifying-code** — The agent can edit source code to apply design changes
69
+ - **files-as-database** — Design configuration can be stored as JSON in `data/` for agent-editable theming
@@ -0,0 +1,118 @@
1
+ ---
2
+ name: scripts
3
+ description: >-
4
+ How to create and run agent-callable scripts in scripts/. Use when creating
5
+ a new script, adding an API integration, implementing a complex agent
6
+ operation, or running pnpm script commands.
7
+ ---
8
+
9
+ # Agent Scripts
10
+
11
+ ## Rule
12
+
13
+ Complex operations the agent needs to perform are implemented as scripts in `scripts/`. The agent runs them via `pnpm script <name>`.
14
+
15
+ ## Why
16
+
17
+ Scripts give the agent callable tools with structured input/output. They keep the agent's chat context clean (no massive code blocks), they're reusable, and they can be tested independently.
18
+
19
+ ## How to Create a Script
20
+
21
+ Create `scripts/my-script.ts`:
22
+
23
+ ```ts
24
+ import fs from "fs";
25
+ import { parseArgs, loadEnv, fail, agentChat } from "@agent-native/core";
26
+
27
+ export default async function myScript(args: string[]) {
28
+ loadEnv();
29
+
30
+ const parsed = parseArgs(args);
31
+ const input = parsed.input;
32
+ if (!input) fail("--input is required");
33
+
34
+ const outputPath = parsed.output ?? "data/result.json";
35
+ const raw = fs.readFileSync(input, "utf-8");
36
+ const data = JSON.parse(raw) as unknown;
37
+
38
+ fs.writeFileSync(outputPath, JSON.stringify(data, null, 2));
39
+ agentChat.submit(`Processed ${input}, result saved to ${outputPath}`);
40
+ }
41
+ ```
42
+
43
+ ## How to Run
44
+
45
+ ```bash
46
+ pnpm script my-script --input data/source.json --output data/result.json
47
+ ```
48
+
49
+ ## Script Dispatcher
50
+
51
+ The default template uses core's `runScript()` in `scripts/run.ts`:
52
+
53
+ ```ts
54
+ import { runScript } from "@agent-native/core";
55
+ runScript();
56
+ ```
57
+
58
+ This is the canonical approach for new apps. Script names must be lowercase with hyphens only (e.g., `my-script`).
59
+
60
+ ## Guidelines
61
+
62
+ - **One script, one job.** Keep scripts focused on a single operation. The agent composes multiple script calls for complex operations.
63
+ - **Use `parseArgs()`** for structured argument parsing. It converts `--key value` pairs to a `Record<string, string>`.
64
+ - **Use `loadEnv()`** if the script needs environment variables (API keys, etc.).
65
+ - **Use `fail()`** for user-friendly error messages (exits with message, no stack trace).
66
+ - **Write results to files.** The agent and UI will pick them up via the file watcher.
67
+ - **Use `agentChat.submit()`** to report results or errors back to the agent chat.
68
+ - **Import from `@agent-native/core`** — Don't redefine `parseArgs()` or other utilities locally.
69
+
70
+ ## Common Patterns
71
+
72
+ **API integration script** (e.g., image generation):
73
+
74
+ ```ts
75
+ import fs from "fs";
76
+ import { parseArgs, loadEnv, fail } from "@agent-native/core";
77
+
78
+ export default async function generateImage(args: string[]) {
79
+ loadEnv();
80
+ const parsed = parseArgs(args);
81
+ const prompt = parsed.prompt;
82
+ if (!prompt) fail("--prompt is required");
83
+
84
+ const outputPath = parsed.output ?? "data/generated-image.png";
85
+ const imageUrl = await callImageAPI(prompt);
86
+ const buffer = await fetch(imageUrl).then((r) => r.arrayBuffer());
87
+ fs.writeFileSync(outputPath, Buffer.from(buffer));
88
+ }
89
+ ```
90
+
91
+ **Data processing script:**
92
+
93
+ ```ts
94
+ import fs from "fs";
95
+ import { parseArgs, fail } from "@agent-native/core";
96
+
97
+ export default async function transform(args: string[]) {
98
+ const parsed = parseArgs(args);
99
+ const source = parsed.source;
100
+ if (!source) fail("--source is required");
101
+
102
+ const data = JSON.parse(fs.readFileSync(source, "utf-8")) as unknown[];
103
+ const result = data.map(transformItem);
104
+ fs.writeFileSync(source, JSON.stringify(result, null, 2));
105
+ }
106
+ ```
107
+
108
+ ## Troubleshooting
109
+
110
+ - **Script not found** — Check that the filename matches the command name exactly. `pnpm script foo-bar` looks for `scripts/foo-bar.ts`.
111
+ - **Args not parsing** — Ensure args use `--key value` or `--key=value` format. Boolean flags use `--flag` (sets value to `"true"`).
112
+ - **Script runs but UI doesn't update** — Make sure results are written to a path under `data/` that the file watcher monitors.
113
+
114
+ ## Related Skills
115
+
116
+ - **files-as-database** — Scripts read/write data files in `data/`
117
+ - **delegate-to-agent** — The agent invokes scripts via `pnpm script <name>`
118
+ - **sse-file-watcher** — File writes from scripts trigger SSE events to update the UI
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: self-modifying-code
3
+ description: >-
4
+ How the agent can modify the app's own source code. Use when the agent needs
5
+ to edit components, routes, styles, or scripts, when designing UI for agent
6
+ editability, or when deciding what the agent should and shouldn't modify.
7
+ ---
8
+
9
+ # Self-Modifying Code
10
+
11
+ ## Rule
12
+
13
+ The agent can edit the app's own source code — components, routes, styles, scripts. This is a feature, not a bug. Design your app expecting this.
14
+
15
+ ## Why
16
+
17
+ An agent-native app isn't just an app the agent can _use_ — it's an app the agent can _change_. The agent can fix bugs, add features, adjust styles, and restructure code. This makes the agent a true collaborator, not just an operator.
18
+
19
+ ## Modification Taxonomy
20
+
21
+ Not all modifications are equal. Use this to decide what level of care is needed:
22
+
23
+ | Tier | What | Examples | After modifying |
24
+ | ------------- | --------------------- | ------------------------------------------------ | --------------------------------- |
25
+ | 1: Data | Files in `data/` | JSON state, generated content, markdown | Nothing — these are routine |
26
+ | 2: Source | App code | Components, routes, styles, scripts | Run `pnpm typecheck && pnpm lint` |
27
+ | 3: Config | Project config | `package.json`, `tsconfig.json`, `vite.config.*` | Ask for explicit approval first |
28
+ | 4: Off limits | Secrets and framework | `.env`, `@agent-native/core` internals | Never modify these |
29
+
30
+ ## Git Checkpoint Pattern
31
+
32
+ Before modifying source code (Tier 2+), create a rollback point:
33
+
34
+ 1. Commit or stash current state
35
+ 2. Make the edit
36
+ 3. Run `pnpm typecheck && pnpm lint`
37
+ 4. If verification fails → revert with `git checkout -- <file>`
38
+ 5. If verification passes → continue
39
+
40
+ This ensures the agent can experiment without breaking the app.
41
+
42
+ ## Designing for Agent Editability
43
+
44
+ Make your app easy for the agent to understand and modify:
45
+
46
+ **Expose UI state via `data-*` attributes** so the agent knows what's selected:
47
+
48
+ ```ts
49
+ const el = document.documentElement;
50
+ el.dataset.currentView = view;
51
+ el.dataset.selectedId = selectedItem?.id || "";
52
+ ```
53
+
54
+ **Expose richer context via `window.__appState`** for complex state:
55
+
56
+ ```ts
57
+ (window as any).__appState = {
58
+ selectedId: id,
59
+ currentLayout: layout,
60
+ itemCount: items.length,
61
+ };
62
+ ```
63
+
64
+ **Use configuration-driven rendering** — Extract visual decisions (colors, layouts, sizes) into JSON config files in `data/`. The agent can modify the config (Tier 1) instead of the component source (Tier 2).
65
+
66
+ ## Don't
67
+
68
+ - Don't modify `.env` files or files containing secrets
69
+ - Don't modify `@agent-native/core` package internals
70
+ - Don't modify `.agents/skills/` or `AGENTS.md` unless explicitly requested
71
+ - Don't skip the typecheck/lint step after editing source code
72
+ - Don't make source changes without a git checkpoint to roll back to
73
+
74
+ ## Related Skills
75
+
76
+ - **files-as-database** — Tier 1 modifications (data files) are the safest and most common
77
+ - **scripts** — The agent can create or modify scripts to add new capabilities
78
+ - **delegate-to-agent** — Self-modification requests come through the agent chat
79
+ - **sse-file-watcher** — Source and data file edits trigger SSE events to update the UI
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: sse-file-watcher
3
+ description: >-
4
+ How to keep the UI in sync with agent changes via Server-Sent Events. Use
5
+ when setting up real-time file sync, adding SSE to a new data directory,
6
+ wiring query invalidation for new data models, or debugging UI not updating.
7
+ ---
8
+
9
+ # SSE File Watcher
10
+
11
+ ## Rule
12
+
13
+ The UI stays in sync with agent changes through Server-Sent Events. When the agent writes a file, the UI updates automatically — no polling, no manual refresh.
14
+
15
+ ## Why
16
+
17
+ The agent modifies files on disk, but the UI runs in the browser. SSE bridges this gap: a file watcher on the server detects changes, streams them to the browser, and React Query invalidates the relevant caches. This is what makes the "files as database" pattern feel real-time.
18
+
19
+ ## How It Works
20
+
21
+ 1. **Server** watches the data directory with chokidar:
22
+
23
+ ```ts
24
+ import { createFileWatcher, createSSEHandler } from "@agent-native/core";
25
+ const watcher = createFileWatcher("./data");
26
+ app.get("/api/events", createSSEHandler(watcher));
27
+ ```
28
+
29
+ 2. **Client** listens for changes and invalidates React Query caches:
30
+
31
+ ```ts
32
+ import { useFileWatcher } from "@agent-native/core";
33
+ useFileWatcher({ queryClient, queryKeys: ["files", "projects"] });
34
+ ```
35
+
36
+ 3. When the agent writes to `data/`, chokidar detects it, SSE pushes the event, and React Query refetches the affected queries.
37
+
38
+ ## Don't
39
+
40
+ - Don't poll for changes — SSE handles it
41
+ - Don't create per-model `fs.watch()` instances — `createFileWatcher("./data")` watches recursively. One watcher is enough.
42
+ - Don't create your own EventSource connections alongside `useFileWatcher` — use the `onEvent` callback for custom handling
43
+
44
+ ## Query Key Mapping
45
+
46
+ By default, `useFileWatcher` invalidates all listed query keys on every file change. For apps with multiple data models, this causes unnecessary refetches. Use path-based filtering via the `onEvent` callback:
47
+
48
+ ```ts
49
+ useFileWatcher({
50
+ queryClient,
51
+ queryKeys: [], // don't auto-invalidate everything
52
+ onEvent: (data) => {
53
+ if (data.path?.includes("projects")) {
54
+ queryClient.invalidateQueries({ queryKey: ["projects"] });
55
+ } else if (data.path?.includes("settings")) {
56
+ queryClient.invalidateQueries({ queryKey: ["settings"] });
57
+ }
58
+ },
59
+ });
60
+ ```
61
+
62
+ To prevent cache thrashing during rapid agent writes, set `staleTime` on your queries:
63
+
64
+ ```ts
65
+ useQuery({
66
+ queryKey: ["projects"],
67
+ queryFn: fetchProjects,
68
+ staleTime: 2000, // don't refetch within 2 seconds
69
+ });
70
+ ```
71
+
72
+ ## Performance
73
+
74
+ When the agent writes many files rapidly (e.g., during self-modification), each write fires a chokidar event → SSE broadcast → React Query invalidation. This can cause excessive refetching.
75
+
76
+ Mitigations:
77
+
78
+ - Use `staleTime: 2000` on React Query to debounce refetches
79
+ - Use path-based filtering (see Query Key Mapping) to limit which queries invalidate
80
+
81
+ ## Troubleshooting
82
+
83
+ | Symptom | Check |
84
+ | ---------------------------------- | --------------------------------------------------------------------------------------------------------------- |
85
+ | UI not updating after agent writes | Is `useFileWatcher` called with the correct `queryClient`? Are the `queryKeys` matching your `useQuery` keys? |
86
+ | SSE not firing | Open browser devtools → Network tab → filter by EventStream. Is `/api/events` connected? Is the server running? |
87
+ | Watcher not detecting changes | Is the path correct? `createFileWatcher("./data")` is relative to CWD. Check the server's working directory. |
88
+ | Constant reconnections | Check for server crashes in terminal output. |
89
+ | High CPU / event storms | The agent is writing many files rapidly. Add `staleTime` to queries and use path-based filtering. |
90
+
91
+ ## Related Skills
92
+
93
+ - **files-as-database** — SSE watches the data files that store application state
94
+ - **scripts** — Script outputs written to `data/` trigger SSE events
95
+ - **self-modifying-code** — Agent code edits trigger SSE events; rapid edits can cause event storms
@@ -1,68 +1,86 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Read",
5
- "Edit",
6
- "Write",
7
- "Glob",
8
- "Grep",
9
- "Bash(ls *)",
10
- "Bash(pwd)",
11
- "Bash(echo *)",
12
- "Bash(cat *)",
13
- "Bash(head *)",
14
- "Bash(tail *)",
15
- "Bash(find *)",
16
- "Bash(wc *)",
17
- "Bash(sort *)",
18
- "Bash(diff *)",
19
- "Bash(which *)",
20
- "Bash(mkdir *)",
21
- "Bash(cp *)",
22
- "Bash(mv *)",
23
- "Bash(touch *)",
24
- "Bash(node *)",
25
- "Bash(npx *)",
26
- "Bash(npm *)",
27
- "Bash(pnpm *)",
28
- "Bash(tsx *)",
29
- "Bash(tsc *)",
30
- "Bash(vitest *)",
31
- "Bash(jest *)",
32
- "Bash(eslint *)",
33
- "Bash(prettier *)",
34
- "Bash(git status*)",
35
- "Bash(git log *)",
36
- "Bash(git diff *)",
37
- "Bash(git show *)",
38
- "Bash(git branch*)",
39
- "Bash(git add *)",
40
- "Bash(git commit *)",
41
- "Bash(git checkout *)",
42
- "Bash(git switch *)",
43
- "Bash(git stash *)",
44
- "Bash(git merge *)",
45
- "Bash(git rebase *)",
46
- "Bash(git pull *)",
47
- "Bash(git blame *)",
48
- "Bash(git rev-parse *)",
49
- "Bash(git remote -v)",
50
- "Bash(chmod *)",
51
- "Bash(gh *)"
52
- ],
53
- "deny": [
54
- "Bash(rm -rf *)",
55
- "Bash(sudo *)",
56
- "Bash(git push --force *)",
57
- "Bash(git push -f *)",
58
- "Bash(git reset --hard *)",
59
- "Bash(git clean -f *)",
60
- "Bash(dd *)",
61
- "Bash(mkfs *)",
62
- "Bash(kill -9 *)",
63
- "Bash(killall *)",
64
- "Bash(shutdown *)",
65
- "Bash(reboot *)"
66
- ]
67
- }
68
- }
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Read",
5
+ "Edit",
6
+ "Write",
7
+ "Glob",
8
+ "Grep",
9
+ "NotebookEdit",
10
+ "WebFetch",
11
+ "WebSearch",
12
+ "Bash(ls *)",
13
+ "Bash(pwd)",
14
+ "Bash(echo *)",
15
+ "Bash(cat *)",
16
+ "Bash(head *)",
17
+ "Bash(tail *)",
18
+ "Bash(find *)",
19
+ "Bash(wc *)",
20
+ "Bash(sort *)",
21
+ "Bash(uniq *)",
22
+ "Bash(diff *)",
23
+ "Bash(which *)",
24
+ "Bash(env)",
25
+ "Bash(mkdir *)",
26
+ "Bash(cp *)",
27
+ "Bash(mv *)",
28
+ "Bash(touch *)",
29
+ "Bash(chmod *)",
30
+ "Bash(node *)",
31
+ "Bash(npx *)",
32
+ "Bash(npm *)",
33
+ "Bash(pnpm *)",
34
+ "Bash(yarn *)",
35
+ "Bash(tsx *)",
36
+ "Bash(tsc *)",
37
+ "Bash(vitest *)",
38
+ "Bash(jest *)",
39
+ "Bash(eslint *)",
40
+ "Bash(prettier *)",
41
+ "Bash(git status*)",
42
+ "Bash(git log *)",
43
+ "Bash(git diff *)",
44
+ "Bash(git show *)",
45
+ "Bash(git branch*)",
46
+ "Bash(git add *)",
47
+ "Bash(git commit *)",
48
+ "Bash(git checkout *)",
49
+ "Bash(git switch *)",
50
+ "Bash(git stash *)",
51
+ "Bash(git merge *)",
52
+ "Bash(git rebase *)",
53
+ "Bash(git pull *)",
54
+ "Bash(git blame *)",
55
+ "Bash(git rev-parse *)",
56
+ "Bash(git worktree *)",
57
+ "Bash(git remote -v)",
58
+ "Bash(gh *)",
59
+ "Bash(curl *)",
60
+ "Bash(grep *)",
61
+ "Bash(rg *)",
62
+ "Bash(sed *)",
63
+ "Bash(awk *)",
64
+ "Bash(jq *)",
65
+ "Bash(rm *)"
66
+ ],
67
+ "deny": [
68
+ "Bash(rm -rf /)",
69
+ "Bash(rm -rf /*)",
70
+ "Bash(rm -rf ~)",
71
+ "Bash(rm -rf ~/*)",
72
+ "Bash(sudo *)",
73
+ "Bash(git push --force *)",
74
+ "Bash(git push -f *)",
75
+ "Bash(git reset --hard *)",
76
+ "Bash(git clean -f *)",
77
+ "Bash(dd *)",
78
+ "Bash(mkfs *)",
79
+ "Bash(kill -9 *)",
80
+ "Bash(killall *)",
81
+ "Bash(pkill *)",
82
+ "Bash(shutdown *)",
83
+ "Bash(reboot *)"
84
+ ]
85
+ }
86
+ }
@@ -1,5 +1,5 @@
1
- {
2
- "tabWidth": 2,
3
- "useTabs": false,
4
- "trailingComma": "all"
5
- }
1
+ {
2
+ "tabWidth": 2,
3
+ "useTabs": false,
4
+ "trailingComma": "all"
5
+ }