kimaki 0.20.1 → 0.22.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 (64) hide show
  1. package/dist/agent-model.e2e.test.js +6 -4
  2. package/dist/cli-commands/project.js +148 -24
  3. package/dist/cli-commands/send.js +48 -3
  4. package/dist/cli-runner.js +86 -7
  5. package/dist/cli-runner.test.js +28 -1
  6. package/dist/commands/btw.js +7 -3
  7. package/dist/commands/new-worktree.js +14 -2
  8. package/dist/commands/session.js +66 -13
  9. package/dist/commands/tasks.js +104 -19
  10. package/dist/commands/user-command.js +3 -2
  11. package/dist/database.js +14 -0
  12. package/dist/db.js +1 -0
  13. package/dist/discord-bot.js +65 -9
  14. package/dist/interaction-handler.js +6 -15
  15. package/dist/message-preprocessing.js +9 -2
  16. package/dist/queue-advanced-e2e-setup.js +22 -0
  17. package/dist/queue-delete-message.e2e.test.js +75 -0
  18. package/dist/schema.js +3 -0
  19. package/dist/session-handler/thread-runtime-state.js +9 -0
  20. package/dist/session-handler/thread-session-runtime.js +49 -1
  21. package/dist/system-message.js +50 -63
  22. package/dist/system-message.test.js +65 -61
  23. package/dist/task-runner.js +18 -3
  24. package/dist/task-schedule.js +4 -0
  25. package/dist/thread-message-queue.e2e.test.js +4 -4
  26. package/dist/voice-message.e2e.test.js +1 -1
  27. package/dist/worktree-lifecycle.e2e.test.js +70 -1
  28. package/dist/worktrees.js +63 -0
  29. package/package.json +11 -4
  30. package/skills/egaki/SKILL.md +26 -80
  31. package/skills/goke/SKILL.md +27 -20
  32. package/skills/holocron/SKILL.md +72 -8
  33. package/skills/new-skill/SKILL.md +87 -0
  34. package/skills/playwriter/SKILL.md +4 -4
  35. package/skills/spiceflow/SKILL.md +2 -0
  36. package/src/agent-model.e2e.test.ts +10 -4
  37. package/src/cli-commands/project.ts +183 -26
  38. package/src/cli-commands/send.ts +64 -5
  39. package/src/cli-runner.test.ts +39 -1
  40. package/src/cli-runner.ts +115 -6
  41. package/src/commands/btw.ts +9 -2
  42. package/src/commands/new-worktree.ts +14 -1
  43. package/src/commands/session.ts +79 -17
  44. package/src/commands/tasks.ts +119 -19
  45. package/src/commands/user-command.ts +3 -2
  46. package/src/database.ts +24 -0
  47. package/src/db.ts +1 -0
  48. package/src/discord-bot.ts +80 -8
  49. package/src/interaction-handler.ts +7 -19
  50. package/src/message-preprocessing.ts +11 -2
  51. package/src/queue-advanced-e2e-setup.ts +23 -0
  52. package/src/queue-delete-message.e2e.test.ts +102 -0
  53. package/src/schema.sql +1 -0
  54. package/src/schema.ts +3 -0
  55. package/src/session-handler/thread-runtime-state.ts +19 -0
  56. package/src/session-handler/thread-session-runtime.ts +75 -0
  57. package/src/system-message.test.ts +73 -61
  58. package/src/system-message.ts +63 -62
  59. package/src/task-runner.ts +34 -3
  60. package/src/task-schedule.ts +6 -0
  61. package/src/thread-message-queue.e2e.test.ts +4 -4
  62. package/src/voice-message.e2e.test.ts +1 -1
  63. package/src/worktree-lifecycle.e2e.test.ts +88 -1
  64. package/src/worktrees.ts +74 -0
@@ -1,43 +1,45 @@
1
1
  ---
2
2
  name: egaki
3
+ repo: remorses/egaki
3
4
  description: >
