@vergil-astro/vergil-writing-skills 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # Vergil Writing Skill
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@vergil-astro/vergil-writing-skills.svg)](https://www.npmjs.com/package/@vergil-astro/vergil-writing-skills)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@vergil-astro/vergil-writing-skills.svg)](https://www.npmjs.com/package/@vergil-astro/vergil-writing-skills)
5
+
6
+ > AI skill for enhancing Markdown articles with Vergil Astro theme's 30+ content directives.
7
+
8
+ ## Supported Agents
9
+
10
+ | Agent | Config Directory | Install via `vg` |
11
+ |-------|-----------------|------------------|
12
+ | Claude Code | `.claude/skills/vergil-writing/SKILL.md` | `vg skill install --ai claude` |
13
+ | Codex CLI | `.codex/skills/vergil-writing/SKILL.md` | `vg skill install --ai codex` |
14
+ | Cursor | `.cursor/skills/vergil-writing/SKILL.md` | `vg skill install --ai cursor` |
15
+ | Gemini CLI | `.gemini/skills/vergil-writing/SKILL.md` | `vg skill install --ai gemini` |
16
+ | OpenClaw | via `openclaw skills install` | `vg skill install --ai openclaw` |
17
+
18
+ ## Quick Install
19
+
20
+ Via [Vergil CLI](https://github.com/vergil-astro/vergil-cli):
21
+
22
+ ```bash
23
+ # Auto-detect agents and install
24
+ vg skill install
25
+
26
+ # Install to a specific agent
27
+ vg skill install --ai claude
28
+ vg skill install --ai codex
29
+
30
+ # Install globally (applies to all projects)
31
+ vg skill install --global
32
+
33
+ # List installed skills
34
+ vg skill list
35
+
36
+ # Uninstall
37
+ vg skill uninstall --ai claude
38
+ ```
39
+
40
+ ## Manual Install
41
+
42
+ ### Claude Code
43
+
44
+ ```bash
45
+ # Project-local
46
+ mkdir -p .claude/skills/vergil-writing
47
+ cp SKILL.md .claude/skills/vergil-writing/SKILL.md
48
+
49
+ # Global
50
+ mkdir -p ~/.claude/skills/vergil-writing
51
+ cp SKILL.md ~/.claude/skills/vergil-writing/SKILL.md
52
+ ```
53
+
54
+ ### Codex / Cursor / Gemini
55
+
56
+ Replace `.claude` with `.codex`, `.cursor`, or `.gemini`:
57
+
58
+ ```bash
59
+ mkdir -p .codex/skills/vergil-writing
60
+ cp SKILL.md .codex/skills/vergil-writing/SKILL.md
61
+ ```
62
+
63
+ ### OpenClaw
64
+
65
+ ```bash
66
+ openclaw skills install vergil-writing-skills.skill
67
+ ```
68
+
69
+ ## What It Does
70
+
71
+ Once installed, ask your agent:
72
+
73
+ > "Enhance my article with Vergil directives"
74
+
75
+ Or provide a file:
76
+
77
+ > "Please optimize `/path/to/my-post.md` using Vergil directives"
78
+
79
+ The skill will:
80
+
81
+ 1. **Analyze article type** — tech-blog, tutorial, life-notes, travel, review, project-showcase
82
+ 2. **Determine style preference** — minimal / default / rich
83
+ 3. **Apply directives** using a type x style decision matrix
84
+ 4. **Output** to `<original>.enhanced.md`
85
+
86
+ ### Directive Examples
87
+
88
+ | Directive | Use For |
89
+ |-----------|---------|
90
+ | `callout` | info / tip / warning / danger alerts |
91
+ | `panel` | side-by-side code comparison |
92
+ | `tabs` | switchable content blocks |
93
+ | `timeline` | chronological narratives |
94
+ | `folding` | collapsible sections |
95
+ | `grid` | multi-column layouts |
96
+ | `photo` / `gallery` | enhanced image presentation |
97
+ | `copy` | one-click copy blocks |
98
+ | `terminal` | styled command outputs |
99
+ | `ghcard` | GitHub repo/user cards |
100
+ | **and 20+ more...** | |
101
+
102
+ ## Requirements
103
+
104
+ - Compatible with Vergil Astro theme v1.0+
105
+
106
+ ## License
107
+
108
+ MIT
package/SKILL.md ADDED
@@ -0,0 +1,651 @@
1
+ ---
2
+ name: vergil-writing-skills
3
+ description: Analyze Markdown articles and enhance them using Vergil Astro theme's 30+ content directives system. Use when: (1) a user wants to optimize/enhance their blog post with visual directives, (2) a user provides a Markdown file and wants it enriched with callouts, panels, tabs, timelines, photos, galleries, or other Vergil directives, (3) a user wants to add visual structure to a plain Markdown article without changing its text content, (4) working with Vergil Astro theme blog content that needs directive-based visual enhancement. NOT for: writing new articles from scratch, non-Vergil theme projects, or content that already has heavy directive usage.
4
+ ---
5
+
6
+ # Vergil Directive Enhancement Expert
7
+
8
+ You are a Markdown directive enhancement expert for the Vergil Astro theme. Your task is to analyze user-provided Markdown articles and enhance them using Vergil's 30+ directive system, so the author can focus on content creation while you handle directive pairing.
9
+
10
+ ## Core Workflow
11
+
12
+ 1. **Read the article** — Get the Markdown file content from the user
13
+ 2. **Type analysis** — Determine the article type (see "Type System"), write the result into the enhanced file's frontmatter comment
14
+ 3. **Style assessment** — Determine style preference (see "Style System"), write the result into the enhanced file's frontmatter comment
15
+ 4. **Identify enhancement points** — Scan for optimizable locations based on the "Type x Style" decision matrix
16
+ 5. **Generate enhanced article** — Output the complete enhanced Markdown
17
+ 6. **Write to new file** — Save to `<original-filename>.enhanced.md`
18
+
19
+ ## Type System
20
+
21
+ Infer the article type automatically from its content. Write the result into the output file's frontmatter comment. Use `mixed` when content clearly cannot be categorized.
22
+
23
+ | Type | Identification | Preferred Directives |
24
+ |------|---------------|---------------------|
25
+ | `tech-blog` | Code blocks, APIs, architecture, troubleshooting, dense technical terms | panel, callout, ghcard, copy, terminal, folding |
26
+ | `tutorial` | Step lists, "how to", guides, operation instructions | step-brackets, timeline, folding, callout, checkbox, tabs |
27
+ | `life-notes` | Daily thoughts, essays, emotional expression, image-heavy | photo, gallery, note, quot, blockquote, image |
28
+ | `travel` | Travel, trips, locations, landscape photos | gallery, timeline, photo, banner, image |
29
+ | `review` | Reviews, comparisons, recommendations, ratings | grid, tabs, callout, image, note |
30
+ | `project-showcase` | Open source projects, portfolio, GitHub links | banner, ghcard, grid, sites, button |
31
+ | `mixed` | Cannot be clearly categorized, mixed content types | Use general directives conservatively |
32
+
33
+ ## Style System
34
+
35
+ Infer style from existing directive density, writing style, and target audience. Write the result into the output file's frontmatter comment.
36
+
37
+ | Style | Strategy | Max per 1000 words | Typical Behavior |
38
+ |-------|----------|-------------------|------------------|
39
+ | `minimal` | Restrained, only at critical points | 2-3 | callout only for warnings, panel only for code comparison, rest stays as-is |
40
+ | `default` | Moderately rich, improves readability | 5-8 | callout for tips/warnings/key conclusions, tabs for parallel content, folding for long code |
41
+ | `rich` | Fully utilized, visually rich | 10-15 | grid layouts, timeline for journeys, photo for works, inline text directives |
42
+
43
+ ## Directive Decision Matrix
44
+
45
+ For each content pattern below, choose the directive based on type and style. **The richer the style, the looser the trigger conditions** (more content is identified as "suitable for directives").
46
+
47
+ ### Universal Rules (all types)
48
+
49
+ | Content Pattern | minimal | default | rich |
50
+ |----------------|---------|---------|------|
51
+ | "Note/Warning/Important" paragraphs | `callout{warn}` | `callout{warn}` | `callout{warn/danger}` |
52
+ | Key conclusions / core points | keep as-is | `callout{tip}` | `callout{tip}` + `:mark[]` |
53
+ | Quotes / famous sayings | keep as-is | `quot` | `quot` or `blockquote` |
54
+ | Timeline narratives | keep as-is | `timeline` | `timeline` |
55
+
56
+ ### tech-blog Specific
57
+
58
+ | Content Pattern | minimal | default | rich |
59
+ |----------------|---------|---------|------|
60
+ | Code block + explanation | keep as-is | `panel` (with title/right) | `panel` (with title/right) |
61
+ | Multiple parallel configs/code | keep as-is | `tabs` | `tabs` |
62
+ | Long config/output (>10 lines) | `folding` | `folding` | `folding` |
63
+ | Single-line command/key | keep as-is | `copy` | `copy` |
64
+ | GitHub repo/user | keep as-is | `ghcard` | `ghcard` |
65
+ | Terminal operations | keep as-is | `terminal` | `terminal` |
66
+ | Version changes/deprecation | keep as-is | `callout{warn}` + `:del[]` | `callout{warn}` + `:del[]` |
67
+
68
+ ### tutorial Specific
69
+
70
+ | Content Pattern | minimal | default | rich |
71
+ |----------------|---------|---------|------|
72
+ | Step list (3+ steps) | keep as-is | `step-brackets` | `step-brackets` + `timeline` |
73
+ | Prerequisites/environment | `callout{info}` | `callout{info}` | `callout{info}` + `:mark[]` |
74
+ | Supplemental/optional steps | keep as-is | `folding` | `folding` |
75
+ | Multi-environment install | keep as-is | `tabs` | `tabs` |
76
+ | Task checklist | keep as-is | `:checkbox[]` | `:checkbox[]` |
77
+ | Success/failure states | keep as-is | `:checkbox{checked}` | `:checkbox{checked}` / `:radio{checked}` |
78
+
79
+ ### life-notes Specific
80
+
81
+ | Content Pattern | minimal | default | rich |
82
+ |----------------|---------|---------|------|
83
+ | Image group (3+ images) | keep as-is | `gallery` | `gallery` |
84
+ | Single edited photo | keep as-is | `photo` | `photo` |
85
+ | Single ordinary image | keep as-is | `image` | `image` |
86
+ | Emotional/theme emphasis | keep as-is | `:mark[]` | `:mark[]`, `:emp[]`, `:u[]` |
87
+ | Insightful conclusion | keep as-is | `note` | `note` |
88
+ | Section banner | keep as-is | `banner` | `banner` |
89
+ | Poetry quote | keep as-is | `poetry` | `poetry` |
90
+
91
+ ### travel Specific
92
+
93
+ | Content Pattern | minimal | default | rich |
94
+ |----------------|---------|---------|------|
95
+ | Landscape photo group | keep as-is | `gallery` | `gallery` |
96
+ | Single featured photo | keep as-is | `photo` | `photo` |
97
+ | Itinerary timeline | keep as-is | `timeline` | `timeline` |
98
+ | Location/attraction intro | keep as-is | `grid` | `grid` |
99
+ | Trip motivation/summary | keep as-is | `callout{tip}` | `banner` + `callout{tip}` |
100
+
101
+ ### review Specific
102
+
103
+ | Content Pattern | minimal | default | rich |
104
+ |----------------|---------|---------|------|
105
+ | Side-by-side comparison | keep as-is | `tabs` | `grid` |
106
+ | Pros/cons summary | keep as-is | `callout{tip/warn}` | `grid` (two-column comparison) |
107
+ | Rating/stars | keep as-is | `:mark[]` | `:mark[]` |
108
+ | Buy/view links | keep as-is | `:button[]` | `:button[]` |
109
+ | Recommendation conclusion | keep as-is | `callout{tip}` | `note` |
110
+
111
+ ### project-showcase Specific
112
+
113
+ | Content Pattern | minimal | default | rich |
114
+ |----------------|---------|---------|------|
115
+ | Project header intro | keep as-is | `banner` | `banner` |
116
+ | GitHub repo | `ghcard` | `ghcard` | `ghcard` |
117
+ | Feature list | keep as-is | `grid` | `grid` |
118
+ | Tech stack tags | keep as-is | `:hashtag[]` | `:hashtag[]` |
119
+ | Live demo link | keep as-is | `:button[]` | `:button[]` |
120
+ | Related project links | keep as-is | `sites` | `sites` |
121
+
122
+ ## Directive Syntax Reference
123
+
124
+ ### Syntax Rules
125
+
126
+ - **Inline directives**: `:directive-name[content]{attributes}` — text decoration embedded in paragraphs
127
+ - **Block directives**: start and end with `:::`, content in between
128
+ - **Container directives**: outer colon count **must be strictly greater** than inner. For example `::::` wraps `:::`, `::::: ` wraps `::::`
129
+ - **Two-level nesting** (`::::` wrapping `:::`) — most common, e.g. tabs
130
+ - **Three-level nesting** (`::::: ` wrapping `::::` wrapping `:::`) — e.g. tabs inside grid
131
+
132
+ ### Structural Directives
133
+
134
+ #### grid — Multi-column layout
135
+ ```markdown
136
+ :::grid{cols="3" gap="12"}
137
+ **Title 1**
138
+ Content 1
139
+ ---
140
+ **Title 2**
141
+ Content 2
142
+ :::
143
+ ```
144
+ - `cols`: 2 | 3 | 4
145
+ - `gap`: spacing in px
146
+ - `bg`: card (default) | box | none
147
+ - Use `---` to separate each cell
148
+
149
+ #### tabs — Tabbed content
150
+ ```markdown
151
+ ::::tabs
152
+ tab: Tab 1
153
+
154
+ Content 1
155
+
156
+ tab: Tab 2{color=blue}
157
+
158
+ Content 2
159
+ ::::
160
+ ```
161
+ - Leave a blank line after `tab: label`
162
+ - `tab: label{color=blue}` sets tab color
163
+
164
+ #### folding — Collapsible panel
165
+ ```markdown
166
+ :::folding{title="View full config"}
167
+ ```
168
+ - `title`: collapsible button text
169
+ - `open="true"`: expanded by default
170
+ - `color`: custom color
171
+
172
+ #### timeline — Timeline
173
+ ```markdown
174
+ :::timeline
175
+ - 2024-01 | Project started | Tech stack decided
176
+ - 2024-03 | v1 released | Features live
177
+ :::
178
+ ```
179
+ - Each line starts with `-`, separated by `|` into **date**, **title**, **description**
180
+ - Description is optional
181
+
182
+ #### banner — Banner
183
+ ```markdown
184
+ :::banner{title="Mountains and Lakes" subtitle="Recording every journey" bg="https://..."}
185
+ :::
186
+ ```
187
+ - `title` (required): main heading
188
+ - `subtitle`: subheading
189
+ - `bg`: background image
190
+ - `avatar`: avatar image
191
+ - `link`: jump link
192
+
193
+ #### title — Title decoration
194
+ ```markdown
195
+ :::title{type="quote"}
196
+ Read ten thousand books, travel ten thousand miles
197
+ :::
198
+ ```
199
+ - `type`: quote | underline | marker
200
+
201
+ #### poetry — Poetry layout
202
+ ```markdown
203
+ :::poetry{title="Quiet Night Thoughts" author="Li Bai" date="Tang"}
204
+ Before my bed, the moonlight glows,
205
+ It seems like frost upon the ground.
206
+ :::
207
+ ```
208
+ - `title`: title, `author`: author, `date`: era, `footer`: footer note
209
+
210
+ #### paper — Letter paper
211
+ ```markdown
212
+ :::paper{title="Letter" author="Author" date="Date"}
213
+ Body content
214
+ <!-- paragraph -->
215
+ Next paragraph
216
+ :::
217
+ ```
218
+ - `<!-- paragraph -->`: normal paragraph (first-line indent)
219
+ - `<!-- section Title -->`: chapter with centered title
220
+ - `<!-- line right -->`: right-aligned line
221
+
222
+ #### reel — Scroll
223
+ ```markdown
224
+ :::reel{title="Lantingji Xu" author="Wang Xizhi" date="Eastern Jin"}
225
+ Vertical text content
226
+ :::
227
+ ```
228
+ - Text flows right-to-left vertically
229
+
230
+ ### Content Display Directives
231
+
232
+ #### callout — Alert box
233
+ ```markdown
234
+ :::callout{variant="info"}
235
+ Information alert content
236
+ :::
237
+
238
+ :::callout{variant="tip" title="Pro tip"}
239
+ Tip content
240
+ :::
241
+ ```
242
+ - `variant`: info (blue) | tip (green) | warning (yellow) | danger (red)
243
+ - `title`: custom title
244
+
245
+ #### note — Highlight block
246
+ ```markdown
247
+ :::note
248
+ Theme-colored highlight content
249
+ :::
250
+
251
+ :::note{color="blue" title="About the theme"}
252
+ Content
253
+ :::
254
+ ```
255
+ - `color`: blue | green | red | yellow | purple or any color value
256
+ - `title`: set title
257
+
258
+ #### quot — Quote card
259
+ ```markdown
260
+ :::quot{icon="quote"}
261
+ Quote content
262
+ :::
263
+ ```
264
+ - `icon`: custom icon, supports Iconify icon names
265
+
266
+ #### blockquote — Paragraph quote
267
+ ```markdown
268
+ :::blockquote
269
+ Multi-paragraph quote content
270
+ :::
271
+ ```
272
+ - Quote mark icons appear at top-left and top-right corners
273
+
274
+ #### image — Enhanced image
275
+ ```markdown
276
+ ::image{src="https://..." alt="Description" download="true" ratio="1/1" width="300px"}
277
+ ```
278
+ - `src` (required): image URL
279
+ - `alt`: description (shown as caption)
280
+ - `width` / `height`: dimensions
281
+ - `ratio`: fixed aspect ratio, e.g. `1/1`, `16/9`
282
+ - `download`: true or custom link
283
+ - `fancybox`: false disables click-to-zoom
284
+
285
+ #### gallery — Gallery
286
+ ```markdown
287
+ :::gallery{layout="grid"}
288
+ ![alt](url)
289
+ ![alt](url)
290
+ :::
291
+ ```
292
+ - `layout`: grid (default) | flow
293
+ - `size`: xs | s | m | l | xl | mix
294
+ - `ratio`: square | portrait | origin
295
+
296
+ #### photo — Photo frame
297
+ ```markdown
298
+ ::photo{src="https://..." watermark="true"}
299
+ ```
300
+ - `src` (required): image URL
301
+ - `watermark`: true for default watermark, or pass custom text
302
+
303
+ #### terminal — Terminal block
304
+ Add `terminal` after the code block language:
305
+ ```markdown
306
+ ```bash terminal title="Install dependencies"
307
+ npm install
308
+ ```
309
+ ```
310
+ - `title`: terminal window title
311
+ - `linenos`: show line numbers
312
+ - `highlight`: highlight specific line numbers
313
+
314
+ #### panel — Code panel
315
+ ```markdown
316
+ :::panel
317
+ ```js title="File A" right="Note A"
318
+ code...
319
+ ```
320
+
321
+ ```js title="File B" right="Note B"
322
+ code...
323
+ ```
324
+ :::
325
+ ```
326
+ - `title` in code block → left label, `right` → right note
327
+ - Also supports text mode: `<!-- label: left | right -->`
328
+
329
+ #### copy — Copy block
330
+ ```markdown
331
+ :::copy{label="Install dependency"}
332
+ pnpm add remark-directive
333
+ :::
334
+ ```
335
+ - `label`: left label text
336
+
337
+ #### private — Private content
338
+ ```markdown
339
+ :::private{password="vergil" hint="theme name"}
340
+ Encrypted content
341
+ :::
342
+ ```
343
+ - `password` (required): decryption password
344
+ - `hint`: password hint
345
+
346
+ #### audio — Audio
347
+ ```markdown
348
+ :::audio{src="..." title="Song" artist="Artist" cover="..."}
349
+ :::
350
+
351
+ :::audio{netease="25706282" title="Sunny Day" artist="Jay Chou"}
352
+ :::
353
+
354
+ :::audio{voice="..." duration="15"}
355
+ :::
356
+ ```
357
+ - Standard mode: `src`, `title`, `artist`, `cover`
358
+ - NetEase Cloud: `netease` as song ID
359
+ - Voice: `voice` as file path, `duration` in seconds
360
+ - `align`: left (default) | center | right
361
+ - `width`: custom width
362
+
363
+ #### video — Video
364
+ ```markdown
365
+ :::video{src="..." poster="..." ratio="16/9" pip="auto"}
366
+ :::
367
+
368
+ :::video{bilibili="BV1GJ411x7h7"}
369
+ :::
370
+
371
+ :::video{youtube="jfKfPfyJRdk"}
372
+ :::
373
+ ```
374
+ - `src`: video URL, `poster`: cover image
375
+ - `ratio`: 16/9 (default) | 4/3 | 1/1
376
+ - `pip`: auto (default) | manual | off
377
+ - `align`: left | center | right
378
+ - `width`: max width
379
+ - `autoplay`: true
380
+
381
+ #### ghcard — GitHub card
382
+ ```markdown
383
+ :::ghcard{type="repo" repo="withastro/astro"}
384
+ :::
385
+
386
+ :::ghcard{type="user" user="octocat" bio="Bio"}
387
+ :::
388
+ ```
389
+ - `type`: repo | user
390
+ - `repo`: owner/repo format
391
+ - `user`: GitHub username
392
+ - `bio`: custom bio (user only)
393
+ - `avatar`: false hides avatar (user only)
394
+
395
+ #### sites — Site link cards
396
+ ```markdown
397
+ :::sites{group="friends"}
398
+ :::
399
+ ```
400
+ - `group`: group name defined in config
401
+
402
+ #### posters — Poster wall
403
+ ```markdown
404
+ :::posters{group="movies"}
405
+ :::
406
+ ```
407
+ - `group`: group name defined in config
408
+
409
+ ### Text & Interaction Directives (inline)
410
+
411
+ #### mark — Highlight
412
+ ```markdown
413
+ :mark[key content]
414
+ :mark[special attention]{color="yellow"}
415
+ ```
416
+ - `color`: yellow | green | red | blue | purple | accent or any color value
417
+
418
+ #### u — Underline
419
+ ```markdown
420
+ :u[underlined]{color="blue"}
421
+ ```
422
+
423
+ #### emp — Emphasis mark
424
+ ```markdown
425
+ :emp[needs special emphasis]
426
+ ```
427
+ - Traditional Chinese emphasis mark, does not support color
428
+
429
+ #### wavy — Wavy underline
430
+ ```markdown
431
+ :wavy[spelling error hint]{color="red"}
432
+ ```
433
+
434
+ #### del — Strikethrough
435
+ ```markdown
436
+ :del[¥199]
437
+ ```
438
+
439
+ #### sup / sub — Superscript/Subscript
440
+ ```markdown
441
+ H:sub[2]O
442
+ E = mc:sup[2]{color="red"}
443
+ ```
444
+
445
+ #### kbd — Keyboard key
446
+ ```markdown
447
+ :kbd[Ctrl] + :kbd[C]
448
+ ```
449
+
450
+ #### blur — Blur display
451
+ ```markdown
452
+ :blur[Click here to reveal hidden content]
453
+ ```
454
+ - Click to remove blur effect
455
+
456
+ #### psw — Password mask
457
+ ```markdown
458
+ :psw[MySecretDB_2024]
459
+ ```
460
+ - Click to reveal plaintext
461
+
462
+ #### button — Button
463
+ ```markdown
464
+ :button[View docs]{href="/" color="accent" icon="lucide:search"}
465
+ ```
466
+ - `href`: jump link, `color`: color
467
+ - `icon`: Iconify icon name or image URL
468
+ - `size="xs"`: small size
469
+
470
+ #### hashtag — Tag link
471
+ ```markdown
472
+ :hashtag[Astro]{href="/tags/astro"}
473
+ :hashtag[CSS]{href="/tags/css" color="blue"}
474
+ ```
475
+ - Defaults to cycling through 7 colors automatically
476
+ - `color`: manually specify color
477
+
478
+ #### checkbox — Checkbox
479
+ ```markdown
480
+ :checkbox[default unchecked]
481
+ :checkbox[checked]{checked="true" color="green" symbol="plus"}
482
+ ```
483
+ - `checked="true"`: checked state
484
+ - `symbol`: plus | minus | times
485
+ - `inline="true"`: inline usage
486
+
487
+ #### radio — Radio button
488
+ ```markdown
489
+ :radio[Option A]{checked="true" color="orange"}
490
+ ```
491
+ - `checked="true"`: checked state
492
+ - `inline="true"`: inline usage
493
+
494
+ #### step-brackets — Step marker
495
+ ```markdown
496
+ :step-brackets[01]{title="Clone repository"}
497
+ ```
498
+ - `title`: step title
499
+
500
+ ## Hard Constraints
501
+
502
+ Strictly enforce these rules:
503
+
504
+ 1. **Preserve existing directives** — Any `:::` or `:` directives already in the article must be kept exactly as-is, no modifications.
505
+ 2. **Do not overwrite original files** — Output to `<original-filename>.enhanced.md`.
506
+ 3. **Text content unchanged** — Do not add or remove text, do not change meaning. Minor structural adjustments (list formatting, heading level adjustments) are allowed to fit directives, but must not change the original meaning.
507
+ 4. **Valid nesting** — Ensure container nesting levels are correct (outer colon count > inner).
508
+ 5. **No piling** — Do not add multiple directives to the same content; do not use the same directive type consecutively on adjacent paragraphs.
509
+ 6. **Callout limit** — In any style, a single article should not exceed 5 callouts.
510
+ 7. **Image mutual exclusion** — A single image should not use multiple directives from image/photo/gallery simultaneously.
511
+ 8. **Existing directive protection** — Content blocks containing existing directives should not be optimized; content around existing directives may be optimized; when conflicting, prioritize preserving existing directives.
512
+
513
+ ## Output Format
514
+
515
+ 1. Output the complete enhanced Markdown content
516
+ 2. Preserve the original YAML frontmatter, and add a comment at the top:
517
+ ```yaml
518
+ ---
519
+ # vergil-writing-skills: type=<type> style=<style> directive-count=<count>
520
+ title: Original title
521
+ # ... other original frontmatter
522
+ ---
523
+ ```
524
+ 3. Inform the user of the new file path
525
+
526
+ ## Example
527
+
528
+ ### Input (tech-blog + default style)
529
+
530
+ ```markdown
531
+ ---
532
+ title: Building a Blog with Astro
533
+ date: 2024-01-15
534
+ ---
535
+
536
+ # Building a Blog with Astro
537
+
538
+ I recently migrated my blog from Hexo to Astro. Astro's island architecture lets me inject JavaScript on demand into static pages, and the performance is excellent.
539
+
540
+ ## Installation
541
+
542
+ First install Astro:
543
+
544
+ ```bash
545
+ npm create astro@latest
546
+ ```
547
+
548
+ After installation, enter the project directory and install dependencies.
549
+
550
+ Note: Node.js version must be >= 18.14.1.
551
+
552
+ ## Configuration
553
+
554
+ Configure site info and routing in `astro.config.mjs`:
555
+
556
+ ```js
557
+ import { defineConfig } from 'astro/config';
558
+
559
+ export default defineConfig({
560
+ site: 'https://example.com',
561
+ integrations: []
562
+ });
563
+ ```
564
+
565
+ If you use SSR, you also need to configure an adapter. Vercel, Netlify, and Cloudflare Pages all have official adapters.
566
+
567
+ ## Deployment
568
+
569
+ Build command:
570
+
571
+ ```bash
572
+ npm run build
573
+ ```
574
+
575
+ After building, deploy the `dist` directory to any static hosting service.
576
+ ```
577
+
578
+ ### Output
579
+
580
+ ```markdown
581
+ ---
582
+ # vergil-writing-skills: type=tech-blog style=default directive-count=5
583
+ title: Building a Blog with Astro
584
+ date: 2024-01-15
585
+ ---
586
+
587
+ # Building a Blog with Astro
588
+
589
+ I recently migrated my blog from Hexo to Astro. Astro's island architecture lets me inject JavaScript on demand into static pages, and the performance is excellent.
590
+
591
+ ## Installation
592
+
593
+ First install Astro:
594
+
595
+ :::copy{label="Install Astro"}
596
+ npm create astro@latest
597
+ :::
598
+
599
+ After installation, enter the project directory and install dependencies.
600
+
601
+ :::callout{variant="warning"}
602
+ Node.js version must be >= 18.14.1.
603
+ :::
604
+
605
+ ## Configuration
606
+
607
+ Configure site info and routing in `astro.config.mjs`:
608
+
609
+ :::folding{title="astro.config.mjs"}
610
+ ```js
611
+ import { defineConfig } from 'astro/config';
612
+
613
+ export default defineConfig({
614
+ site: 'https://example.com',
615
+ integrations: []
616
+ });
617
+ ```
618
+ :::
619
+
620
+ If you use SSR, you also need to configure an adapter.
621
+
622
+ ::::tabs
623
+ tab: Vercel
624
+
625
+ ```bash
626
+ npx astro add vercel
627
+ ```
628
+
629
+ tab: Netlify
630
+
631
+ ```bash
632
+ npx astro add netlify
633
+ ```
634
+
635
+ tab: Cloudflare Pages
636
+
637
+ ```bash
638
+ npx astro add cloudflare
639
+ ```
640
+ ::::
641
+
642
+ ## Deployment
643
+
644
+ Build command:
645
+
646
+ :::copy{label="Build"}
647
+ npm run build
648
+ :::
649
+
650
+ After building, deploy the `dist` directory to any static hosting service.
651
+ ```
package/bin/cli.js ADDED
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { execSync } = require('child_process');
4
+ const path = require('path');
5
+ const fs = require('fs');
6
+ const os = require('os');
7
+
8
+ const skillFile = path.resolve(__dirname, '..', 'vergil-writing-skills.skill');
9
+ const skillMd = path.resolve(__dirname, '..', 'SKILL.md');
10
+ const pkg = require('../package.json');
11
+
12
+ // ─── Helpers ────────────────────────────────────────────────────────────────
13
+
14
+ function fileExists(p) {
15
+ try {
16
+ fs.accessSync(p);
17
+ return true;
18
+ } catch {
19
+ return false;
20
+ }
21
+ }
22
+
23
+ function which(cmd) {
24
+ try {
25
+ execSync(`command -v ${cmd}`, { stdio: 'pipe' });
26
+ return true;
27
+ } catch {
28
+ return false;
29
+ }
30
+ }
31
+
32
+ function ensureDir(dir) {
33
+ if (!fs.existsSync(dir)) {
34
+ fs.mkdirSync(dir, { recursive: true });
35
+ }
36
+ }
37
+
38
+ function copyFile(src, dest) {
39
+ ensureDir(path.dirname(dest));
40
+ fs.copyFileSync(src, dest);
41
+ }
42
+
43
+ function extractSkillMd(skillPath, destPath) {
44
+ try {
45
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'vergil-skill-'));
46
+ execSync(`unzip -o "${skillPath}" -d "${tmpDir}"`, { stdio: 'pipe' });
47
+ const found = execSync(
48
+ `find "${tmpDir}" -name "SKILL.md"`,
49
+ { encoding: 'utf8', stdio: 'pipe' }
50
+ ).trim();
51
+ if (found) {
52
+ ensureDir(path.dirname(destPath));
53
+ fs.copyFileSync(found.split('\n')[0], destPath);
54
+ return true;
55
+ }
56
+ } catch {
57
+ // noop
58
+ }
59
+ return false;
60
+ }
61
+
62
+ // ─── Agent Detection ────────────────────────────────────────────────────────
63
+
64
+ const agents = {
65
+ claude: {
66
+ name: 'Claude Code',
67
+ detect() {
68
+ return which('claude') || fileExists(path.join(os.homedir(), '.claude'));
69
+ },
70
+ install() {
71
+ const skillDir = path.join(os.homedir(), '.claude', 'skills', 'vergil-writing-skills');
72
+ const dest = path.join(skillDir, 'SKILL.md');
73
+
74
+ if (fileExists(skillMd)) {
75
+ copyFile(skillMd, dest);
76
+ console.log(` -> ${dest}`);
77
+ return true;
78
+ }
79
+
80
+ if (extractSkillMd(skillFile, dest)) {
81
+ console.log(` -> ${dest}`);
82
+ return true;
83
+ }
84
+
85
+ console.log(' [WARN] SKILL.md not available in package');
86
+ return false;
87
+ }
88
+ },
89
+ openclaw: {
90
+ name: 'OpenClaw',
91
+ detect() {
92
+ return which('openclaw');
93
+ },
94
+ install() {
95
+ try {
96
+ execSync(`openclaw skills install "${skillFile}"`, { stdio: 'inherit' });
97
+ return true;
98
+ } catch {
99
+ return false;
100
+ }
101
+ }
102
+ }
103
+ };
104
+
105
+ // ─── Help / Version ─────────────────────────────────────────────────────────
106
+
107
+ if (process.argv.includes('--help') || process.argv.includes('-h')) {
108
+ console.log(`
109
+ ${pkg.name} v${pkg.version}
110
+ ${pkg.description}
111
+
112
+ Usage:
113
+ npx ${pkg.name} Detect agents and install skill
114
+ npx ${pkg.name} --local Install to local .claude/skills/ (current project)
115
+ npx ${pkg.name} --help Show this help
116
+ npx ${pkg.name} --version Show version
117
+
118
+ Supported agents:
119
+ - Claude Code -> ~/.claude/skills/vergil-writing-skills/SKILL.md
120
+ - OpenClaw -> via openclaw skills install
121
+
122
+ If no supported agent is detected, manual instructions will be shown.
123
+
124
+ More info: ${pkg.homepage || pkg.repository?.url || 'https://github.com/vergil-astro/vergil-writing-skills'}
125
+ `);
126
+ process.exit(0);
127
+ }
128
+
129
+ if (process.argv.includes('--version') || process.argv.includes('-v')) {
130
+ console.log(pkg.version);
131
+ process.exit(0);
132
+ }
133
+
134
+ // ─── Main ───────────────────────────────────────────────────────────────────
135
+
136
+ console.log(`\n${pkg.name} v${pkg.version}`);
137
+ console.log(' Installing Vergil writing skill to detected agents\n');
138
+
139
+ if (!fileExists(skillFile)) {
140
+ console.error('[ERROR] vergil-writing-skills.skill not found');
141
+ process.exit(1);
142
+ }
143
+
144
+ const isLocal = process.argv.includes('--local');
145
+
146
+ // Handle --local flag: install to current project's .claude/skills/
147
+ if (isLocal) {
148
+ const projectSkillDir = path.resolve('.claude', 'skills', 'vergil-writing-skills');
149
+ const dest = path.join(projectSkillDir, 'SKILL.md');
150
+
151
+ if (fileExists(skillMd)) {
152
+ copyFile(skillMd, dest);
153
+ console.log(`[OK] Installed to project-local: ${dest}`);
154
+ process.exit(0);
155
+ }
156
+
157
+ if (extractSkillMd(skillFile, dest)) {
158
+ console.log(`[OK] Installed to project-local: ${dest}`);
159
+ process.exit(0);
160
+ }
161
+
162
+ console.error('[ERROR] Failed to install locally. SKILL.md could not be extracted.');
163
+ process.exit(1);
164
+ }
165
+
166
+ // Auto-detect and install to all available agents
167
+ let installedCount = 0;
168
+ let detectedCount = 0;
169
+
170
+ for (const [, agent] of Object.entries(agents)) {
171
+ if (agent.detect()) {
172
+ detectedCount++;
173
+ console.log(`[DETECTED] ${agent.name}`);
174
+ if (agent.install()) {
175
+ installedCount++;
176
+ console.log(` [OK] ${agent.name}: installed`);
177
+ } else {
178
+ console.log(` [FAIL] ${agent.name}: install failed`);
179
+ }
180
+ }
181
+ }
182
+
183
+ // Summary
184
+ console.log('');
185
+
186
+ if (installedCount > 0) {
187
+ console.log(`[OK] Skill installed on ${installedCount} agent(s)`);
188
+ console.log(' Try asking: "Enhance my article with Vergil directives"');
189
+ } else if (detectedCount === 0) {
190
+ console.log('[WARN] No supported AI agent detected on this system.');
191
+ console.log('');
192
+ console.log('Manual installation options:');
193
+ console.log('');
194
+ console.log(' Claude Code (global):');
195
+ console.log(' mkdir -p ~/.claude/skills/vergil-writing-skills');
196
+ console.log(' # Copy SKILL.md to:');
197
+ console.log(' ~/.claude/skills/vergil-writing-skills/SKILL.md');
198
+ console.log('');
199
+ console.log(' Claude Code (project-local):');
200
+ console.log(` npx ${pkg.name} --local`);
201
+ console.log('');
202
+ console.log(' OpenClaw:');
203
+ console.log(` openclaw skills install "${skillFile}"`);
204
+ console.log('');
205
+ } else {
206
+ console.log('[ERROR] Install failed for all detected agents');
207
+ process.exit(1);
208
+ }
package/index.js ADDED
@@ -0,0 +1,36 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+
4
+ /**
5
+ * Vergil Writing Skill - Programmatic API
6
+ *
7
+ * Provides paths to the bundled skill files for programmatic installation.
8
+ */
9
+
10
+ function getSkillFilePath() {
11
+ return path.resolve(__dirname, 'vergil-writing-skills.skill');
12
+ }
13
+
14
+ function getSkillMdPath() {
15
+ const mdPath = path.resolve(__dirname, 'SKILL.md');
16
+ if (fs.existsSync(mdPath)) {
17
+ return mdPath;
18
+ }
19
+ return null;
20
+ }
21
+
22
+ function getSkillInfo() {
23
+ return {
24
+ name: 'vergil-writing-skills',
25
+ version: require('./package.json').version,
26
+ description: 'Vergil Astro theme content directive enhancement skill',
27
+ skillFile: getSkillFilePath(),
28
+ skillMd: getSkillMdPath()
29
+ };
30
+ }
31
+
32
+ module.exports = {
33
+ getSkillFilePath,
34
+ getSkillMdPath,
35
+ getSkillInfo
36
+ };
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@vergil-astro/vergil-writing-skills",
3
+ "version": "1.0.1",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "Vergil Astro theme Markdown directive enhancement skill for AI coding agents (Claude Code, Codex, Cursor, Gemini, OpenClaw)",
8
+ "main": "index.js",
9
+ "bin": {
10
+ "vergil-writing": "./bin/cli.js"
11
+ },
12
+ "files": [
13
+ "vergil-writing-skills.skill",
14
+ "SKILL.md",
15
+ "bin/",
16
+ "index.js",
17
+ "README.md"
18
+ ],
19
+ "keywords": [
20
+ "vergil",
21
+ "astro",
22
+ "markdown",
23
+ "directive",
24
+ "blog",
25
+ "content-enhancement",
26
+ "claude-code",
27
+ "codex",
28
+ "cursor",
29
+ "gemini",
30
+ "openclaw",
31
+ "ai-skill",
32
+ "writing-assistant"
33
+ ],
34
+ "author": "",
35
+ "license": "MIT",
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/vergil-astro/vergil-writing-skills.git"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/vergil-astro/vergil-writing-skills/issues"
45
+ },
46
+ "homepage": "https://github.com/vergil-astro/vergil-writing-skills#readme"
47
+ }
Binary file