create-claude-code-visualizer 0.1.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 (220) hide show
  1. package/index.js +393 -0
  2. package/package.json +31 -0
  3. package/templates/CLAUDE.md +108 -0
  4. package/templates/app/.env.local.example +14 -0
  5. package/templates/app/ecosystem.config.js +29 -0
  6. package/templates/app/next-env.d.ts +6 -0
  7. package/templates/app/next.config.ts +16 -0
  8. package/templates/app/package-lock.json +4581 -0
  9. package/templates/app/package.json +38 -0
  10. package/templates/app/postcss.config.js +5 -0
  11. package/templates/app/src/app/agents/[slug]/chat/loading.tsx +26 -0
  12. package/templates/app/src/app/agents/[slug]/chat/page.tsx +579 -0
  13. package/templates/app/src/app/agents/[slug]/loading.tsx +19 -0
  14. package/templates/app/src/app/agents/page.tsx +8 -0
  15. package/templates/app/src/app/api/agents/[slug]/capabilities/route.ts +11 -0
  16. package/templates/app/src/app/api/agents/[slug]/route.ts +57 -0
  17. package/templates/app/src/app/api/agents/route.ts +28 -0
  18. package/templates/app/src/app/api/ai/generate-agent/route.ts +87 -0
  19. package/templates/app/src/app/api/ai/improve-claude-md/route.ts +78 -0
  20. package/templates/app/src/app/api/ai/suggestions/route.ts +64 -0
  21. package/templates/app/src/app/api/ai/title/route.ts +88 -0
  22. package/templates/app/src/app/api/auth/role/route.ts +17 -0
  23. package/templates/app/src/app/api/commands/[slug]/route.ts +61 -0
  24. package/templates/app/src/app/api/commands/route.ts +6 -0
  25. package/templates/app/src/app/api/governance/costs/route.ts +117 -0
  26. package/templates/app/src/app/api/governance/sessions/route.ts +335 -0
  27. package/templates/app/src/app/api/notifications/route.ts +62 -0
  28. package/templates/app/src/app/api/preferences/route.ts +44 -0
  29. package/templates/app/src/app/api/runs/[id]/approve/route.ts +38 -0
  30. package/templates/app/src/app/api/runs/[id]/events/route.ts +28 -0
  31. package/templates/app/src/app/api/runs/[id]/metadata/route.ts +30 -0
  32. package/templates/app/src/app/api/runs/[id]/route.ts +21 -0
  33. package/templates/app/src/app/api/runs/[id]/start/route.ts +61 -0
  34. package/templates/app/src/app/api/runs/[id]/stop/route.ts +16 -0
  35. package/templates/app/src/app/api/runs/[id]/stream/route.ts +201 -0
  36. package/templates/app/src/app/api/runs/route.ts +95 -0
  37. package/templates/app/src/app/api/schedules/[id]/route.ts +81 -0
  38. package/templates/app/src/app/api/schedules/route.ts +75 -0
  39. package/templates/app/src/app/api/settings/access-logs/route.ts +33 -0
  40. package/templates/app/src/app/api/settings/claude-md/route.ts +44 -0
  41. package/templates/app/src/app/api/settings/env-keys/route.ts +271 -0
  42. package/templates/app/src/app/api/settings/users/route.ts +108 -0
  43. package/templates/app/src/app/api/skills/[slug]/route.ts +43 -0
  44. package/templates/app/src/app/api/skills/route.ts +6 -0
  45. package/templates/app/src/app/api/tools/route.ts +65 -0
  46. package/templates/app/src/app/api/uploads/cleanup/route.ts +29 -0
  47. package/templates/app/src/app/api/uploads/route.ts +77 -0
  48. package/templates/app/src/app/auth/callback/route.ts +19 -0
  49. package/templates/app/src/app/globals.css +115 -0
  50. package/templates/app/src/app/layout.tsx +24 -0
  51. package/templates/app/src/app/loading.tsx +16 -0
  52. package/templates/app/src/app/login/page.tsx +64 -0
  53. package/templates/app/src/app/not-authorized/page.tsx +33 -0
  54. package/templates/app/src/app/runs/page.tsx +55 -0
  55. package/templates/app/src/app/schedules/page.tsx +110 -0
  56. package/templates/app/src/app/settings/page.tsx +1294 -0
  57. package/templates/app/src/app/skills/page.tsx +7 -0
  58. package/templates/app/src/components/agent-card.tsx +58 -0
  59. package/templates/app/src/components/agent-grid.tsx +90 -0
  60. package/templates/app/src/components/auth/auth-context.tsx +79 -0
  61. package/templates/app/src/components/chat-thread.tsx +50 -0
  62. package/templates/app/src/components/chat-view.tsx +670 -0
  63. package/templates/app/src/components/commands-browser.tsx +349 -0
  64. package/templates/app/src/components/create-agent-modal.tsx +388 -0
  65. package/templates/app/src/components/governance-dashboard.tsx +397 -0
  66. package/templates/app/src/components/icons.tsx +401 -0
  67. package/templates/app/src/components/layout/agent-sidebar.tsx +504 -0
  68. package/templates/app/src/components/layout/app-shell.tsx +29 -0
  69. package/templates/app/src/components/layout/nav.tsx +87 -0
  70. package/templates/app/src/components/layout/overview-inner.tsx +14 -0
  71. package/templates/app/src/components/layout/profile-menu.tsx +95 -0
  72. package/templates/app/src/components/layout/sidebar.tsx +30 -0
  73. package/templates/app/src/components/markdown.tsx +57 -0
  74. package/templates/app/src/components/message-bar.tsx +161 -0
  75. package/templates/app/src/components/notifications/notification-bell.tsx +104 -0
  76. package/templates/app/src/components/notifications/notification-panel.tsx +116 -0
  77. package/templates/app/src/components/overview/overview-content.tsx +287 -0
  78. package/templates/app/src/components/overview/overview-context.tsx +88 -0
  79. package/templates/app/src/components/preferences-modal.tsx +112 -0
  80. package/templates/app/src/components/run-form.tsx +73 -0
  81. package/templates/app/src/components/run-history-table.tsx +226 -0
  82. package/templates/app/src/components/run-output.tsx +187 -0
  83. package/templates/app/src/components/schedule-form.tsx +148 -0
  84. package/templates/app/src/components/skills-browser.tsx +338 -0
  85. package/templates/app/src/components/tool-tooltip.tsx +82 -0
  86. package/templates/app/src/hooks/use-sse.ts +115 -0
  87. package/templates/app/src/instrumentation.ts +9 -0
  88. package/templates/app/src/lib/agent-cache.ts +19 -0
  89. package/templates/app/src/lib/agent-runner.ts +411 -0
  90. package/templates/app/src/lib/agents.ts +168 -0
  91. package/templates/app/src/lib/ai.ts +40 -0
  92. package/templates/app/src/lib/approval-store.ts +70 -0
  93. package/templates/app/src/lib/auth-guard.ts +116 -0
  94. package/templates/app/src/lib/capabilities.ts +191 -0
  95. package/templates/app/src/lib/line-diff.ts +96 -0
  96. package/templates/app/src/lib/queue.ts +22 -0
  97. package/templates/app/src/lib/redis.ts +12 -0
  98. package/templates/app/src/lib/role-permissions.ts +166 -0
  99. package/templates/app/src/lib/run-agent.ts +442 -0
  100. package/templates/app/src/lib/supabase-browser.ts +8 -0
  101. package/templates/app/src/lib/supabase-middleware.ts +63 -0
  102. package/templates/app/src/lib/supabase-server.ts +28 -0
  103. package/templates/app/src/lib/supabase.ts +6 -0
  104. package/templates/app/src/lib/tool-descriptions.ts +29 -0
  105. package/templates/app/src/lib/types.ts +73 -0
  106. package/templates/app/src/lib/typewriter-animation.ts +159 -0
  107. package/templates/app/src/middleware.ts +13 -0
  108. package/templates/app/tsconfig.json +21 -0
  109. package/templates/app/uploads/.gitkeep +0 -0
  110. package/templates/app/worker/index.ts +342 -0
  111. package/templates/claude/agents/ai-trends-scout.md +66 -0
  112. package/templates/claude/commands/add-to-todos.md +56 -0
  113. package/templates/claude/commands/check-todos.md +56 -0
  114. package/templates/claude/hooks/auto-approve-safe.sh +34 -0
  115. package/templates/claude/hooks/auto-format.sh +25 -0
  116. package/templates/claude/hooks/block-destructive.sh +32 -0
  117. package/templates/claude/hooks/compaction-preserver.sh +16 -0
  118. package/templates/claude/hooks/notify.sh +26 -0
  119. package/templates/claude/settings.local.json +66 -0
  120. package/templates/claude/skills/frontend-design/SKILL.md +127 -0
  121. package/templates/claude/skills/frontend-design/reference/color-and-contrast.md +132 -0
  122. package/templates/claude/skills/frontend-design/reference/interaction-design.md +123 -0
  123. package/templates/claude/skills/frontend-design/reference/motion-design.md +99 -0
  124. package/templates/claude/skills/frontend-design/reference/responsive-design.md +114 -0
  125. package/templates/claude/skills/frontend-design/reference/spatial-design.md +100 -0
  126. package/templates/claude/skills/frontend-design/reference/typography.md +131 -0
  127. package/templates/claude/skills/frontend-design/reference/ux-writing.md +107 -0
  128. package/templates/claude/skills/gws-admin-reports/SKILL.md +57 -0
  129. package/templates/claude/skills/gws-calendar/SKILL.md +108 -0
  130. package/templates/claude/skills/gws-calendar-agenda/SKILL.md +52 -0
  131. package/templates/claude/skills/gws-calendar-insert/SKILL.md +55 -0
  132. package/templates/claude/skills/gws-chat/SKILL.md +73 -0
  133. package/templates/claude/skills/gws-chat-send/SKILL.md +49 -0
  134. package/templates/claude/skills/gws-classroom/SKILL.md +75 -0
  135. package/templates/claude/skills/gws-docs/SKILL.md +48 -0
  136. package/templates/claude/skills/gws-docs-write/SKILL.md +49 -0
  137. package/templates/claude/skills/gws-drive/SKILL.md +137 -0
  138. package/templates/claude/skills/gws-drive-upload/SKILL.md +52 -0
  139. package/templates/claude/skills/gws-events/SKILL.md +67 -0
  140. package/templates/claude/skills/gws-events-renew/SKILL.md +48 -0
  141. package/templates/claude/skills/gws-events-subscribe/SKILL.md +59 -0
  142. package/templates/claude/skills/gws-forms/SKILL.md +45 -0
  143. package/templates/claude/skills/gws-gmail/SKILL.md +59 -0
  144. package/templates/claude/skills/gws-gmail-forward/SKILL.md +53 -0
  145. package/templates/claude/skills/gws-gmail-reply/SKILL.md +56 -0
  146. package/templates/claude/skills/gws-gmail-reply-all/SKILL.md +60 -0
  147. package/templates/claude/skills/gws-gmail-send/SKILL.md +55 -0
  148. package/templates/claude/skills/gws-gmail-triage/SKILL.md +50 -0
  149. package/templates/claude/skills/gws-gmail-watch/SKILL.md +58 -0
  150. package/templates/claude/skills/gws-keep/SKILL.md +48 -0
  151. package/templates/claude/skills/gws-meet/SKILL.md +51 -0
  152. package/templates/claude/skills/gws-modelarmor/SKILL.md +42 -0
  153. package/templates/claude/skills/gws-modelarmor-create-template/SKILL.md +53 -0
  154. package/templates/claude/skills/gws-modelarmor-sanitize-prompt/SKILL.md +48 -0
  155. package/templates/claude/skills/gws-modelarmor-sanitize-response/SKILL.md +48 -0
  156. package/templates/claude/skills/gws-people/SKILL.md +67 -0
  157. package/templates/claude/skills/gws-shared/SKILL.md +66 -0
  158. package/templates/claude/skills/gws-sheets/SKILL.md +53 -0
  159. package/templates/claude/skills/gws-sheets-append/SKILL.md +51 -0
  160. package/templates/claude/skills/gws-sheets-read/SKILL.md +47 -0
  161. package/templates/claude/skills/gws-slides/SKILL.md +43 -0
  162. package/templates/claude/skills/gws-tasks/SKILL.md +56 -0
  163. package/templates/claude/skills/gws-workflow/SKILL.md +44 -0
  164. package/templates/claude/skills/gws-workflow-email-to-task/SKILL.md +47 -0
  165. package/templates/claude/skills/gws-workflow-file-announce/SKILL.md +50 -0
  166. package/templates/claude/skills/gws-workflow-meeting-prep/SKILL.md +47 -0
  167. package/templates/claude/skills/gws-workflow-standup-report/SKILL.md +46 -0
  168. package/templates/claude/skills/gws-workflow-weekly-digest/SKILL.md +46 -0
  169. package/templates/claude/skills/persona-content-creator/SKILL.md +33 -0
  170. package/templates/claude/skills/persona-customer-support/SKILL.md +34 -0
  171. package/templates/claude/skills/persona-event-coordinator/SKILL.md +35 -0
  172. package/templates/claude/skills/persona-exec-assistant/SKILL.md +35 -0
  173. package/templates/claude/skills/persona-hr-coordinator/SKILL.md +33 -0
  174. package/templates/claude/skills/persona-it-admin/SKILL.md +30 -0
  175. package/templates/claude/skills/persona-project-manager/SKILL.md +35 -0
  176. package/templates/claude/skills/persona-researcher/SKILL.md +33 -0
  177. package/templates/claude/skills/persona-sales-ops/SKILL.md +35 -0
  178. package/templates/claude/skills/persona-team-lead/SKILL.md +36 -0
  179. package/templates/claude/skills/recipe-backup-sheet-as-csv/SKILL.md +25 -0
  180. package/templates/claude/skills/recipe-batch-invite-to-event/SKILL.md +25 -0
  181. package/templates/claude/skills/recipe-block-focus-time/SKILL.md +24 -0
  182. package/templates/claude/skills/recipe-bulk-download-folder/SKILL.md +25 -0
  183. package/templates/claude/skills/recipe-collect-form-responses/SKILL.md +25 -0
  184. package/templates/claude/skills/recipe-compare-sheet-tabs/SKILL.md +25 -0
  185. package/templates/claude/skills/recipe-copy-sheet-for-new-month/SKILL.md +25 -0
  186. package/templates/claude/skills/recipe-create-classroom-course/SKILL.md +25 -0
  187. package/templates/claude/skills/recipe-create-doc-from-template/SKILL.md +29 -0
  188. package/templates/claude/skills/recipe-create-events-from-sheet/SKILL.md +24 -0
  189. package/templates/claude/skills/recipe-create-expense-tracker/SKILL.md +26 -0
  190. package/templates/claude/skills/recipe-create-feedback-form/SKILL.md +25 -0
  191. package/templates/claude/skills/recipe-create-gmail-filter/SKILL.md +26 -0
  192. package/templates/claude/skills/recipe-create-meet-space/SKILL.md +25 -0
  193. package/templates/claude/skills/recipe-create-presentation/SKILL.md +25 -0
  194. package/templates/claude/skills/recipe-create-shared-drive/SKILL.md +25 -0
  195. package/templates/claude/skills/recipe-create-task-list/SKILL.md +26 -0
  196. package/templates/claude/skills/recipe-create-vacation-responder/SKILL.md +25 -0
  197. package/templates/claude/skills/recipe-draft-email-from-doc/SKILL.md +25 -0
  198. package/templates/claude/skills/recipe-email-drive-link/SKILL.md +25 -0
  199. package/templates/claude/skills/recipe-find-free-time/SKILL.md +25 -0
  200. package/templates/claude/skills/recipe-find-large-files/SKILL.md +24 -0
  201. package/templates/claude/skills/recipe-forward-labeled-emails/SKILL.md +27 -0
  202. package/templates/claude/skills/recipe-generate-report-from-sheet/SKILL.md +34 -0
  203. package/templates/claude/skills/recipe-label-and-archive-emails/SKILL.md +25 -0
  204. package/templates/claude/skills/recipe-log-deal-update/SKILL.md +25 -0
  205. package/templates/claude/skills/recipe-organize-drive-folder/SKILL.md +26 -0
  206. package/templates/claude/skills/recipe-plan-weekly-schedule/SKILL.md +26 -0
  207. package/templates/claude/skills/recipe-post-mortem-setup/SKILL.md +25 -0
  208. package/templates/claude/skills/recipe-reschedule-meeting/SKILL.md +25 -0
  209. package/templates/claude/skills/recipe-review-meet-participants/SKILL.md +25 -0
  210. package/templates/claude/skills/recipe-review-overdue-tasks/SKILL.md +25 -0
  211. package/templates/claude/skills/recipe-save-email-attachments/SKILL.md +26 -0
  212. package/templates/claude/skills/recipe-save-email-to-doc/SKILL.md +29 -0
  213. package/templates/claude/skills/recipe-schedule-recurring-event/SKILL.md +24 -0
  214. package/templates/claude/skills/recipe-send-team-announcement/SKILL.md +24 -0
  215. package/templates/claude/skills/recipe-share-doc-and-notify/SKILL.md +25 -0
  216. package/templates/claude/skills/recipe-share-event-materials/SKILL.md +25 -0
  217. package/templates/claude/skills/recipe-share-folder-with-team/SKILL.md +26 -0
  218. package/templates/claude/skills/recipe-sync-contacts-to-sheet/SKILL.md +25 -0
  219. package/templates/claude/skills/recipe-watch-drive-changes/SKILL.md +25 -0
  220. package/templates/mcp.json +12 -0