4
- AI image and video generation CLI. Use this skill to install egaki, configure
5
- auth, run help commands, and generate images or videos with provider keys or
6
- an Egaki subscription.
5
+ AI image and video generation CLI and MDX-to-video framework built on Remotion.
6
+ Use this skill to install egaki, configure auth, generate images/videos, create
7
+ MDX video projects with animation primitives (Opacity, Scale, TranslateX, Blur),
8
+ easing presets (EASE, springFromDuration, dspring, cubicBezier), LayoutTransition,
9
+ captions, voice cloning, TTS, Server components, and media components. ALWAYS load
10
+ this skill when the user mentions egaki, runs egaki commands, edits egaki MDX video
11
+ files, or works in a project with an egaki vite plugin.
7
12
  ---
8
13
 
9
14
  # egaki
10
15
 
11
- Generate AI images and videos from the terminal.
12
- Use this for text-to-image, image editing, mask-based edits, text-to-video,
13
- image-to-video, and model discovery.
14
-
15
- ## Install
16
+ Every time you work with egaki, you MUST fetch the latest README:
16
17
 
17
18
  ```bash
18
- pnpm add -g egaki
19
+ curl -s https://raw.githubusercontent.com/remorses/egaki/main/README.md # NEVER pipe to head/tail, read the full output
19
20
  ```
20
21
 
21
- ## Always check help first
22
+ The README is the single source of truth for all user-facing docs: CLI usage,
23
+ MDX video syntax, animation primitives, easing presets, LayoutTransition,
24
+ captions, voice cloning, media components, CSS rules, and project setup.
22
25
 
23
- Run the full help output before using commands:
26
+ ## Always check help first
24
27
 
25
28
  ```bash
26
- egaki --help
29
+ egaki --help # NEVER pipe to head/tail, read the full output
27
30
  ```
28
31
 
29
- Do not truncate help output with `head`.
30
-
31
- For subcommand details: `egaki <command> --help` (e.g. `egaki image --help`, `egaki video --help`, `egaki login --help`)
32
+ For subcommand details: `egaki <command> --help` (e.g. `egaki image --help`,
33
+ `egaki video --help`, `egaki login --help`)
32
34
 
33
35
  ## Auth options
34
36
 
35
- You can authenticate in two ways:
37
+ Two authentication modes:
36
38
 
37
- 1. Egaki subscription key (recommended all models, one key)
38
- 2. Provider API keys (Google, OpenAI, Fal, Replicate) via `egaki login`
39
+ 1. **Egaki subscription key** (recommended, all models, one key)
40
+ 2. **Provider API keys** (Google, OpenAI, Fal, xAI, etc.) via `egaki login`
39
41
 
40
- If using Egaki subscription, set it up first with `egaki subscribe`, then store
42
+ If using Egaki subscription, set it up with `egaki subscribe`, then store
41
43
  the key with `egaki login --provider egaki --key egaki_...`.
42
44
 
43
45
  ## Login behavior for remote agents
@@ -49,78 +51,22 @@ to the user so they can complete auth interactively.
49
51
 
50
52
  The `--model` / `-m` flag is **optional** on both `egaki image` and `egaki video`.
51
53
 
52
- - **Interactive (TTY):** omitting `--model` shows a picker with popular models
53
- - **Non-interactive (piped/scripted):** omitting `--model` uses a sensible default
54
+ - **Interactive (TTY):** omitting `--model` shows a picker
55
+ - **Non-interactive (piped/scripted):** uses a sensible default
54
56
 
55
57
  Agents should always pass `-m` explicitly to avoid the interactive picker.
56
58
 
57
59
  ### Preferred image models
58
60
 
59
- When the user does not specify a model, prefer these in order:
60
-
61
61
  1. **`gpt-image-1`** (or `gpt-image-2` / `chatgpt-image-latest` if available)
62
62
  2. **`grok-imagine-image`** (xAI Grok)
63
63
  3. **`nano-banana-pro-preview`**
64
64
 
65
- Always try the first available model. Fall back to the next if auth is missing
66
- for the preferred one.
67
-
68
65
  ### Preferred video models
69
66
 
70
- When the user does not specify a video model, prefer:
71
-
72
67
  1. **`grok-imagine-video-1.5`** (xAI Grok)
73
68
 
