showpane 0.4.14 → 0.4.16

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 (43) hide show
  1. package/bundle/meta/scaffold-manifest.json +8 -8
  2. package/bundle/scaffold/VERSION +1 -1
  3. package/bundle/scaffold/prisma/seed.ts +40 -35
  4. package/bundle/scaffold/src/app/(portal)/client/example/example-client.tsx +1 -2
  5. package/bundle/scaffold/src/app/(portal)/client/page.tsx +5 -4
  6. package/bundle/scaffold/src/app/page.tsx +2 -2
  7. package/bundle/scaffold/src/components/portal-shell.tsx +1 -1
  8. package/bundle/toolchain/CLI_VERSION +1 -1
  9. package/bundle/toolchain/VERSION +1 -1
  10. package/bundle/toolchain/skills/VERSION +1 -1
  11. package/bundle/toolchain/skills/portal-analytics/SKILL.md +9 -12
  12. package/bundle/toolchain/skills/portal-analytics/SKILL.md.tmpl +4 -4
  13. package/bundle/toolchain/skills/portal-create/SKILL.md +13 -16
  14. package/bundle/toolchain/skills/portal-create/SKILL.md.tmpl +8 -8
  15. package/bundle/toolchain/skills/portal-credentials/SKILL.md +15 -18
  16. package/bundle/toolchain/skills/portal-credentials/SKILL.md.tmpl +10 -10
  17. package/bundle/toolchain/skills/portal-delete/SKILL.md +14 -17
  18. package/bundle/toolchain/skills/portal-delete/SKILL.md.tmpl +9 -9
  19. package/bundle/toolchain/skills/portal-deploy/SKILL.md +5 -8
  20. package/bundle/toolchain/skills/portal-dev/SKILL.md +10 -13
  21. package/bundle/toolchain/skills/portal-dev/SKILL.md.tmpl +5 -5
  22. package/bundle/toolchain/skills/portal-list/SKILL.md +15 -18
  23. package/bundle/toolchain/skills/portal-list/SKILL.md.tmpl +10 -10
  24. package/bundle/toolchain/skills/portal-onboard/SKILL.md +50 -30
  25. package/bundle/toolchain/skills/portal-onboard/SKILL.md.tmpl +46 -23
  26. package/bundle/toolchain/skills/portal-preview/SKILL.md +16 -19
  27. package/bundle/toolchain/skills/portal-preview/SKILL.md.tmpl +11 -11
  28. package/bundle/toolchain/skills/portal-setup/SKILL.md +15 -13
  29. package/bundle/toolchain/skills/portal-setup/SKILL.md.tmpl +11 -6
  30. package/bundle/toolchain/skills/portal-share/SKILL.md +17 -20
  31. package/bundle/toolchain/skills/portal-share/SKILL.md.tmpl +12 -12
  32. package/bundle/toolchain/skills/portal-status/SKILL.md +9 -12
  33. package/bundle/toolchain/skills/portal-status/SKILL.md.tmpl +4 -4
  34. package/bundle/toolchain/skills/portal-update/SKILL.md +9 -12
  35. package/bundle/toolchain/skills/portal-update/SKILL.md.tmpl +4 -4
  36. package/bundle/toolchain/skills/portal-upgrade/SKILL.md +6 -9
  37. package/bundle/toolchain/skills/portal-upgrade/SKILL.md.tmpl +1 -1
  38. package/bundle/toolchain/skills/portal-verify/SKILL.md +6 -9
  39. package/bundle/toolchain/skills/portal-verify/SKILL.md.tmpl +1 -1
  40. package/bundle/toolchain/skills/shared/runtime-principles.md +4 -4
  41. package/bundle/toolchain/templates/sales-followup/sales-followup-client.tsx +1 -1
  42. package/dist/index.js +28 -5
  43. package/package.json +3 -3
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-04-10T15:24:11.197Z",
4
- "scaffoldVersion": "0.2.5",
3
+ "generatedAt": "2026-04-11T21:51:10.517Z",
4
+ "scaffoldVersion": "0.2.6",
5
5
  "files": {
6
6
  ".env.example": "ed105f2bdcd1888a98181d55e3c9f7d6eff3ae9c3e2366c2e777a12e3caddfa7",
7
7
  ".gitignore": "998e5f43865ea56ac79a05acfd5d4b0d696f310bd5325a1ed458c3d40154d437",
8
- "VERSION": "e959f750e92dbb7614ae28ac96f0a37272caed81d8bbb758791af7bfbb6106a0",
8
+ "VERSION": "be3c6d2c6c406a64d44f0b6464a887e290416dd90c524094485b1be00936d6d7",
9
9
  "next.config.ts": "cf27999cc274cce79bc4c8df11789807719abf40752b60e4b4967a3d2f0ed013",
10
10
  "package-lock.json": "d8e30eb86f08e70787d4459a084b4ab2a9f119696bbd3146ec4ba5675fffd3c2",
11
11
  "package.json": "b095e17e7fc181c630e87fe9f473c5a4ef969afcd4b110f9f9c6d6a6d93f1c0b",
12
12
  "postcss.config.js": "fa650b380adfabb151a0b352f7135e107e6352345f899060f1c5c231228f94bf",
13
13
  "prisma.config.ts": "36f56fd74eae70632e484443e38d08665158d72d5c978dc456651d8d5e1a636e",
14
14
  "prisma/schema.local.prisma": "f5d6f3cb17d6d229f46ef82eef7c0ff4261596924f0173fef075ac394f423073",
15
- "prisma/seed.ts": "398b645c31ea0d5b0291f27c32aded22bdb64021e581a547e85b3cccca65c551",
15
+ "prisma/seed.ts": "bb8eb3bc189fabbab3be83d3909afee583a5b724d258139feda22af504bed134",
16
16
  "public/example-avatar.svg": "0edeb0d3fbefa89cc27ffe6564d20e3ee0fd073cb6d9f2a025248ef3b3f277fd",
17
17
  "public/example-logo.svg": "bc5cd933aff2a17698dee66a7b4ea940ad12238e9d813474d643b459b1e8d6da",
18
18
  "public/robots.txt": "331ea9090db0c9f6f597bd9840fd5b171830f6e0b3ba1cb24dfa91f0c95aedc1",
@@ -24,10 +24,10 @@
24
24
  "src/__tests__/portal-contracts.test.ts": "9562b67f84f528ee0bb0bc4c0225adaf1dcc38c59b7629bda7c44e374a020eac",
25
25
  "src/app/(portal)/client/[slug]/page.tsx": "4f2f9253b2ad5d37a0f13759db52c786ae9c401f50fae9431da1417e9736e000",
26
26
  "src/app/(portal)/client/[slug]/s/[token]/route.ts": "a445e54b9139e40dfe0bc039e34e6af224a27f75a614741ab224d317ad4d3ec9",
27
- "src/app/(portal)/client/example/example-client.tsx": "b9b744f0358b7773f319757157598fc69059eb38e0eaa1c09cb5fc10cfc3894b",
27
+ "src/app/(portal)/client/example/example-client.tsx": "ed32b111acea861f448d865338f8841d47c6ca7c2f87ed30d85bb0804940d4ec",
28
28
  "src/app/(portal)/client/example/page.tsx": "f330864f63c9feea76c8a62c3eba3ce57578627e0d4abd929fd7fefdfc7af058",
29
29
  "src/app/(portal)/client/layout.tsx": "4f43871510408a81da229d48ae316ec1d1c1beda93121922246300a2c8fd0999",
30
- "src/app/(portal)/client/page.tsx": "af36f1a6f359d6a7bd4a6ac550058c9d9c107e9885bb238b4c06ec26700e23e3",
30
+ "src/app/(portal)/client/page.tsx": "7b4e3e5b286672f83581e24349e98ac930d8bbf5dfed02793754be2ddadf430f",
31
31
  "src/app/api/client-auth/route.ts": "ce1858559b1e944d5b1dc719d1f03bebf66286671700b1b5397382109f0f1e0d",
32
32
  "src/app/api/client-auth/share/route.ts": "ed82414212dcd26af8c6c0f2bd44d9d79a727ed35cfedbac8c4077a6220aad14",
33
33
  "src/app/api/client-events/route.ts": "13d545537b7e8ce421e6169d25c105adf2a2de3d978ae0a2c6751ff5f7d2eb33",
@@ -38,10 +38,10 @@
38
38
  "src/app/api/health/route.ts": "78fff55707372ce0cd6e9e49ef4f049622bc43cc42916d3f83e0162409d678b1",
39
39
  "src/app/globals.css": "28dcda76006d0e6af01b6dcf1a315dc5b5b6931c880fc53fd6565ff09d5dd13a",
40
40
  "src/app/layout.tsx": "c17aabeb2b486f023e777230343ace6cc06840f641a10b9dd9f65e092018f82f",
41
- "src/app/page.tsx": "ef5a6cb28d4f364ca94306736e250da2d25a4076d9cf4bee621bacf03ec87f0b",
41
+ "src/app/page.tsx": "1f71205c3ae30bf6929d37947b0c94ae53aed33b6689b7d6b13066ad51c1bc14",
42
42
  "src/components/copy-button.tsx": "2f3d1d8a6a0a570c8d78e19c3c15519c44af17b5d8893ae5a5f57db5ecce7077",
43
43
  "src/components/portal-login.tsx": "8b0d91bb28674e1102fd2e5b5ddcc3a93755dd806fbd3d1b2dbea2646cffca5e",
44
- "src/components/portal-shell.tsx": "6b90b1ca0bd8ba0762a03411e1103190085c7b138cf30362e412832e888f9d01",
44
+ "src/components/portal-shell.tsx": "f46a0f753a4a0318f06c8b4e46295febb84b03ea082c95057a6da50c737b4e21",
45
45
  "src/lib/abuse-controls.ts": "d79d58d93267aca48ad0b7b9b91f753c9a3c27263e4e98daf768a950c44a6fc6",
46
46
  "src/lib/branding.ts": "cc55f40e02bc3e486b227988f95739ca1cda8012c97b591295995eb4465efd57",
47
47
  "src/lib/client-auth.ts": "b9bdfe77dbe5d6ec6c6a930627fc43d3253f0d76fd8fc4093af5a75742bebe42",
@@ -1 +1 @@
1
- 0.2.5
1
+ 0.2.6
@@ -1,49 +1,54 @@
1
1
  import { PrismaClient } from "@/lib/prisma-client";
2
- import bcrypt from "bcryptjs";
3
2
 
4
3
  const prisma = new PrismaClient();
5
4
 
5
+ function normalizeSlug(value: string): string {
6
+ return value
7
+ .toLowerCase()
8
+ .trim()
9
+ .replace(/[^a-z0-9\s-]/g, "")
10
+ .replace(/\s+/g, "-")
11
+ .replace(/-+/g, "-")
12
+ .replace(/^-|-$/g, "");
13
+ }
14
+
15
+ function normalizeWebsiteUrl(value: string | undefined): string | null {
16
+ if (!value) return null;
17
+ const trimmed = value.trim();
18
+ if (!trimmed) return null;
19
+ return trimmed.startsWith("http://") || trimmed.startsWith("https://")
20
+ ? trimmed
21
+ : `https://${trimmed}`;
22
+ }
23
+
6
24
  async function main() {
7
- const org = await prisma.organization.upsert({
8
- where: { slug: "demo" },
9
- update: {},
10
- create: {
11
- name: "Demo Company",
12
- slug: "demo",
13
- contactName: "Jane Smith",
14
- contactTitle: "Account Manager",
15
- contactEmail: "jane@example.com",
16
- supportEmail: "support@example.com",
17
- websiteUrl: "https://example.com",
18
- },
19
- });
25
+ const organizationName = process.env.SHOWPANE_ORG_NAME?.trim();
26
+ if (!organizationName) {
27
+ console.log("Seed skipped: no organization details provided");
28
+ return;
29
+ }
20
30
 
21
- const passwordHash = await bcrypt.hash("demo-only-password", 10);
31
+ const organizationSlug =
32
+ process.env.SHOWPANE_ORG_SLUG?.trim() || normalizeSlug(organizationName);
33
+ const contactName = process.env.SHOWPANE_CONTACT_NAME?.trim() || null;
34
+ const contactEmail = process.env.SHOWPANE_CONTACT_EMAIL?.trim() || null;
35
+ const websiteUrl = normalizeWebsiteUrl(process.env.SHOWPANE_WEBSITE_URL);
22
36
 
23
- await prisma.clientPortal.upsert({
24
- where: {
25
- organizationId_slug: {
26
- organizationId: org.id,
27
- slug: "example",
28
- },
29
- },
30
- update: {
31
- companyName: "Acme Health",
32
- username: "example",
33
- passwordHash,
34
- lastUpdated: "2 April 2026",
35
- },
37
+ const org = await prisma.organization.upsert({
38
+ where: { slug: organizationSlug },
39
+ update: {},
36
40
  create: {
37
- organizationId: org.id,
38
- slug: "example",
39
- companyName: "Acme Health",
40
- username: "example",
41
- passwordHash,
42
- lastUpdated: "2 April 2026",
41
+ name: organizationName,
42
+ slug: organizationSlug,
43
+ contactName,
44
+ contactTitle: null,
45
+ contactEmail,
46
+ supportEmail: contactEmail,
47
+ websiteUrl,
43
48
  },
44
49
  });
45
50
 
46
- console.log("Seed complete: org 'demo', portal 'example' (username: example, password: demo-only-password)");
51
+ console.log(`Seed complete: org '${org.slug}'`);
47
52
  }
48
53
 
49
54
  main()
@@ -1,9 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  /**
4
- * Reference portal — the /portal create skill reads this file as the quality
4
+ * Reference portal — the /portal-create skill reads this file as the quality
5
5
  * and style guide when generating new portals. Keep it polished.
6
- * Login: username "example", password "demo-only-password" (seeded by prisma/seed.ts)
7
6
  */
8
7
 
9
8
  import { type ReactNode } from "react";
@@ -5,14 +5,15 @@ import { PortalLogin } from "@/components/portal-login";
5
5
  export default function ClientLogin() {
6
6
  return (
7
7
  <PortalLogin
8
- companyName="Demo Company"
8
+ companyName="Your Portal"
9
9
  companyLogo={
10
10
  <div className="flex h-7 w-7 items-center justify-center rounded-lg bg-gray-900">
11
- <span className="text-xs font-bold text-white">D</span>
11
+ <span className="text-xs font-bold text-white">P</span>
12
12
  </div>
13
13
  }
14
- companyUrl="https://example.com"
15
- supportEmail="support@example.com"
14
+ companyUrl="https://showpane.com"
15
+ supportEmail="support@showpane.com"
16
+ description="Private portal access. Sign in with the credentials you were sent."
16
17
  />
17
18
  );
18
19
  }
@@ -118,10 +118,10 @@ export default async function Home() {
118
118
  Recommended
119
119
  </p>
120
120
  <p className="mt-3 font-mono text-sm leading-6 text-slate-700">
121
- /portal onboard
121
+ /portal-onboard
122
122
  </p>
123
123
  </div>
124
- <CopyButton text="/portal onboard" />
124
+ <CopyButton text="/portal-onboard" />
125
125
  </div>
126
126
  </section>
127
127
 
@@ -248,7 +248,7 @@ export function PortalShell({
248
248
  <span>
249
249
  This portal is local only. Tell Claude{" "}
250
250
  <code className="rounded bg-white px-1.5 py-0.5 font-mono text-[11px] text-amber-950 sm:text-xs">
251
- /portal deploy
251
+ /portal-deploy
252
252
  </code>{" "}
253
253
  to publish it to Showpane Cloud.
254
254
  </span>
@@ -1 +1 @@
1
- 0.4.14
1
+ 0.4.16
@@ -1 +1 @@
1
- 1.1.5 (requires app >= 0.2.5)
1
+ 1.1.6 (requires app >= 0.2.6)
@@ -1 +1 @@
1
- 1.1.5 (requires app >= 0.2.5)
1
+ 1.1.6 (requires app >= 0.2.6)
@@ -15,7 +15,7 @@ SHOWPANE_HOME="$HOME/.showpane"
15
15
  SHOWPANE_BIN="$SHOWPANE_HOME/bin"
16
16
  CONFIG="$SHOWPANE_HOME/config.json"
17
17
  if [ ! -f "$CONFIG" ]; then
18
- echo "Showpane not configured. Run /portal setup first."
18
+ echo "Showpane not configured. Run /portal-setup first."
19
19
  exit 1
20
20
  fi
21
21
 
@@ -68,16 +68,13 @@ echo "TEL_PROMPTED: $TEL_PROMPTED"
68
68
 
69
69
  If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
70
70
 
71
- If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal upgrade`.
71
+ If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
72
72
 
73
- If `TEL_PROMPTED` is `no`, ask the user once about telemetry and then record the decision:
73
+ If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
74
74
 
75
- - anonymous — local analytics plus anonymous remote sync, with no stable device id
76
- - off — local analytics only, no remote sync
77
-
78
- After the user chooses, run:
75
+ Run:
79
76
  ```bash
80
- "$SHOWPANE_BIN/showpane-config" set telemetry <anonymous|off>
77
+ "$SHOWPANE_BIN/showpane-config" set telemetry anonymous
81
78
  touch "$SHOWPANE_HOME/.telemetry-prompted"
82
79
  ```
83
80
 
@@ -147,7 +144,7 @@ For all portals, the response includes a `portals` array with the same fields pe
147
144
 
148
145
  If the script exits with a non-zero code, read stderr for the error JSON. Common errors:
149
146
 
150
- - `portal_not_found`: The slug does not exist in this organization. Suggest running `/portal list` to see available portals.
147
+ - `portal_not_found`: The slug does not exist in this organization. Suggest running `/portal-list` to see available portals.
151
148
  - `no_analytics_data`: The portal exists but has zero recorded events. This is normal for brand-new portals.
152
149
 
153
150
  ### Step 3: Format the output as an ASCII table
@@ -251,7 +248,7 @@ A portal with zero views is not necessarily a problem. Context matters:
251
248
  - **New portal (created in last 7 days)**: Zero views is expected if the hosted portal has not been sent yet. Note: "Portal was created recently. Publish it first, then share hosted access with the client to start tracking engagement."
252
249
  - **Portal with credentials but no views**: The client may not have received the hosted portal yet, or the email landed in spam. Suggest: "Credentials exist but no one has logged in. Consider publishing first or resending the hosted portal details."
253
250
  - **Portal that previously had views but now has zero**: The client relationship may have gone cold. This is the most actionable signal -- suggest a follow-up.
254
- - **Portal with credentials and share link but no views**: The client may not have used the hosted link yet, or it may have been buried in email. Suggest resending the hosted link with `/portal share`.
251
+ - **Portal with credentials and share link but no views**: The client may not have used the hosted link yet, or it may have been buried in email. Suggest resending the hosted link with `/portal-share`.
255
252
 
256
253
  ## Telemetry
257
254
 
@@ -265,8 +262,8 @@ If telemetry is enabled, the analytics skill records a minimal event after each
265
262
 
266
263
  - If the preamble fails (no config, no Prisma), stop and show the error. Do not attempt to query analytics.
267
264
  - If `query-analytics.ts` returns a non-zero exit code, display the error message from stderr and suggest a fix.
268
- - If DATABASE_URL is empty, tell the user: "No database configured. Run /portal setup to connect your database."
269
- - If the analytics query times out (large dataset), suggest narrowing the period: "Query took too long. Try a shorter period: /portal analytics whzan --period 7d"
265
+ - If DATABASE_URL is empty, tell the user: "No database configured. Run /portal-setup to connect your database."
266
+ - If the analytics query times out (large dataset), suggest narrowing the period: "Query took too long. Try a shorter period: /portal-analytics whzan --period 7d"
270
267
 
271
268
  ## Learnings Integration
272
269
 
@@ -60,7 +60,7 @@ For all portals, the response includes a `portals` array with the same fields pe
60
60
 
61
61
  If the script exits with a non-zero code, read stderr for the error JSON. Common errors:
62
62
 
63
- - `portal_not_found`: The slug does not exist in this organization. Suggest running `/portal list` to see available portals.
63
+ - `portal_not_found`: The slug does not exist in this organization. Suggest running `/portal-list` to see available portals.
64
64
  - `no_analytics_data`: The portal exists but has zero recorded events. This is normal for brand-new portals.
65
65
 
66
66
  ### Step 3: Format the output as an ASCII table
@@ -164,7 +164,7 @@ A portal with zero views is not necessarily a problem. Context matters:
164
164
  - **New portal (created in last 7 days)**: Zero views is expected if the hosted portal has not been sent yet. Note: "Portal was created recently. Publish it first, then share hosted access with the client to start tracking engagement."
165
165
  - **Portal with credentials but no views**: The client may not have received the hosted portal yet, or the email landed in spam. Suggest: "Credentials exist but no one has logged in. Consider publishing first or resending the hosted portal details."
166
166
  - **Portal that previously had views but now has zero**: The client relationship may have gone cold. This is the most actionable signal -- suggest a follow-up.
167
- - **Portal with credentials and share link but no views**: The client may not have used the hosted link yet, or it may have been buried in email. Suggest resending the hosted link with `/portal share`.
167
+ - **Portal with credentials and share link but no views**: The client may not have used the hosted link yet, or it may have been buried in email. Suggest resending the hosted link with `/portal-share`.
168
168
 
169
169
  ## Telemetry
170
170
 
@@ -178,8 +178,8 @@ If telemetry is enabled, the analytics skill records a minimal event after each
178
178
 
179
179
  - If the preamble fails (no config, no Prisma), stop and show the error. Do not attempt to query analytics.
180
180
  - If `query-analytics.ts` returns a non-zero exit code, display the error message from stderr and suggest a fix.
181
- - If DATABASE_URL is empty, tell the user: "No database configured. Run /portal setup to connect your database."
182
- - If the analytics query times out (large dataset), suggest narrowing the period: "Query took too long. Try a shorter period: /portal analytics whzan --period 7d"
181
+ - If DATABASE_URL is empty, tell the user: "No database configured. Run /portal-setup to connect your database."
182
+ - If the analytics query times out (large dataset), suggest narrowing the period: "Query took too long. Try a shorter period: /portal-analytics whzan --period 7d"
183
183
 
184
184
  ## Learnings Integration
185
185
 
@@ -20,7 +20,7 @@ SHOWPANE_HOME="$HOME/.showpane"
20
20
  SHOWPANE_BIN="$SHOWPANE_HOME/bin"
21
21
  CONFIG="$SHOWPANE_HOME/config.json"
22
22
  if [ ! -f "$CONFIG" ]; then
23
- echo "Showpane not configured. Run /portal setup first."
23
+ echo "Showpane not configured. Run /portal-setup first."
24
24
  exit 1
25
25
  fi
26
26
 
@@ -73,16 +73,13 @@ echo "TEL_PROMPTED: $TEL_PROMPTED"
73
73
 
74
74
  If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
75
75
 
76
- If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal upgrade`.
76
+ If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
77
77
 
78
- If `TEL_PROMPTED` is `no`, ask the user once about telemetry and then record the decision:
78
+ If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
79
79
 
80
- - anonymous — local analytics plus anonymous remote sync, with no stable device id
81
- - off — local analytics only, no remote sync
82
-
83
- After the user chooses, run:
80
+ Run:
84
81
  ```bash
85
- "$SHOWPANE_BIN/showpane-config" set telemetry <anonymous|off>
82
+ "$SHOWPANE_BIN/showpane-config" set telemetry anonymous
86
83
  touch "$SHOWPANE_HOME/.telemetry-prompted"
87
84
  ```
88
85
 
@@ -104,7 +101,7 @@ If `skills/shared/platform-constraints.md` exists, read it once near the start o
104
101
 
105
102
  ### Step 1: Determine the portal slug
106
103
 
107
- If the user provided a slug (e.g., `/portal create acme-health`), use it. Otherwise, infer from context — the company name mentioned in conversation, a meeting transcript, or ask the user directly.
104
+ If the user provided a slug (e.g., `/portal-create acme-health`), use it. Otherwise, infer from context — the company name mentioned in conversation, a meeting transcript, or ask the user directly.
108
105
 
109
106
  Validate the slug by running:
110
107
 
@@ -145,7 +142,7 @@ Never fail or block because Granola is unavailable. It is purely additive.
145
142
  ### Step 3: Template selection
146
143
 
147
144
  Ask which template to use as a starting point. Keep this brief and practical —
148
- the user chose `/portal create` because they want the fast path, not a wizard.
145
+ the user chose `/portal-create` because they want the fast path, not a wizard.
149
146
 
150
147
  1. **sales-followup** — Meeting notes, next steps, documents. Best after a sales call.
151
148
  2. **consulting** — Project overview, deliverables, timeline. Best for ongoing engagements.
@@ -286,7 +283,7 @@ Run the create-portal script to register the portal in the database:
286
283
  cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PATH/tsconfig.json" "$SKILL_DIR/bin/create-portal.ts" --slug <slug> --company "<client_company_name>" --org-id <org_id>
287
284
  ```
288
285
 
289
- This creates the `ClientPortal` record with the slug, company name, and links it to the Organization. It does NOT create credentials — that is a separate step via `/portal credentials`.
286
+ This creates the `ClientPortal` record with the slug, company name, and links it to the Organization. It does NOT create credentials — that is a separate step via `/portal-credentials`.
290
287
 
291
288
  ### Step 7: Self-review
292
289
 
@@ -319,7 +316,7 @@ open "http://localhost:3000/client/<slug>"
319
316
 
320
317
  If not running, suggest:
321
318
 
322
- > "Start the dev server with `/portal dev` to preview your portal at http://localhost:3000/client/<slug>"
319
+ > "Start the dev server with `/portal-dev` to preview your portal at http://localhost:3000/client/<slug>"
323
320
 
324
321
  ### Step 9: Summary and next steps
325
322
 
@@ -334,10 +331,10 @@ Portal created: <slug>
334
331
  src/app/(portal)/client/<slug>/<slug>-client.tsx
335
332
 
336
333
  Next steps:
337
- 1. Create login credentials: /portal credentials <slug>
338
- 2. Preview the portal: /portal preview <slug>
339
- 3. Edit content: /portal update <slug>
340
- 4. Deploy: /portal deploy
334
+ 1. Create login credentials: /portal-credentials <slug>
335
+ 2. Preview the portal: /portal-preview <slug>
336
+ 3. Edit content: /portal-update <slug>
337
+ 4. Deploy: /portal-deploy
341
338
  ```
342
339
 
343
340
  ### Step 10: Record learning
@@ -17,7 +17,7 @@ capabilities, read `skills/shared/platform-constraints.md` and apply the relevan
17
17
 
18
18
  ### Step 1: Determine the portal slug
19
19
 
20
- If the user provided a slug (e.g., `/portal create acme-health`), use it. Otherwise, infer from context — the company name mentioned in conversation, a meeting transcript, or ask the user directly.
20
+ If the user provided a slug (e.g., `/portal-create acme-health`), use it. Otherwise, infer from context — the company name mentioned in conversation, a meeting transcript, or ask the user directly.
21
21
 
22
22
  Validate the slug by running:
23
23
 
@@ -58,7 +58,7 @@ Never fail or block because Granola is unavailable. It is purely additive.
58
58
  ### Step 3: Template selection
59
59
 
60
60
  Ask which template to use as a starting point. Keep this brief and practical —
61
- the user chose `/portal create` because they want the fast path, not a wizard.
61
+ the user chose `/portal-create` because they want the fast path, not a wizard.
62
62
 
63
63
  1. **sales-followup** — Meeting notes, next steps, documents. Best after a sales call.
64
64
  2. **consulting** — Project overview, deliverables, timeline. Best for ongoing engagements.
@@ -199,7 +199,7 @@ Run the create-portal script to register the portal in the database:
199
199
  cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PATH/tsconfig.json" "$SKILL_DIR/bin/create-portal.ts" --slug <slug> --company "<client_company_name>" --org-id <org_id>
200
200
  ```
201
201
 
202
- This creates the `ClientPortal` record with the slug, company name, and links it to the Organization. It does NOT create credentials — that is a separate step via `/portal credentials`.
202
+ This creates the `ClientPortal` record with the slug, company name, and links it to the Organization. It does NOT create credentials — that is a separate step via `/portal-credentials`.
203
203
 
204
204
  ### Step 7: Self-review
205
205
 
@@ -232,7 +232,7 @@ open "http://localhost:3000/client/<slug>"
232
232
 
233
233
  If not running, suggest:
234
234
 
235
- > "Start the dev server with `/portal dev` to preview your portal at http://localhost:3000/client/<slug>"
235
+ > "Start the dev server with `/portal-dev` to preview your portal at http://localhost:3000/client/<slug>"
236
236
 
237
237
  ### Step 9: Summary and next steps
238
238
 
@@ -247,10 +247,10 @@ Portal created: <slug>
247
247
  src/app/(portal)/client/<slug>/<slug>-client.tsx
248
248
 
249
249
  Next steps:
250
- 1. Create login credentials: /portal credentials <slug>
251
- 2. Preview the portal: /portal preview <slug>
252
- 3. Edit content: /portal update <slug>
253
- 4. Deploy: /portal deploy
250
+ 1. Create login credentials: /portal-credentials <slug>
251
+ 2. Preview the portal: /portal-preview <slug>
252
+ 3. Edit content: /portal-update <slug>
253
+ 4. Deploy: /portal-deploy
254
254
  ```
255
255
 
256
256
  ### Step 10: Record learning
@@ -25,7 +25,7 @@ SHOWPANE_HOME="$HOME/.showpane"
25
25
  SHOWPANE_BIN="$SHOWPANE_HOME/bin"
26
26
  CONFIG="$SHOWPANE_HOME/config.json"
27
27
  if [ ! -f "$CONFIG" ]; then
28
- echo "Showpane not configured. Run /portal setup first."
28
+ echo "Showpane not configured. Run /portal-setup first."
29
29
  exit 1
30
30
  fi
31
31
 
@@ -78,16 +78,13 @@ echo "TEL_PROMPTED: $TEL_PROMPTED"
78
78
 
79
79
  If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
80
80
 
81
- If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal upgrade`.
81
+ If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
82
82
 
83
- If `TEL_PROMPTED` is `no`, ask the user once about telemetry and then record the decision:
83
+ If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
84
84
 
85
- - anonymous — local analytics plus anonymous remote sync, with no stable device id
86
- - off — local analytics only, no remote sync
87
-
88
- After the user chooses, run:
85
+ Run:
89
86
  ```bash
90
- "$SHOWPANE_BIN/showpane-config" set telemetry <anonymous|off>
87
+ "$SHOWPANE_BIN/showpane-config" set telemetry anonymous
91
88
  touch "$SHOWPANE_HOME/.telemetry-prompted"
92
89
  ```
93
90
 
@@ -109,7 +106,7 @@ If `skills/shared/platform-constraints.md` exists, read it once near the start o
109
106
 
110
107
  ### Step 1: Identify the portal
111
108
 
112
- If the user provided a slug (e.g., `/portal credentials acme-health`), use it. Otherwise, list available portals to help the user choose:
109
+ If the user provided a slug (e.g., `/portal-credentials acme-health`), use it. Otherwise, list available portals to help the user choose:
113
110
 
114
111
  ```bash
115
112
  cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PATH/tsconfig.json" "$SKILL_DIR/bin/list-portals.ts" --org-id <org_id>
@@ -117,9 +114,9 @@ cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PA
117
114
 
118
115
  Present the list and ask which portal needs credentials. If there is only one portal, confirm it rather than asking.
119
116
 
120
- Verify the portal exists by checking the database. The `create-portal.ts` script should have been run during `/portal create` to register the portal. If no DB record exists, inform the user:
117
+ Verify the portal exists by checking the database. The `create-portal.ts` script should have been run during `/portal-create` to register the portal. If no DB record exists, inform the user:
121
118
 
122
- > "No portal record found for '<slug>'. Run `/portal create <slug>` first to register it."
119
+ > "No portal record found for '<slug>'. Run `/portal-create <slug>` first to register it."
123
120
 
124
121
  Also check the portal's current credential status from the list output. If credentials already exist, inform the user before proceeding:
125
122
 
@@ -156,7 +153,7 @@ The script returns JSON on stdout:
156
153
 
157
154
  If the script returns an error, handle it based on the error type:
158
155
 
159
- - `portal_not_found` — The portal slug doesn't exist in the database for this org. Suggest running `/portal create <slug>` first.
156
+ - `portal_not_found` — The portal slug doesn't exist in the database for this org. Suggest running `/portal-create <slug>` first.
160
157
  - `database_error` — Connection or query failure. Check DATABASE_URL and re-apply the local schema with `cd $APP_PATH && npm run prisma:db-push`.
161
158
  - `auth_secret_missing` — The AUTH_SECRET environment variable is not set in `$APP_PATH/.env`. The rotate-credentials script needs this to function. Suggest adding `AUTH_SECRET=<random-string>` to the .env file.
162
159
 
@@ -183,7 +180,7 @@ The ASCII box ensures the credentials stand out clearly in terminal output. Do n
183
180
 
184
181
  Immediately after displaying credentials, show this warning:
185
182
 
186
- > **Save these credentials now.** They will not be shown again. The password is hashed in the database and cannot be retrieved. If lost, run `/portal credentials <slug>` again to rotate to a new password.
183
+ > **Save these credentials now.** They will not be shown again. The password is hashed in the database and cannot be retrieved. If lost, run `/portal-credentials <slug>` again to rotate to a new password.
187
184
 
188
185
  If this was a rotation (`"rotated": true`), add:
189
186
 
@@ -196,8 +193,8 @@ Provide guidance on how to share the credentials with the client:
196
193
  > **How to share with your client:**
197
194
  > - Send the username and password via a secure channel (encrypted email, Signal, etc.)
198
195
  > - The login page is at `/client` — the client enters the portal slug as the "company" field, then the username and password
199
- > - For external access, publish the portal first with `/portal deploy`
200
- > - After publish, you can use `/portal share <slug>` if you want a direct hosted link instead of asking the client to log in
196
+ > - For external access, publish the portal first with `/portal-deploy`
197
+ > - After publish, you can use `/portal-share <slug>` if you want a direct hosted link instead of asking the client to log in
201
198
 
202
199
  Recommend against sharing credentials via:
203
200
  - Unencrypted email (can be intercepted)
@@ -236,8 +233,8 @@ Credentials created for: acme-health
236
233
 
237
234
  Next steps:
238
235
  1. Send credentials to the client via a secure channel
239
- 2. Deploy if not already live: /portal deploy
240
- 3. Optional hosted direct link after publish: /portal share <slug>
236
+ 2. Deploy if not already live: /portal-deploy
237
+ 3. Optional hosted direct link after publish: /portal-share <slug>
241
238
  ```
242
239
 
243
240
  ### Step 9: Record credential event
@@ -259,7 +256,7 @@ echo '{"skill":"portal-credentials","key":"credentials-created","insight":"Creat
259
256
 
260
257
  ## Error Handling
261
258
 
262
- - **Script not found**: If `$SKILL_DIR/bin/rotate-credentials.ts` does not exist, the skill pack may not be fully installed. Suggest running `/portal upgrade` or checking the Showpane installation.
259
+ - **Script not found**: If `$SKILL_DIR/bin/rotate-credentials.ts` does not exist, the skill pack may not be fully installed. Suggest running `/portal-upgrade` or checking the Showpane installation.
263
260
  - **Prisma connection error**: DATABASE_URL may be wrong or the database may be down. Check the .env file and database status.
264
261
  - **Permission denied on .env**: The preamble sources `$APP_PATH/.env`. If this file is not readable, the DATABASE_URL will not be set. Check file permissions.
265
262
  - **Script timeout**: If the script takes more than 30 seconds, something is wrong. The most common cause is a database connection timeout — check network connectivity to the database host.
@@ -22,7 +22,7 @@ hooks:
22
22
 
23
23
  ### Step 1: Identify the portal
24
24
 
25
- If the user provided a slug (e.g., `/portal credentials acme-health`), use it. Otherwise, list available portals to help the user choose:
25
+ If the user provided a slug (e.g., `/portal-credentials acme-health`), use it. Otherwise, list available portals to help the user choose:
26
26
 
27
27
  ```bash
28
28
  cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PATH/tsconfig.json" "$SKILL_DIR/bin/list-portals.ts" --org-id <org_id>
@@ -30,9 +30,9 @@ cd "$APP_PATH" && NODE_PATH="$APP_PATH/node_modules" npx tsx --tsconfig "$APP_PA
30
30
 
31
31
  Present the list and ask which portal needs credentials. If there is only one portal, confirm it rather than asking.
32
32
 
33
- Verify the portal exists by checking the database. The `create-portal.ts` script should have been run during `/portal create` to register the portal. If no DB record exists, inform the user:
33
+ Verify the portal exists by checking the database. The `create-portal.ts` script should have been run during `/portal-create` to register the portal. If no DB record exists, inform the user:
34
34
 
35
- > "No portal record found for '<slug>'. Run `/portal create <slug>` first to register it."
35
+ > "No portal record found for '<slug>'. Run `/portal-create <slug>` first to register it."
36
36
 
37
37
  Also check the portal's current credential status from the list output. If credentials already exist, inform the user before proceeding:
38
38
 
@@ -69,7 +69,7 @@ The script returns JSON on stdout:
69
69
 
70
70
  If the script returns an error, handle it based on the error type:
71
71
 
72
- - `portal_not_found` — The portal slug doesn't exist in the database for this org. Suggest running `/portal create <slug>` first.
72
+ - `portal_not_found` — The portal slug doesn't exist in the database for this org. Suggest running `/portal-create <slug>` first.
73
73
  - `database_error` — Connection or query failure. Check DATABASE_URL and re-apply the local schema with `cd $APP_PATH && npm run prisma:db-push`.
74
74
  - `auth_secret_missing` — The AUTH_SECRET environment variable is not set in `$APP_PATH/.env`. The rotate-credentials script needs this to function. Suggest adding `AUTH_SECRET=<random-string>` to the .env file.
75
75
 
@@ -96,7 +96,7 @@ The ASCII box ensures the credentials stand out clearly in terminal output. Do n
96
96
 
97
97
  Immediately after displaying credentials, show this warning:
98
98
 
99
- > **Save these credentials now.** They will not be shown again. The password is hashed in the database and cannot be retrieved. If lost, run `/portal credentials <slug>` again to rotate to a new password.
99
+ > **Save these credentials now.** They will not be shown again. The password is hashed in the database and cannot be retrieved. If lost, run `/portal-credentials <slug>` again to rotate to a new password.
100
100
 
101
101
  If this was a rotation (`"rotated": true`), add:
102
102
 
@@ -109,8 +109,8 @@ Provide guidance on how to share the credentials with the client:
109
109
  > **How to share with your client:**
110
110
  > - Send the username and password via a secure channel (encrypted email, Signal, etc.)
111
111
  > - The login page is at `/client` — the client enters the portal slug as the "company" field, then the username and password
112
- > - For external access, publish the portal first with `/portal deploy`
113
- > - After publish, you can use `/portal share <slug>` if you want a direct hosted link instead of asking the client to log in
112
+ > - For external access, publish the portal first with `/portal-deploy`
113
+ > - After publish, you can use `/portal-share <slug>` if you want a direct hosted link instead of asking the client to log in
114
114
 
115
115
  Recommend against sharing credentials via:
116
116
  - Unencrypted email (can be intercepted)
@@ -149,8 +149,8 @@ Credentials created for: acme-health
149
149
 
150
150
  Next steps:
151
151
  1. Send credentials to the client via a secure channel
152
- 2. Deploy if not already live: /portal deploy
153
- 3. Optional hosted direct link after publish: /portal share <slug>
152
+ 2. Deploy if not already live: /portal-deploy
153
+ 3. Optional hosted direct link after publish: /portal-share <slug>
154
154
  ```
155
155
 
156
156
  ### Step 9: Record credential event
@@ -172,7 +172,7 @@ echo '{"skill":"portal-credentials","key":"credentials-created","insight":"Creat
172
172
 
173
173
  ## Error Handling
174
174
 
175
- - **Script not found**: If `$SKILL_DIR/bin/rotate-credentials.ts` does not exist, the skill pack may not be fully installed. Suggest running `/portal upgrade` or checking the Showpane installation.
175
+ - **Script not found**: If `$SKILL_DIR/bin/rotate-credentials.ts` does not exist, the skill pack may not be fully installed. Suggest running `/portal-upgrade` or checking the Showpane installation.
176
176
  - **Prisma connection error**: DATABASE_URL may be wrong or the database may be down. Check the .env file and database status.
177
177
  - **Permission denied on .env**: The preamble sources `$APP_PATH/.env`. If this file is not readable, the DATABASE_URL will not be set. Check file permissions.
178
178
  - **Script timeout**: If the script takes more than 30 seconds, something is wrong. The most common cause is a database connection timeout — check network connectivity to the database host.