package/index.js ADDED
@@ -0,0 +1,393 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { execSync, spawnSync } = require("child_process");
6
+ const prompts = require("prompts");
7
+
8
+ const BLUE = "\x1b[34m";
9
+ const GREEN = "\x1b[32m";
10
+ const YELLOW = "\x1b[33m";
11
+ const RED = "\x1b[31m";
12
+ const NC = "\x1b[0m";
13
+
14
+ const log = (msg) => console.log(`${GREEN}[✓]${NC} ${msg}`);
15
+ const info = (msg) => console.log(`${BLUE}[→]${NC} ${msg}`);
16
+ const warn = (msg) => console.log(`${YELLOW}[!]${NC} ${msg}`);
17
+ const err = (msg) => console.log(`${RED}[✗]${NC} ${msg}`);
18
+
19
+ const TEMPLATES_DIR = path.join(__dirname, "templates");
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Helpers
23
+ // ---------------------------------------------------------------------------
24
+
25
+ function copyDir(src, dest) {
26
+ fs.mkdirSync(dest, { recursive: true });
27
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
28
+ const srcPath = path.join(src, entry.name);
29
+ const destPath = path.join(dest, entry.name);
30
+ if (entry.isDirectory()) {
31
+ copyDir(srcPath, destPath);
32
+ } else {
33
+ fs.copyFileSync(srcPath, destPath);
34
+ }
35
+ }
36
+ }
37
+
38
+ function copyIfNotExists(src, dest) {
39
+ if (!fs.existsSync(dest)) {
40
+ fs.copyFileSync(src, dest);
41
+ return true;
42
+ }
43
+ return false;
44
+ }
45
+
46
+ function copyDirAdditive(src, dest) {
47
+ fs.mkdirSync(dest, { recursive: true });
48
+ let added = 0;
49
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
50
+ const srcPath = path.join(src, entry.name);
51
+ const destPath = path.join(dest, entry.name);
52
+ if (entry.isDirectory()) {
53
+ if (!fs.existsSync(destPath)) {
54
+ copyDir(srcPath, destPath);
55
+ added++;
56
+ }
57
+ } else {
58
+ if (copyIfNotExists(srcPath, destPath)) added++;
59
+ }
60
+ }
61
+ return added;
62
+ }
63
+
64
+ function mergeJsonFile(srcPath, destPath, mergeFn) {
65
+ if (!fs.existsSync(destPath)) {
66
+ fs.copyFileSync(srcPath, destPath);
67
+ return;
68
+ }
69
+ const existing = JSON.parse(fs.readFileSync(destPath, "utf8"));
70
+ const ours = JSON.parse(fs.readFileSync(srcPath, "utf8"));
71
+ const merged = mergeFn(existing, ours);
72
+ fs.writeFileSync(destPath, JSON.stringify(merged, null, 2) + "\n");
73
+ }
74
+
75
+ function run(cmd, opts = {}) {
76
+ try {
77
+ return execSync(cmd, { stdio: "inherit", ...opts });
78
+ } catch {
79
+ return null;
80
+ }
81
+ }
82
+
83
+ function runCapture(cmd) {
84
+ try {
85
+ return execSync(cmd, { encoding: "utf8" }).trim();
86
+ } catch {
87
+ return null;
88
+ }
89
+ }
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // Main
93
+ // ---------------------------------------------------------------------------
94
+
95
+ async function main() {
96
+ console.log("");
97
+ console.log(`${BLUE}╔══════════════════════════════════════════════════╗${NC}`);
98
+ console.log(`${BLUE}║ Claude Code Visualizer — Setup ║${NC}`);
99
+ console.log(`${BLUE}╚══════════════════════════════════════════════════╝${NC}`);
100
+ console.log("");
101
+
102
+ // Determine project directory from CLI arg or prompt
103
+ let projectDir = process.argv[2];
104
+
105
+ if (!projectDir) {
106
+ const res = await prompts({
107
+ type: "text",
108
+ name: "dir",
109
+ message: "Project directory",
110
+ initial: "my-claude-visualizer",
111
+ });
112
+ if (!res.dir) process.exit(0);
113
+ projectDir = res.dir;
114
+ }
115
+
116
+ const projectRoot = path.resolve(projectDir);
117
+ const isExisting = fs.existsSync(projectRoot) && fs.existsSync(path.join(projectRoot, ".claude"));
118
+ const appDir = path.join(projectRoot, "personal-assistant-app");
119
+
120
+ if (isExisting) {
121
+ info(`Detected existing .claude/ project at ${projectRoot}`);
122
+ info("Will merge additively — your existing files always win.");
123
+ } else {
124
+ info(`Creating new project at ${projectRoot}`);
125
+ }
126
+ console.log("");
127
+
128
+ // -----------------------------------------------------------------
129
+ // Credentials
130
+ // -----------------------------------------------------------------
131
+
132
+ const creds = await prompts([
133
+ {
134
+ type: "password",
135
+ name: "anthropicKey",
136
+ message: "Anthropic API key (sk-ant-...)",
137
+ validate: (v) => v.startsWith("sk-ant-") || "Key should start with sk-ant-",
138
+ },
139
+ {
140
+ type: "text",
141
+ name: "supabaseUrl",
142
+ message: "Supabase project URL (https://xyz.supabase.co)",
143
+ },
144
+ {
145
+ type: "password",
146
+ name: "supabaseAnonKey",
147
+ message: "Supabase anon key",
148
+ },
149
+ ]);
150
+
151
+ if (!creds.anthropicKey) process.exit(0);
152
+
153
+ // -----------------------------------------------------------------
154
+ // Copy the app
155
+ // -----------------------------------------------------------------
156
+
157
+ info("Setting up project files...");
158
+
159
+ fs.mkdirSync(projectRoot, { recursive: true });
160
+
161
+ // Copy personal-assistant-app (the Next.js UI)
162
+ const appTemplate = path.join(TEMPLATES_DIR, "app");
163
+ if (fs.existsSync(appDir)) {
164
+ warn("personal-assistant-app/ already exists — updating...");
165
+ }
166
+ copyDir(appTemplate, appDir);
167
+ log("personal-assistant-app/ installed");
168
+
169
+ // -----------------------------------------------------------------
170
+ // Set up .claude/ (agents, commands, skills, hooks, settings)
171
+ // -----------------------------------------------------------------
172
+
173
+ const srcClaude = path.join(TEMPLATES_DIR, "claude");
174
+ const dstClaude = path.join(projectRoot, ".claude");
175
+
176
+ // Agents
177
+ const addedAgents = copyDirAdditive(
178
+ path.join(srcClaude, "agents"),
179
+ path.join(dstClaude, "agents")
180
+ );
181
+ log(`Agents: added ${addedAgents} new`);
182
+
183
+ // Commands
184
+ const addedCommands = copyDirAdditive(
185
+ path.join(srcClaude, "commands"),
186
+ path.join(dstClaude, "commands")
187
+ );
188
+ log(`Commands: added ${addedCommands} new`);
189
+
190
+ // Skills
191
+ const addedSkills = copyDirAdditive(
192
+ path.join(srcClaude, "skills"),
193
+ path.join(dstClaude, "skills")
194
+ );
195
+ log(`Skills: added ${addedSkills} new`);
196
+
197
+ // Hooks
198
+ fs.mkdirSync(path.join(dstClaude, "hooks"), { recursive: true });
199
+ let addedHooks = 0;
200
+ for (const hook of fs.readdirSync(path.join(srcClaude, "hooks"))) {
201
+ const src = path.join(srcClaude, "hooks", hook);
202
+ const dest = path.join(dstClaude, "hooks", hook);
203
+ if (copyIfNotExists(src, dest)) {
204
+ try { fs.chmodSync(dest, 0o755); } catch {}
205
+ addedHooks++;
206
+ }
207
+ }
208
+ log(`Hooks: added ${addedHooks} new`);
209
+
210
+ // settings.local.json — merge hooks config
211
+ mergeJsonFile(
212
+ path.join(srcClaude, "settings.local.json"),
213
+ path.join(dstClaude, "settings.local.json"),
214
+ (existing, ours) => {
215
+ // Merge hooks: add our hook events if they don't already exist
216
+ const mergedHooks = { ...(ours.hooks || {}) };
217
+ for (const [event, hooks] of Object.entries(existing.hooks || {})) {
218
+ mergedHooks[event] = hooks; // existing wins
219
+ }
220
+ return {
221
+ ...existing,
222
+ enableAllProjectMcpServers:
223
+ existing.enableAllProjectMcpServers ?? ours.enableAllProjectMcpServers,
224
+ hooks: mergedHooks,
225
+ };
226
+ }
227
+ );
228
+ log("settings.local.json configured");
229
+
230
+ // .mcp.json — merge servers
231
+ mergeJsonFile(
232
+ path.join(TEMPLATES_DIR, "mcp.json"),
233
+ path.join(projectRoot, ".mcp.json"),
234
+ (existing, ours) => ({
235
+ mcpServers: { ...(ours.mcpServers || {}), ...(existing.mcpServers || {}) },
236
+ })
237
+ );
238
+ log(".mcp.json configured");
239
+
240
+ // CLAUDE.md
241
+ const claudeMdDest = path.join(projectRoot, "CLAUDE.md");
242
+ if (copyIfNotExists(path.join(TEMPLATES_DIR, "CLAUDE.md"), claudeMdDest)) {
243
+ log("CLAUDE.md created");
244
+ } else {
245
+ log("CLAUDE.md exists — keeping yours");
246
+ }
247
+
248
+ // -----------------------------------------------------------------
249
+ // Write .env.local
250
+ // -----------------------------------------------------------------
251
+
252
+ const envContent = `# Generated by create-personalai — ${new Date().toISOString()}
253
+ ANTHROPIC_API_KEY=${creds.anthropicKey}
254
+ NEXT_PUBLIC_SUPABASE_URL=${creds.supabaseUrl}
255
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=${creds.supabaseAnonKey}
256
+ SUPABASE_URL=${creds.supabaseUrl}
257
+ SUPABASE_ANON_KEY=${creds.supabaseAnonKey}
258
+ REDIS_URL=redis://localhost:6379
259
+ PROJECT_ROOT=${projectRoot}
260
+ `;
261
+
262
+ fs.writeFileSync(path.join(appDir, ".env.local"), envContent, { mode: 0o600 });
263
+ log(".env.local created");
264
+
265
+ // Add Supabase MCP server if we have a URL
266
+ const supabaseMatch = (creds.supabaseUrl || "").match(
267
+ /https:\/\/([^.]+)\.supabase\.co/
268
+ );
269
+ if (supabaseMatch) {
270
+ const ref = supabaseMatch[1];
271
+ const mcpPath = path.join(projectRoot, ".mcp.json");
272
+ const mcp = JSON.parse(fs.readFileSync(mcpPath, "utf8"));
273
+ mcp.mcpServers.supabase = {
274
+ type: "http",
275
+ url: `https://mcp.supabase.com/mcp?project_ref=${ref}`,
276
+ };
277
+ fs.writeFileSync(mcpPath, JSON.stringify(mcp, null, 2) + "\n");
278
+ log("Supabase MCP server added");
279
+ }
280
+
281
+ // -----------------------------------------------------------------
282
+ // npm install
283
+ // -----------------------------------------------------------------
284
+
285
+ info("Installing dependencies...");
286
+ run("npm install", { cwd: appDir });
287
+ log("Dependencies installed");
288
+
289
+ // -----------------------------------------------------------------
290
+ // Google Workspace (optional)
291
+ // -----------------------------------------------------------------
292
+
293
+ console.log("");
294
+ const { setupGws } = await prompts({
295
+ type: "confirm",
296
+ name: "setupGws",
297
+ message: "Set up Google Workspace integration? (Gmail, Calendar, Drive, etc.)",
298
+ initial: false,
299
+ });
300
+
301
+ if (setupGws) {
302
+ console.log("");
303
+ info("Installing Google Workspace CLI...");
304
+ run("npm install @anthropic-ai/claude-code-google-workspace", { cwd: projectRoot });
305
+
306
+ // Check if gws auth is needed
307
+ const hasAuth = runCapture("npx gws auth status");
308
+ if (!hasAuth) {
309
+ console.log("");
310
+ const { gwsAuth } = await prompts({
311
+ type: "select",
312
+ name: "gwsAuth",
313
+ message: "Google Workspace authentication",
314
+ choices: [
315
+ { title: "Full setup (creates GCP project + OAuth)", value: "setup" },
316
+ { title: "Login only (you already have OAuth configured)", value: "login" },
317
+ { title: "Skip for now", value: "skip" },
318
+ ],
319
+ });
320
+
321
+ if (gwsAuth === "setup") {
322
+ run("npx gws auth setup --login", { cwd: projectRoot });
323
+ } else if (gwsAuth === "login") {
324
+ run("npx gws auth login", { cwd: projectRoot });
325
+ } else {
326
+ info("Skipping auth. Run later: npx gws auth setup --login");
327
+ }
328
+ } else {
329
+ log("Already authenticated with Google Workspace");
330
+ }
331
+
332
+ // Install GWS skills
333
+ console.log("");
334
+ const { installSkills } = await prompts({
335
+ type: "confirm",
336
+ name: "installSkills",
337
+ message: "Install Google Workspace skills? (lets agents use Gmail, Calendar, etc.)",
338
+ initial: true,
339
+ });
340
+
341
+ if (installSkills) {
342
+ run("npx skills add https://github.com/googleworkspace/cli", { cwd: projectRoot });
343
+ }
344
+
345
+ // Add gws permission to settings
346
+ const settingsPath = path.join(dstClaude, "settings.local.json");
347
+ const settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
348
+ if (!JSON.stringify(settings).includes("npx gws")) {
349
+ settings.permissions = settings.permissions || {};
350
+ settings.permissions.allow = settings.permissions.allow || [];
351
+ settings.permissions.allow.push("Bash(npx gws:*)");
352
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
353
+ log("Added gws permission to settings");
354
+ }
355
+
356
+ log("Google Workspace setup complete");
357
+ }
358
+
359
+ // -----------------------------------------------------------------
360
+ // Done
361
+ // -----------------------------------------------------------------
362
+
363
+ console.log("");
364
+ console.log(`${GREEN}╔══════════════════════════════════════════════════╗${NC}`);
365
+ console.log(`${GREEN}║ Setup Complete! ║${NC}`);
366
+ console.log(`${GREEN}╚══════════════════════════════════════════════════╝${NC}`);
367
+ console.log("");
368
+
369
+ log(`Project created at: ${projectRoot}`);
370
+ console.log("");
371
+ info("To get started:");
372
+ console.log("");
373
+ console.log(` cd ${projectDir}/personal-assistant-app`);
374
+ console.log(" redis-server & # Start Redis (needed for job queue)");
375
+ console.log(" npm run dev:all # Start the app + worker");
376
+ console.log("");
377
+ info("Then open http://localhost:3000");
378
+ console.log("");
379
+
380
+ if (!setupGws) {
381
+ info("To add Google Workspace later:");
382
+ console.log(` cd ${projectDir}`);
383
+ console.log(" npm install @anthropic-ai/claude-code-google-workspace");
384
+ console.log(" npx gws auth setup --login");
385
+ console.log(" npx skills add https://github.com/googleworkspace/cli");
386
+ console.log("");
387
+ }
388
+ }
389
+
390
+ main().catch((e) => {
391
+ err(e.message);
392
+ process.exit(1);
393
+ });
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "create-claude-code-visualizer",
3
+ "version": "0.1.0",
4
+ "description": "Run and manage Claude Code agents through a web UI",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "create-claude-code-visualizer": "./index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "templates/**"
12
+ ],
13
+ "scripts": {
14
+ "prepare-templates": "node prepare-templates.js",
15
+ "prepublishOnly": "node prepare-templates.js"
16
+ },
17
+ "dependencies": {
18
+ "prompts": "^2.4.2"
19
+ },
20
+ "engines": {
21
+ "node": ">=18"
22
+ },
23
+ "keywords": [
24
+ "claude",
25
+ "ai",
26
+ "assistant",
27
+ "agents",
28
+ "claude-code",
29
+ "create"
30
+ ]
31
+ }
@@ -0,0 +1,108 @@
1
+ # PersonalAIssistant
2
+
3
+ ## Identity
4
+
5
+ You are the user's personal AI assistant. You have full access to every tool, MCP server, skill, and subagent in this workspace. Handle tasks directly when you can, delegate to specialized subagents when their expertise produces better results.
6
+
7
+ ## Architecture
8
+
9
+ This project is a personal assistant platform built on Claude Code. It consists of:
10
+
11
+ - **personal-assistant-app/** — A Next.js 15 frontend for managing and running AI agents
12
+ - **.claude/** — Claude Code configuration (agents, skills, commands, hooks)
13
+ - **assets/** — Static assets (fonts, images, documents)
14
+
15
+ ## MCP Servers (auto-loaded from .mcp.json)
16
+
17
+ - **Chrome DevTools** (`mcp__chrome-devtools__*`) — Browser debugging, screenshots, DOM inspection
18
+
19
+ Add more MCP servers by editing `.mcp.json` at the project root.
20
+
21
+ ## Creating Agents
22
+
23
+ Agents live in `.claude/agents/*.md`. Each agent has YAML frontmatter + markdown instructions:
24
+
25
+ ```yaml
26
+ ---
27
+ name: Agent Name
28
+ description: What this agent does
29
+ tools: 'WebSearch, WebFetch, Read'
30
+ color: '#8B5CF6'
31
+ emoji: "\U0001F52E"
32
+ vibe: Short tagline
33
+ ---
34
+ # Agent instructions here...
35
+ ```
36
+
37
+ The frontend auto-discovers agents from this directory.
38
+
39
+ ## Creating Skills
40
+
41
+ Skills live in `.claude/skills/*/SKILL.md`. Each skill directory contains a `SKILL.md` with frontmatter:
42
+
43
+ ```yaml
44
+ ---
45
+ name: skill-name
46
+ description: What this skill does
47
+ ---
48
+ Skill instructions here...
49
+ ```
50
+
51
+ ## Creating Commands
52
+
53
+ Commands live in `.claude/commands/*.md`. They become available as `/command-name` in Claude Code:
54
+
55
+ ```yaml
56
+ ---
57
+ description: What this command does
58
+ allowed-tools:
59
+ - Read
60
+ - Edit
61
+ ---
62
+ Command instructions here...
63
+ ```
64
+
65
+ ## Hooks (automatic, no action needed)
66
+
67
+ Hooks fire automatically — do not invoke them manually:
68
+ - `block-destructive.sh` — Blocks dangerous bash commands (rm -rf, git reset --hard, etc.)
69
+ - `auto-approve-safe.sh` — Auto-approves safe read-only commands (ls, git status, etc.)
70
+ - `auto-format.sh` — Auto-formats code after edits (prettier for JS/TS, ruff for Python)
71
+ - `compaction-preserver.sh` — Preserves critical context during session compaction
72
+ - `notify.sh` — Desktop notifications when Claude needs attention
73
+
74
+ ## Frontend Development
75
+
76
+ ### Screenshot Feedback Loop
77
+
78
+ After generating frontend code, close the loop:
79
+ 1. Take a screenshot with Chrome DevTools MCP (`take_screenshot`)
80
+ 2. Check console for errors (`list_console_messages`)
81
+ 3. If the design looks generic or has issues, fix and re-screenshot
82
+ 4. Only report done after visual verification
83
+
84
+ ## Running the App
85
+
86
+ ```bash
87
+ # Prerequisites: Node.js 18+, Redis server
88
+
89
+ # 1. Install dependencies
90
+ cd personal-assistant-app && npm install
91
+
92
+ # 2. Copy and fill in environment variables
93
+ cp .env.local.example .env.local
94
+ # Edit .env.local with your Supabase + Anthropic keys
95
+
96
+ # 3. Start Redis (required for BullMQ job queue)
97
+ redis-server
98
+
99
+ # 4. Start the app + worker
100
+ npm run dev:all
101
+ ```
102
+
103
+ The app runs at http://localhost:3000.
104
+
105
+ ## Session Continuity
106
+
107
+ - `/add-to-todos` — Capture tasks mid-work without breaking flow
108
+ - `/check-todos` — Review and pick up saved todos
@@ -0,0 +1,14 @@
1
+ # Supabase — create a project at https://supabase.com
2
+ NEXT_PUBLIC_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
3
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
4
+ SUPABASE_URL=https://YOUR_PROJECT.supabase.co
5
+ SUPABASE_ANON_KEY=your-anon-key
6
+
7
+ # Anthropic — get your key at https://console.anthropic.com
8
+ ANTHROPIC_API_KEY=sk-ant-api03-...
9
+
10
+ # Redis — used by BullMQ for agent job queues
11
+ REDIS_URL=redis://localhost:6379
12
+
13
+ # Project root — absolute path to this repo on your machine
14
+ PROJECT_ROOT=/path/to/PersonalAIssistantBase
@@ -0,0 +1,29 @@
1
+ module.exports = {
2
+ apps: [
3
+ {
4
+ name: "personalai-web",
5
+ script: "npm",
6
+ args: "start",
7
+ cwd: __dirname,
8
+ env: {
9
+ NODE_ENV: "production",
10
+ PORT: 3000,
11
+ },
12
+ max_memory_restart: "512M",
13
+ restart_delay: 5000,
14
+ max_restarts: 10,
15
+ },
16
+ {
17
+ name: "personalai-worker",
18
+ script: "npm",
19
+ args: "run start:worker",
20
+ cwd: __dirname,
21
+ env: {
22
+ NODE_ENV: "production",
23
+ },
24
+ max_memory_restart: "1G",
25
+ restart_delay: 5000,
26
+ max_restarts: 10,
27
+ },
28
+ ],
29
+ };
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ /// <reference path="./.next/types/routes.d.ts" />
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -0,0 +1,16 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ const nextConfig: NextConfig = {
4
+ devIndicators: false,
5
+ serverExternalPackages: ["@anthropic-ai/claude-agent-sdk", "ioredis", "bullmq"],
6
+ async rewrites() {
7
+ return [
8
+ {
9
+ source: "/",
10
+ destination: "/agents/main/chat",
11
+ },
12
+ ];
13
+ },
14
+ };
15
+
16
+ export default nextConfig;