74
- ## Example commands
75
-
76
- ```bash
77
- # configure key interactively
78
- egaki login
79
-
80
- # show login status
81
- egaki login --show
82
-
83
- # subscribe to Egaki for all supported models
84
- egaki subscribe
85
-
86
- # check subscription usage
87
- egaki usage
88
-
89
- # generate an image (interactive model picker if TTY)
90
- egaki image "a watercolor fox reading a map" -o fox.png
91
-
92
- # select a model explicitly
93
- egaki image "isometric floating city, soft colors" -m imagen-4.0-generate-001 -o city.png
94
-
95
- # edit an existing image (local file or URL)
96
- egaki image "add a red scarf and make it winter" --input portrait.jpg -o portrait-winter.png
97
- egaki image "turn this into a manga panel" --input https://example.com/photo.jpg -o manga.png
98
-
99
- # inpainting with a mask
100
- egaki image "replace the sky with a dramatic sunset" --input scene.png --mask mask.png -o scene-sunset.png
101
-
102
- # generate a video — use a 5 minute timeout, video generation is slow
103
- egaki video "a paper boat drifting on a calm lake at sunrise" -o boat.mp4
104
-
105
- # generate a video with a specific model
106
- egaki video "timelapse of a stormy sea, cinematic" -m google/veo-3.1-fast-generate-001 --duration 6 -o storm.mp4
107
-
108
- # cheap video model
109
- egaki video "a cat walking on a rooftop at night" -m klingai/kling-v2.5-turbo-t2v --duration 5 -o cat.mp4
110
-
111
- # image-to-video (model must support i2v)
112
- egaki video "slowly animate the clouds" --input photo.jpg -m klingai/kling-v2.6-i2v -o animated.mp4
113
-
114
- # discover all models (image + video)
115
- egaki models
116
-
117
- # filter by type
118
- egaki models --type video
119
- egaki models --type image
120
- ```
121
-
122
- ## Video generation note for agents
69
+ ## Video generation note
123
70
 
124
- Video generation can be very slow — some models take 13 minutes per request.
125
- Always use a command timeout of **at least 5 minutes** when invoking `egaki video`
126
- from automation or agent workflows.
71
+ Video generation can be very slow (1-3 minutes per request). Always use a
72
+ command timeout of **at least 5 minutes** from automation or agent workflows.
@@ -85,34 +85,39 @@ Supported agents: `cursor`, `claude`, `devin`, `replit`, `gemini`, `codex`, `aug
85
85
 
86
86
  ## Long-Running Interactive Commands
87
87
 
88
- Commands that start a browser/device login flow or any other long-running TTY-only interaction must fail fast in non-TTY shells. Do not start the flow and hope the agent notices the URL. The process must stay alive while the user approves the browser prompt, so agents need to launch it in a persistent terminal session like tuistory or tmux.
88
+ Commands that start a browser/device login flow need to work for both interactive users and AI agents. goke's built-in **daemon** pattern (`ctx.daemon`) handles this: the command forks itself into a background process that waits for browser approval, while the foreground returns immediately so agents aren't blocked.
89
89
 
90
- Always guard these commands with `!process.stdout.isTTY` before making network requests, opening the browser, or starting spinners. Do not fail just because an agent is running the command if the command has a real TTY.
90
+ Use `isAgent` to branch between agent mode (start daemon, return immediately) and interactive mode (block until login completes). Do not fail in non-TTY shells; use the daemon instead.
91
91
 
92
92
  ```ts
93
- import dedent from 'string-dedent'
94
- import { goke } from 'goke'
95
-
96
- cli.command('login', 'Authenticate with browser login').action((options, { console, process }) => {
97
- if (!process.stdout.isTTY) {
98
- console.error(dedent`
99
- mycli login needs an interactive terminal and must stay alive while you approve the browser login.
100
-
101
- Run it in a background terminal session like tuistory or tmux, then wait for the URL/code:
93
+ import { goke, isAgent, openInBrowser } from 'goke'
102
94
 
103
- bunx tuistory launch "mycli login" -s mycli-login
104
- bunx tuistory -s mycli-login wait "/code:|https?:\\/\\//i" --timeout 15000
95
+ cli
96
+ .command('login', 'Authenticate with browser login')
97
+ .action(async (options, ctx) => {
98
+ if (ctx.daemon.isDaemon) {
99
+ // ── DAEMON: run the long-running flow in background ──
100
+ const result = await startOAuthFlow({ /* ... */ })
101
+ if (result.success) saveAuth(result)
102
+ return // daemon exits, PID file is cleaned up
103
+ }
105
104
 
106
- The login command exits by itself after successful browser approval.
107
- `)
108
- process.exit(1)
109
- }
105
+ // ── CLIENT: decide foreground vs background ──
106
+ if (isAgent) {
107
+ // Agent mode: start daemon and return immediately
108
+ await ctx.daemon.start({ timeoutMs: 10 * 60 * 1000 })
109
+ ctx.console.log('Login running in background.')
110
+ ctx.console.log('After approving in browser, verify with: mycli me')
111
+ return
112
+ }
110
113
 
111
- // Start device/browser login only after the guard.
112
- })
114
+ // Interactive mode: attach to daemon, see all its logs and errors in real time
115
+ await ctx.daemon.start({ attach: true, timeoutMs: 10 * 60 * 1000 })
116
+ ctx.console.log('Login successful!')
117
+ })
113
118
  ```
114
119
 
115
- Use `tuistory wait` for the handoff point that needs user interaction. It returns nearby lines around the match, so agents can show the URL/code without a separate `tuistory read` call. Do not add `tuistory close` to login instructions when the CLI exits by itself after success.
120
+ Add a `me` command (exits 0 if logged in, 1 if not) so agents can poll for completion. Use `ctx.daemon.forCommand('login')` to check the login daemon status from other commands. See the **Background Daemons** section in the goke README for the full pattern, including `env` passthrough and PID file safety.
116
121
 
117
122
  ## Shell Completions
118
123
 
@@ -398,6 +403,8 @@ cli
398
403
 
399
404
  CLIs that talk to a remote server must support multiple server URLs so users can self-host, use a preview/staging environment, or point to localhost during development. Auth tokens and other per-server state live in a JSON config file keyed by API URL.
400
405
 
406
+ **Never log config file paths** (like `~/.myapp/config.json` or `~/.myapp/auth.json`) in CLI output. Agents read CLI output and will try to `cat` or parse these files directly, bypassing the CLI's own commands. Log success/failure messages without revealing internal storage paths.
407
+
401
408
  ### Config file location
402
409
 
403
410
  Store config at `~/.cliname/config.json`. The directory is named after the CLI binary. Use `os.homedir()` to resolve `~`.
@@ -44,6 +44,7 @@ When the user asks about a specific workflow, fetch the matching page directly:
44
44
  - **Holocron deploy**: https://holocron.so/docs/deploy/holocron.md
45
45
  - **AI assistant docs**: https://holocron.so/docs/ai/assistant.md
46
46
  - **Bleed**: https://holocron.so/docs/customize/bleed.md
47
+ - **Layout and page modes**: https://holocron.so/docs/customize/layout.md
47
48
 
48
49
  ```bash
49
50
  curl -fsSL https://holocron.so/docs/quickstart.md
@@ -55,7 +56,7 @@ curl -fsSL https://holocron.so/docs/organize/docs-json.md
55
56
  Use the CLI to create a new docs site with a working template:
56
57
 
57
58
  ```bash
58
- npx -y @holocron.so/cli create --name "My Docs" my-docs --skip-auth
59
+ npx -y "@holocron.so/cli" create --name "My Docs" my-docs --skip-auth
59
60
  ```
60
61
 
61
62
  The `--skip-auth` flag skips cloud setup & AI chat setup (suitable for agents and local-only
@@ -357,6 +358,22 @@ Sidebar: `Home`
357
358
  - **Every `title` MUST be unique across the site.**
358
359
  - **`index.mdx` MUST use `sidebarTitle: Home`** (or `Overview`) and a descriptive `title`.
359
360
 
361
+ ## Page modes — hiding sidebars
362
+
363
+ Set **`mode`** in frontmatter to hide sidebars. Use for landing pages, tool pages, or pages that should not show left nav or AI chat. See https://holocron.so/docs/customize/layout.md for details.
364
+
365
+ - **`center`** — hides the left nav, centers content. Right aside still works.
366
+ - **`custom`** — hides both sidebars and the editorial grid. Only navbar, tab bar, and footer remain. See `example/src/landing.mdx` for a full example.
367
+
368
+ In both modes the content can feel too wide. Use **`maxWidth`** to constrain it:
369
+
370
+ ```yaml
371
+ ---
372
+ mode: "custom"
373
+ maxWidth: 700
374
+ ---
375
+ ```
376
+
360
377
  ## Custom entry (mounting docs inside a Spiceflow app)
361
378
 
362
379
  When the site mounts Holocron inside an existing **Spiceflow** app (the `entry`
@@ -402,6 +419,23 @@ the **`knownPaths`** field in `docs.json` to tell Holocron these paths are valid
402
419
  Wildcards only work as a trailing `/*` suffix. Glob patterns like `/api/*/users`
403
420
  are not supported.
404
421
 
422
+ ## Vertical spacing inside wrappers
423
+
424
+ When wrapping MDX content in a `<div>` or custom component, add
425
+ `flex flex-col gap-(--prose-gap)` so children get correct vertical spacing.
426
+ Without it, elements collapse together. Add `no-bleed` too if the wrapper
427
+ contains images or code blocks that shouldn't escape its bounds.
428
+
429
+ ```mdx
430
+ <div className='no-bleed flex flex-col gap-(--prose-gap)'>
431
+
432
+ First paragraph.
433
+
434
+ Second paragraph with correct spacing above.
435
+
436
+ </div>
437
+ ```
438
+
405
439
  ## MDX container components
406
440
 
407
441
  Always use multi-line form for container components like `Callout`, `Note`,
@@ -505,7 +539,7 @@ section above.
505
539
  Run `--help` to see all available commands. Never truncate the output.
506
540
 
507
541
  ```bash
508
- npx -y @holocron.so/cli --help
542
+ npx -y "@holocron.so/cli" --help
509
543
  ```
510
544
 
511
545
  Key commands: `login`, `logout`, `whoami`, `deploy`, `projects list`,
@@ -514,19 +548,26 @@ Key commands: `login`, `logout`, `whoami`, `deploy`, `projects list`,
514
548
  Before logging in, always check if the user is already authenticated:
515
549
 
516
550
  ```bash
517
- npx -y @holocron.so/cli whoami
551
+ npx -y "@holocron.so/cli" whoami
518
552
  ```
519
553
 
520
554
  If `whoami` succeeds and shows user, orgs, and projects, skip login. Only run
521
- `npx -y @holocron.so/cli login` if `whoami` fails.
555
+ `npx -y "@holocron.so/cli" login` if `whoami` fails.
522
556
 
523
557
  ## Deploy
524
558
 
559
+ When the user asks to "deploy the site", they may mean deploying with their own
560
+ script and platform (Cloudflare Workers, a Node server, CI pipeline), not
561
+ `holocron deploy`. Check `package.json` scripts first: if there is a `deploy`,
562
+ `deployment`, or similar script (e.g. wrangler deploy), use that instead of the
563
+ Holocron CLI. Only use `holocron deploy` when the project has no own deploy
564
+ script or the user explicitly asks for holocron.so hosting.
565
+
525
566
  `holocron deploy` builds the docs site and uploads it to holocron.so hosting.
526
567
  It is the fastest way to publish without managing your own server.
527
568
 
528
569
  ```bash
529
- npx -y @holocron.so/cli deploy
570
+ npx -y "@holocron.so/cli" deploy
530
571
  ```
531
572
 
532
573
  The command runs the build, uploads only changed files, finalizes the deployment,
@@ -606,7 +647,7 @@ Use ASCII diagrams frequently in MDX pages. Always use the **`diagram`** languag
606
647
  - Never exceed 94 characters per line.
607
648
  - Prefer a **varied, organic layout**. Mix plain text labels, boxes for major components, and directional arrows.
608
649
  - All connections must use **directional arrows**. Never use plain lines without an arrowhead.
609
- - Verify alignment by running `npx -y @holocron.so/cli diagrams fix <file>` (see dedicated section below).
650
+ - Verify alignment by running `npx -y "@holocron.so/cli" diagrams fix <file>` (see dedicated section below).
610
651
 
611
652
  ````mdx
612
653
  ```diagram
@@ -632,7 +673,7 @@ docs.jsonc ───►│ Vite Plugin │──────► Build Output
632
673
  LLMs cannot count characters reliably. Every time you create or edit a diagram in an MDX page, you **must** run the alignment fixer before committing. This is not optional.
633
674
 
634
675
  ```bash
635
- npx -y @holocron.so/cli diagrams fix path/to/file.mdx
676
+ npx -y "@holocron.so/cli" diagrams fix path/to/file.mdx
636
677
  ```
637
678
 
638
679
  The command:
@@ -664,6 +705,29 @@ Accordion apply `no-bleed` automatically to keep descendants inside their frame.
664
705
 
665
706
  See https://holocron.so/docs/customize/bleed.md for the full reference.
666
707
 
708
+ ## Custom CSS — prefer CSS variables over class selectors
709
+
710
+ When customizing the look of a Holocron site, **always use CSS variable overrides** in `:root` instead of targeting internal class names, DOM structure, or aria labels. Holocron exposes a set of documented CSS variables for colors, typography, spacing, code blocks, blockquotes, and sidebar navigation. These are stable across Holocron updates; internal markup is not.
711
+
712
+ ```css
713
+ /* style.css */
714
+ :root {
715
+ --weight-heading: 700;
716
+ --code-block-background: var(--muted);
717
+ --code-block-border: 1px solid var(--border-subtle);
718
+ --sidebar-link-radius: var(--radius-sm);
719
+ --blockquote-border-color: var(--border-subtle);
720
+ }
721
+ ```
722
+
723
+ Fetch the full list of available tokens:
724
+
725
+ ```bash
726
+ curl -fsSL https://holocron.so/docs/customize/theme.md
727
+ ```
728
+
729
+ If a user wants to customize something that has no CSS variable, **do not hack it with fragile selectors**. Instead, open an issue on the Holocron repo (https://github.com/remorses/holocron/issues) requesting a new CSS variable for that use case. Holocron actively adds new variables based on user needs. Internal selectors like `.slot-sidebar-left nav > div:first-child > a` or `figure[class~='group/code'] button[aria-label='Copy code']` will break on any refactor and should never be used.
730
+
667
731
  ## Agent rules
668
732
 
669
733
  - **Always place MDX pages inside the Holocron `pagesDir`.** Before creating or
@@ -677,7 +741,7 @@ See https://holocron.so/docs/customize/bleed.md for the full reference.
677
741
  - All ASCII diagrams in MDX pages must use the `diagram` language hint on the
678
742
  code fence (` ```diagram `). This renders them with proper styling on the
679
743
  website instead of plain monospace.
680
- - After creating or editing any diagram, run `npx -y @holocron.so/cli diagrams fix <file>`
744
+ - After creating or editing any diagram, run `npx -y "@holocron.so/cli" diagrams fix <file>`
681
745
  to auto-fix alignment. LLMs cannot count characters reliably.
682
746
  - Never pipe curl or `--help` output through `head`, `tail`, or any truncation
683
747
  command. Always read the full output.
@@ -62,6 +62,93 @@ Claude Code, Cursor, Windsurf, and others. Skills teach agents the
62
62
  workflows, patterns, and tools specific to this project.
63
63
  ```
64
64
 
65
+ ## Making a skill installable from a URL
66
+
67
+ Use this when the project does **not have a public GitHub repo** (private repos, closed-source SaaS products) or when you want the install command to use your own domain:
68
+
69
+ ```bash
70
+ npx skills add https://example.com
71
+ ```
72
+
73
+ The `skills` CLI treats any non-GitHub/GitLab HTTP(S) URL as a **well-known discovery endpoint** (RFC 8615). It fetches `/.well-known/agent-skills/index.json` and expects the v0.2.0 discovery schema:
74
+
75
+ ```json
76
+ {
77
+ "$schema": "https://schemas.agentskills.io/discovery/0.2.0/schema.json",
78
+ "skills": [
79
+ {
80
+ "name": "my-skill",
81
+ "type": "skill-md",
82
+ "description": "One-line description shown in the CLI skill picker.",
83
+ "url": "./my-skill/SKILL.md",
84
+ "digest": "sha256:<hex sha256 of the exact artifact bytes>"
85
+ }
86
+ ]
87
+ }
88
+ ```
89
+
90
+ Rules:
91
+
92
+ - **The digest must match the served bytes exactly.** The CLI downloads the artifact from `url` and verifies its sha256 before installing. Never hardcode the digest; compute it from the same string you serve.
93
+ - **`url` is resolved relative to index.json**, so `./my-skill/SKILL.md` works and survives domain changes. Absolute URLs also work.
94
+ - **`name` must be kebab-case** (`^[a-z0-9-]+$`, no leading/trailing/double dashes) and match the SKILL.md frontmatter name.
95
+ - `type: "skill-md"` serves a single markdown file. Use `type: "archive"` (zip or tar.gz with a root SKILL.md) only when the skill ships companion files.
96
+ - Keep the canonical SKILL.md in the repo (`skills/<name>/SKILL.md`) and serve those exact bytes, so the published skill can never drift from git.
97
+
98
+ Example with **spiceflow** on Cloudflare Workers: import the SKILL.md with vite `?raw` and compute the digest once per isolate with WebCrypto.
99
+
100
+ ```ts
101
+ import { Spiceflow } from 'spiceflow'
102
+ import skillMd from '../../skills/my-skill/SKILL.md?raw'
103
+
104
+ let digestPromise: Promise<string> | undefined
105
+ function getSkillDigest(): Promise<string> {
106
+ digestPromise ??= (async () => {
107
+ const bytes = new TextEncoder().encode(skillMd)
108
+ const hash = await crypto.subtle.digest('SHA-256', bytes)
109
+ const hex = Array.from(new Uint8Array(hash), (b) => b.toString(16).padStart(2, '0')).join('')
110
+ return `sha256:${hex}`
111
+ })()
112
+ return digestPromise
113
+ }
114
+
115
+ export const skillDiscoveryApp = new Spiceflow()
116
+ .route({
117
+ method: 'GET',
118
+ path: '/.well-known/agent-skills/index.json',
119
+ handler: async () =>
120
+ Response.json({
121
+ $schema: 'https://schemas.agentskills.io/discovery/0.2.0/schema.json',
122
+ skills: [
123
+ {
124
+ name: 'my-skill',
125
+ type: 'skill-md',
126
+ description: 'One-line description shown in the CLI skill picker.',
127
+ url: './my-skill/SKILL.md',
128
+ digest: await getSkillDigest(),
129
+ },
130
+ ],
131
+ }),
132
+ })
133
+ .route({
134
+ method: 'GET',
135
+ path: '/.well-known/agent-skills/my-skill/SKILL.md',
136
+ handler: () =>
137
+ new Response(skillMd, {
138
+ headers: { 'content-type': 'text/markdown; charset=utf-8' },
139
+ }),
140
+ })
141
+ ```
142
+
143
+ Validate end-to-end against a local dev server before deploying:
144
+
145
+ ```bash
146
+ npx skills add http://localhost:3000 --list
147
+ npx skills add http://localhost:3000 -y --copy
148
+ ```
149
+
150
+ If the digest is wrong the CLI silently skips the skill, so an empty `--list` result usually means a digest mismatch.
151
+
65
152
  ## Frontmatter
66
153
 
67
154
  Every SKILL.md starts with YAML frontmatter containing three required fields:
@@ -3,9 +3,9 @@ name: playwriter
3
3
  description: Control the user own Chrome browser via Playwriter extension with Playwright code snippets in a stateful local js sandbox. Use this over other Playwright MCPs to automate the browser — it connects to the user's existing Chrome instead of launching a new one. Use this cli for navigating JS-heavy websites (Instagram, Twitter, cookie/login walls, lazy-loaded UIs) instead of webfetch/curl. ALWAYS load this skill before using any playwriter commands
4
4
  ---
5
5
 
6
- ## REQUIRED: Read Full Documentation First
6
+ ## Read Full Documentation (once per session)
7
7
 
8
- **Before using playwriter, you MUST run this command:**
8
+ **Before the first playwriter command in a session, run:**
9
9
 
10
10
  ```bash
11
11
  playwriter skill # IMPORTANT! do not use | head here. read in full!
@@ -19,9 +19,9 @@ This outputs the complete documentation including:
19
19
  - Best practices for slow pages and SPAs
20
20
  - Context variables, utility functions, and more
21
21
 
22
- **Do NOT skip this step.** The quick examples below will fail without understanding timeouts, selector rules, and common pitfalls from the full docs.
22
+ **Do NOT skip this step.** The examples below will fail without understanding timeouts, selector rules, and pitfalls from the full docs. You only need to do this once per session; subsequent playwriter commands in the same session do not require re-reading.
23
23
 
24
- **Read the ENTIRE output.** Do NOT pipe through `head`, `tail`, or any truncation command. The skill output must be read in its entirety — critical rules about timeouts, selectors, and common pitfalls are spread throughout the document, not just at the top.
24
+ **Read the ENTIRE output.** Do NOT pipe through `head`, `tail`, or any truncation command. Critical rules are spread throughout the document, not just at the top.
25
25
 
26
26
  ## Minimal Example (after reading full docs)
27
27
 
@@ -11,6 +11,8 @@ Every time you work with spiceflow, you MUST fetch the **entire** README from th
11
11
  curl -s https://raw.githubusercontent.com/remorses/spiceflow/main/README.md
12
12
  ```
13
13
 
14
+ If you are about to design any navigation, cookie, redirect, or refresh behavior and you have not fetched the README in this session, stop and fetch it first.
15
+
14
16
  **Do NOT truncate, summarize, or skip sections.** Never pipe to `head`, `tail`, `sed`, or any command that cuts the output short. Never stop reading early because it "looks long enough." The README contains sections on routing, RSC, server actions, layouts, error handling, forms, federation, deployment, and more. Missing any of them means missing framework behavior you will get wrong.
15
17
 
16
18
  After reading the full README, check if it references any docs/ files relevant to your task. If it does, fetch those too in full:
@@ -710,14 +710,17 @@ describe('agent model resolution', () => {
710
710
  await db.delete(schema.channel_agents).where(orm.eq(schema.channel_agents.channel_id, TEXT_CHANNEL_ID))
711
711
  await db.delete(schema.channel_models).where(orm.eq(schema.channel_models.channel_id, TEXT_CHANNEL_ID))
712
712
 
713
+ const existingThreadIds = new Set(
714
+ (await discord.channel(TEXT_CHANNEL_ID).getThreads()).map((thread) => thread.id),
715
+ )
713
716
  await discord.channel(TEXT_CHANNEL_ID).user(TEST_USER_ID).sendMessage({
714
717
  content: 'Reply with exactly: btw-source-msg',
715
718
  })
716
719
 
717
720
  const sourceThread = await discord.channel(TEXT_CHANNEL_ID).waitForThread({
718
721
  timeout: 4_000,
719
- predicate: (t) => {
720
- return t.name === 'Reply with exactly: btw-source-msg'
722
+ predicate: (thread) => {
723
+ return !existingThreadIds.has(thread.id)
721
724
  },
722
725
  })
723
726
 
@@ -742,14 +745,17 @@ describe('agent model resolution', () => {
742
745
  modelId: `${PROVIDER_NAME}/${CHANNEL_MODEL}`,
743
746
  })
744
747
 
748
+ const existingForkThreadIds = new Set(
749
+ (await discord.channel(TEXT_CHANNEL_ID).getThreads()).map((thread) => thread.id),
750
+ )
745
751
  await discord.thread(sourceThread.id).user(TEST_USER_ID).sendMessage({
746
752
  content: 'Reply with exactly: btw-model-check. btw',
747
753
  })
748
754
 
749
755
  const forkedThread = await discord.channel(TEXT_CHANNEL_ID).waitForThread({
750
756
  timeout: 4_000,
751
- predicate: (t) => {
752
- return t.name === 'btw: Reply with exactly: btw-model-check'
757
+ predicate: (thread) => {
758
+ return !existingForkThreadIds.has(thread.id)
753
759
  },
754
760
  })
755
761