@natjswenson/devlog 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/package.json +1 -1
  2. package/CHANGELOG.md +0 -164
  3. package/LICENSE +0 -21
  4. package/README.md +0 -240
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@natjswenson/devlog",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Release dev log generator \u2014 Claude Code skill + preview app for publishing version-release dev logs, written in your voice, to your site",
5
5
  "license": "MIT",
6
6
  "author": "Nate Swenson",
package/CHANGELOG.md DELETED
@@ -1,164 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to `@natjswenson/devlog` are documented here.
4
-
5
- ## 0.4.0 (2026-06-28) — researched, end-to-end implementation-guide posts
6
-
7
- **Changed**
8
- - `/devlog` now writes each release entry as a researched, cited, end-to-end
9
- implementation guide rather than a narrative summary of what shipped. Step 6
10
- derives the engineering topic(s) the work touched, researches them against
11
- reputable outside sources (cited inline and in a `## Sources` section), and
12
- writes a setup → build → use → verify walkthrough with multiple
13
- copy-paste-reusable, language-tagged code blocks that together form a complete,
14
- runnable whole (right-sized: roughly 3-6 essential blocks for a substantive
15
- feature, fewer for a small change, never padded). A short `## Shipped` hook
16
- still opens the post and `## Changelog` still closes it. Updated the skill
17
- description and the Step 6 / 6a-6c guidance accordingly.
18
-
19
- **Added**
20
- - `deepDive` config block: `topicDomains` (default: AI, DevOps/SRE, software
21
- engineering) and `minSources` (default 2) to steer topic selection and the
22
- citation floor. Repo-agnostic; user-supplied values live in `config.json`.
23
-
24
- ## 0.3.1 (2026-06-20) — fetch tags before discovering releases
25
-
26
- **Fixed**
27
- - `/devlog` now runs a best-effort `git fetch --tags --quiet` per project at the
28
- start of release discovery (Step 3), before listing tags. Releases are
29
- commonly cut by CI on the remote (a version-driven GitHub Release on green
30
- `main`/`master`), so the tag is born on the remote; a local clone that hadn't
31
- fetched would list only stale local tags and silently report "no new release"
32
- for a release that was already live. The fetch is best-effort: on failure
33
- (offline, no remote, auth prompt) it notes the failure and proceeds on local
34
- tags rather than aborting. `--tags` takes no untrusted input and `project.path`
35
- is validated + single-quoted per Step 0.5.
36
-
37
- ## 0.3.0 (2026-06-18) — release-focused entries, written in your voice
38
-
39
- **Changed (behavior)**
40
- - `/devlog` now generates one entry **per version release** (a semver git tag) instead of
41
- one entry per day. An entry summarizes the commits in a release's tag range
42
- (`<prevTag>..<thisTag>`), scoped by `pathFilter` when present. The run is **idempotent**:
43
- a release's entry is written once and never overwritten, and re-running produces nothing
44
- until a new tag is cut. The per-day "Update — HH:MM" append mode is removed.
45
- - Entries are keyed by version: `<project-key>/<version>.md` (e.g. `v0.2.0.md`), with a
46
- `version` field added to the frontmatter and to each `manifest.json` entry. Entry sections
47
- are now **What Shipped / What's Next / Commits**. The entry `date` is the tag's commit date.
48
-
49
- **Added**
50
- - **Voice-driven publishing.** Entries are written in the user's voice using a voice profile
51
- resolved in this order: `config.voicePath` → `~/.claude/skills/ghostwriter/voice` (if
52
- installed) → a bundled fallback at `~/.claude/skills/devlog/voice/`. devlog reads
53
- `voice-profile.md` and `voice-notes.md` (overrides) — and never `algorithm.md`, since
54
- LinkedIn reach tuning does not apply to a dev log.
55
- - `voicePath` (top-level, optional) and `projects[].tagPrefix` (optional, default `v`) config
56
- fields, with security validation in both `bin/devlog.js` and SKILL.md. `tagPrefix` lets each
57
- project in a monorepo detect its own releases (e.g. `devlog-v`, `ghostwriter-v`).
58
- - `init` prompts for the voice directory and release tag prefix, and installs the bundled
59
- voice template. `config` shows the voice path and each project's tag pattern.
60
- - The React example carries the optional `version` field through frontmatter parsing and
61
- manifest validation.
62
-
63
- **Migration note:** existing per-day `YYYY-MM-DD.md` entries are left untouched; new entries
64
- are per-release. To detect a monorepo project's releases, set its `tagPrefix`.
65
-
66
- ## 0.2.0 (2026-06-08) — monorepo subdirectory filtering
67
-
68
- **Added**
69
- - `projects[].pathFilter` config field: scope a project's commits to a repo-relative
70
- subdirectory (e.g. `skills/devlog`). Lets several logical projects share one monorepo
71
- `path`/`remote` while each collects only its own subtree's commits. `git log` gains a
72
- `-- <pathFilter>` pathspec; commit links still resolve to `<remote>/commit/<hash>`.
73
- - SKILL.md documents the field, its security validation (no leading `-`/`/`, no `..`,
74
- single-quoted), and the multi-skill monorepo workflow.
75
- - `bin/devlog.js` validates `pathFilter` and shows it as `scope:` in `devlog config`.
76
-
77
- ## 0.1.9 (2026-06-05) — accessibility fix
78
-
79
- **Accessibility**
80
- - The drop-in React component (`examples/react/DevLogPage.jsx`) now exposes the expand/collapse entries as a proper disclosure control. Previously they were mouse-only — a bare `onClick` on `<article>` with no `role`, `tabIndex`, `aria-expanded`, or keyboard handler, so keyboard and screen-reader users could not operate the feed.
81
- - The header carries `role="button"`, `tabIndex={0}`, `aria-expanded`, and `aria-controls` for screen-reader toggle semantics.
82
- - `Enter`/`Space` toggle the focused entry (`preventDefault` on Space stops page scroll).
83
- - `:focus-visible` outline makes keyboard focus visible.
84
- - The toggle moved from the whole card to the header, so links inside an expanded entry are no longer nested in an interactive ancestor and text selection in the body works normally.
85
- - Visuals are unchanged: padding/hover/cursor moved from `.devlog-entry` to `.devlog-header`, with the redundant content padding zeroed so spacing matches.
86
-
87
- ## 0.1.8 (2026-05-01) — final hardening pass
88
-
89
- Closes the four Low-Hardening findings from the second adversarial verification:
90
-
91
- - **L-1:** `validateConfig` now bounds `projects[].label` length (≤200 chars) and rejects control characters. Label apostrophes/quotes/etc are intentionally allowed since label is React text content only — never shell-interpolated. The validator includes an explicit invariant comment to keep this guarantee load-bearing.
92
- - **L-2:** `atomicWriteJSON` uses `wx` (exclusive create) flag, preventing symlink-attack scenarios on shared filesystems where another local user could pre-create the tmp file.
93
- - **L-3:** `atomicWriteJSON` tmp filename now also includes `Date.now()` for additional uniqueness across rapid sequential calls.
94
- - **L-4:** SKILL.md Step 5 explicitly instructs the LLM to treat fetched dev-log content as data, not instructions — defense against indirect prompt injection from hostile dev-log markdown.
95
-
96
- Verification: a second 6-perspective adversarial agent against HEAD reports zero Critical/High/Medium-Active vulnerabilities remain.
97
-
98
- ## 0.1.7 (2026-05-01) — security hardening + UX improvements
99
-
100
- **Security**
101
- - Tightened `SHELL_METACHARS` to additionally reject whitespace, single-quote, square brackets, equals, and percent
102
- - Project paths now cannot start with `-` (would be parsed as flag)
103
- - Added strict validation of the `branch` field (no leading dash, no `..` as a path component)
104
- - Atomic `config.json` writes (write-to-tmp + rename)
105
- - CLI no longer forwards arbitrary `VITE_*` env vars to the spawned vite — only `VITE_DEVLOG_*` plus `PATH`/`HOME`/etc.
106
- - Added `Content-Security-Policy` meta tag to the preview app
107
- - Explicit `urlTransform` in `react-markdown` rejects `data:`, `blob:`, `javascript:`, `vbscript:`, `file:`, and any non-http(s)/mailto scheme
108
- - `react-markdown` invoked with `skipHtml` for explicit defense-in-depth
109
- - `SKILL.md` instructs the LLM to single-quote every interpolated config value (defense-in-depth on top of validation)
110
- - Production preview builds without env vars show a clear "Setup required" screen instead of attempting demo fetches that would 404
111
- - `config.json` written with mode `0600`, `~/.claude/skills/devlog/` created with mode `0700`
112
- - Pinned all dependencies to exact versions (no `^` ranges) to eliminate resolution drift
113
-
114
- **UX**
115
- - `init` now loops to register multiple projects in a single setup
116
- - New `add-project` subcommand: `npx @natjswenson/devlog add-project` — register a project without editing config.json by hand
117
- - New `config` subcommand: `npx @natjswenson/devlog config` — view current config with validation status
118
- - Init detects when `gh` is authenticated as a different user than `githubUser` and warns
119
- - Better next-step messaging after init (color, concrete commands)
120
- - All error messages now include actionable hints (`log.hint`)
121
-
122
- **Docs**
123
- - New `SECURITY.md` — threat model, audit history, ruled-out attack scenarios, vulnerability reporting flow
124
- - New `CHANGELOG.md` (this file)
125
- - README updated with new subcommands and security guarantees section
126
-
127
- ## 0.1.6 (2026-05-01) — initial security audit fixes
128
-
129
- Addressed 1 Critical + 3 High findings from the first round of the 6-agent siege:
130
- - SKILL.md now requires runtime allowlist validation of every config value before shell interpolation
131
- - CLI switched from `execSync` with template strings to `spawnSync` with argv arrays for any user-input-bearing call
132
- - `gh repo create` regex hardened against leading-dash flag injection
133
- - `gitAuthor` validator now rejects shell metachars
134
- - Schema validation added for `manifest.json`, `VITE_DEVLOG_PROJECTS`, frontmatter (allowlist + `Object.create(null)`)
135
- - `optimizeDeps` includes for vite to fix react-markdown / react-dom CJS interop in npx layouts
136
- - Preview vite server bound to localhost only, CORS disabled
137
-
138
- ## 0.1.5 (2026-05-01)
139
-
140
- - Corrected live-site URL in README (`natejswenson.com` not `.io`)
141
-
142
- ## 0.1.4 (2026-05-01)
143
-
144
- - README troubleshooting section, npm + license badges
145
- - SKILL.md uses `<config.branch || 'main'>` consistently in push/URL output
146
-
147
- ## 0.1.3 (2026-05-01)
148
-
149
- - Expanded `optimizeDeps.include` to cover react/react-dom for npx-installed layouts
150
-
151
- ## 0.1.2 (2026-05-01)
152
-
153
- - First `optimizeDeps` fix for `style-to-js` CJS/ESM interop (react-markdown rendering)
154
-
155
- ## 0.1.1 (2026-05-01)
156
-
157
- - `projects[].label` and `branch` config fields (optional, with safe defaults)
158
-
159
- ## 0.1.0 (2026-05-01)
160
-
161
- - Initial release
162
- - CLI: `init`, `preview`
163
- - React drop-in components: `DevLogPage`, `useDevLogEntries`
164
- - Standalone deployable Vite preview app with snarky demo mode
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Nate Swenson
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,240 +0,0 @@
1
- # devlog
2
-
3
- [![npm](https://img.shields.io/npm/v/@natjswenson/devlog?color=blue)](https://www.npmjs.com/package/@natjswenson/devlog)
4
- [![license](https://img.shields.io/npm/l/@natjswenson/devlog)](./LICENSE)
5
- [![security](https://img.shields.io/badge/security-audited-green)](./SECURITY.md)
6
- [![vulnerabilities](https://img.shields.io/badge/npm%20audit-0%20issues-brightgreen)](#security)
7
-
8
- A Claude Code skill that turns each version release (a git tag) into a published dev log entry, written in your own voice — and a React example for displaying it on your site.
9
-
10
- > **Build in public, by release.** Tag a release like you always do. Run `/devlog`. Each new version shows up on your site as a narrative entry — in your voice — not raw commit messages.
11
-
12
- ## Live example
13
-
14
- The skill is in production at [natejswenson.com/devlog](https://natejswenson.com/devlog), publishing to [github.com/natejswenson/daily-dev-log](https://github.com/natejswenson/daily-dev-log). What you see on that page is exactly what `npx @natjswenson/devlog preview` renders for you locally.
15
-
16
- ## How it works
17
-
18
- 1. **You ship a release** — tag it (e.g. `git tag v0.3.0`), like you already do.
19
- 2. **Run `/devlog` in Claude Code.** The skill finds tags that don't yet have an entry, summarizes each release's changes into a narrative markdown entry written in your voice, and pushes it to your dev-log GitHub repo. It's idempotent — re-running does nothing until you cut a new release.
20
- 3. **Your site fetches it.** Static `manifest.json` + per-release markdown files served from `raw.githubusercontent.com` — no backend needed.
21
-
22
- **In your voice.** Entries are written using a voice profile, resolved in this order: your `config.voicePath` → [ghostwriter](../ghostwriter)'s `voice/` dir if installed → a bundled default. devlog reads `voice-profile.md` (and `voice-notes.md` overrides) — never ghostwriter's `algorithm.md`, since LinkedIn reach tuning doesn't apply to a dev log.
23
-
24
- ## Quick start
25
-
26
- ```sh
27
- npx @natjswenson/devlog init
28
- ```
29
-
30
- That command:
31
- - Creates `<your-username>/daily-dev-log` on GitHub (or uses an existing one)
32
- - Installs the skill at `~/.claude/skills/devlog/`
33
- - Writes `~/.claude/skills/devlog/config.json` with your answers
34
- - Lets you register one or more projects in a single run
35
-
36
- Then:
37
-
38
- ```sh
39
- npx @natjswenson/devlog preview
40
- ```
41
-
42
- to see your dev log rendered locally at `http://localhost:5173`.
43
-
44
- ## Prerequisites
45
-
46
- - **Node 18+** — for the CLI and preview app
47
- - **GitHub CLI** (`gh`), authenticated with `gh auth login` — used to create your dev-log repo and push entries
48
- - **Claude Code** — to run the `/devlog` skill
49
-
50
- ## Commands
51
-
52
- | Command | What it does |
53
- |---|---|
54
- | `npx @natjswenson/devlog init` | One-time setup: create dev-log repo, install skill, write config |
55
- | `npx @natjswenson/devlog add-project` | Register an additional project without editing config.json by hand |
56
- | `npx @natjswenson/devlog config` | Show your current config with validation status |
57
- | `npx @natjswenson/devlog preview` | Run a local preview at `http://localhost:5173` |
58
- | `npx @natjswenson/devlog --help` | Usage |
59
- | `npx @natjswenson/devlog --version` | Version |
60
-
61
- > **Tip:** run from any directory *outside* a clone of this repo. Running inside the repo causes a `package.json` name collision and `npx` fails with `command not found`.
62
-
63
- ## What you end up with
64
-
65
- ```
66
- ~/.claude/skills/devlog/
67
- ├── SKILL.md # The /devlog slash-command instructions
68
- ├── config.json # Your settings (mode 0600)
69
- └── voice/ # Bundled fallback voice profile (last resort)
70
- ├── voice-profile.md
71
- └── voice-notes.md
72
-
73
- github.com/<you>/daily-dev-log/ # Created by init, populated by /devlog
74
- ├── myproject/
75
- │ ├── manifest.json
76
- │ ├── v0.3.0.md
77
- │ ├── v0.2.0.md
78
- │ └── ...
79
- └── ...
80
- ```
81
-
82
- ## Manual setup (if you prefer)
83
-
84
- ```sh
85
- gh repo create <you>/daily-dev-log --public --add-readme
86
- mkdir -p ~/.claude/skills/devlog/voice
87
- curl -o ~/.claude/skills/devlog/SKILL.md https://raw.githubusercontent.com/natejswenson/devlog/main/SKILL.md
88
- # Optional fallback voice profile (used when voicePath and ghostwriter are both absent):
89
- curl -o ~/.claude/skills/devlog/voice/voice-profile.md https://raw.githubusercontent.com/natejswenson/devlog/main/voice/voice-profile.example.md
90
- curl -o ~/.claude/skills/devlog/voice/voice-notes.md https://raw.githubusercontent.com/natejswenson/devlog/main/voice/voice-notes.example.md
91
- # Then copy config.example.json → ~/.claude/skills/devlog/config.json and fill it in
92
- ```
93
-
94
- ## Add to your site
95
-
96
- ### React (drop-in)
97
-
98
- ```sh
99
- cp -r examples/react/ your-site/src/devlog/
100
- ```
101
-
102
- Edit `your-site/src/devlog/devlog-config.js` to point at your repo, then:
103
-
104
- ```jsx
105
- import DevLogPage from './devlog/DevLogPage.jsx';
106
-
107
- <DevLogPage project="myproject" />
108
- ```
109
-
110
- Full instructions: [`examples/react/README.md`](./examples/react/README.md).
111
-
112
- ### No site yet?
113
-
114
- The `preview/` directory is a complete deployable Vite app. Set `VITE_DEVLOG_OWNER` / `VITE_DEVLOG_REPO` / `VITE_DEVLOG_PROJECTS` env vars on Vercel, Netlify, or Cloudflare Pages, build with `vite build`, deploy `dist/`. See [`preview/README.md`](./preview/README.md).
115
-
116
- ### Other stacks (Next, Astro, plain HTML)
117
-
118
- It's static JSON and Markdown on GitHub. Build whatever UI you want — see the **Data contract** below.
119
-
120
- ## Data contract
121
-
122
- The dev-log repo has this layout, all served as raw files from `https://raw.githubusercontent.com/<owner>/<repo>/<branch>/`:
123
-
124
- ```
125
- <repo>/
126
- └── <project-key>/
127
- ├── manifest.json # Index of all entries (newest first)
128
- ├── v0.3.0.md # One entry per release (named by version)
129
- ├── v0.2.0.md
130
- └── ...
131
- ```
132
-
133
- **`manifest.json`:**
134
- ```json
135
- {
136
- "entries": [
137
- { "date": "2026-06-08", "file": "v0.2.0.md", "title": "...", "summary": "...", "version": "v0.2.0" }
138
- ]
139
- }
140
- ```
141
-
142
- Strict validation rules (entries that don't match are silently dropped by the React example):
143
- - `date` matches `YYYY-MM-DD` (the release/tag date)
144
- - `file` matches `^[a-zA-Z0-9._-]+\.md$`
145
- - `title` and `summary` are non-empty strings
146
- - `version` (optional) matches `^[a-zA-Z0-9._-]+$`
147
-
148
- **Entry markdown:**
149
-
150
- ```markdown
151
- ---
152
- title: "Concise release summary"
153
- date: 2026-06-08
154
- project: myproject
155
- version: v0.2.0
156
- summary: "1-2 sentence summary"
157
- ---
158
-
159
- ## What Shipped
160
- Narrative paragraphs, written in your voice.
161
-
162
- ## What's Next
163
- Forward-looking note.
164
-
165
- ## Commits
166
- - commit message ([abc1234](https://github.com/.../commit/abc1234567...))
167
- ```
168
-
169
- That's the entire contract.
170
-
171
- ## Configuration reference
172
-
173
- `~/.claude/skills/devlog/config.json`:
174
-
175
- | Field | Type | Description |
176
- |---|---|---|
177
- | `targetRepo` | `"<owner>/<repo>"` | Repo where dev log entries are published. Must match `^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$`. |
178
- | `branch` | string (optional) | Branch in the dev-log repo. Defaults to `main`. Must not contain `..` or start with `-`. |
179
- | `gitAuthor` | string | Your name. Retained for backward compatibility; it is **not** currently rendered on entries (the author filter was removed, and release notes summarize all commits in a tag range). Still **required** by config validation — it must be present and non-empty (don't drop it). Whitespace OK; no shell metacharacters. |
180
- | `githubUser` | string | Your GitHub username. |
181
- | `voicePath` | string (optional) | Directory holding `voice-profile.md` (and optionally `voice-notes.md`) used to write entries in your voice. A leading `~` is expanded. If unset, devlog uses ghostwriter's `voice/` if installed, else the bundled default. Read only — never shell-interpolated. |
182
- | `projects` | array | One entry per project you want dev logs for. |
183
- | `projects[].key` | string | Subdirectory name in the dev-log repo. Strict token: `^[a-z0-9][a-z0-9._-]*$`, no `..`. |
184
- | `projects[].label` | string (optional) | Display name for the tab. Defaults to `key`. |
185
- | `projects[].path` | string | Local filesystem path to the project. Whitespace OK. |
186
- | `projects[].remote` | `"<owner>/<repo>"` | The project's GitHub remote. Used to mark public commits and link them. |
187
- | `projects[].pathFilter` | string (optional) | Repo-relative subdir scoping this project's commits in a monorepo (e.g. `skills/devlog`). |
188
- | `projects[].tagPrefix` | string (optional) | Prefix of the git tags that mark this project's releases (e.g. `devlog-v`). Defaults to `v`. Used in `git tag --list '<tagPrefix>*'`. |
189
-
190
- See [`config.example.json`](./config.example.json) for a complete template, or run `npx @natjswenson/devlog config` to inspect your current config with validation.
191
-
192
- ## Security
193
-
194
- The package is designed to be safe to install on a developer's machine and have ambient gh/git credentials. See [SECURITY.md](./SECURITY.md) for the full threat model and audit history.
195
-
196
- **At a glance:**
197
- - ✓ All shell calls in the CLI use `spawnSync` with argv arrays (no shell, no injection surface)
198
- - ✓ The skill validates every config field against an allowlist before interpolating into shell commands; instructs the LLM to single-quote interpolated values
199
- - ✓ Markdown rendering uses `react-markdown` with `skipHtml` and an allowlist `urlTransform` (only http(s)/mailto allowed; data:, javascript:, vbscript:, file:, blob: all neutralized)
200
- - ✓ Frontmatter parser uses `Object.create(null)` + key allowlist (no prototype pollution)
201
- - ✓ All external JSON is schema-validated before use (manifest, env-var projects array)
202
- - ✓ Vite dev server bound to `localhost`, CORS off
203
- - ✓ Demo-mode `window.fetch` override gated to dev builds only
204
- - ✓ `config.json` written atomically (tmp + rename), mode 0600
205
- - ✓ All dependencies pinned to exact versions
206
- - ✓ `npm audit`: 0 known vulnerabilities
207
-
208
- **To report a vulnerability:** open a [GitHub security advisory](https://github.com/natejswenson/devlog/security/advisories/new). Do not open a public issue.
209
-
210
- ## Customization
211
-
212
- - **Tweak the entry template:** edit `~/.claude/skills/devlog/SKILL.md` (Step 6 — generate the entry).
213
- - **Tweak your voice:** edit the `voice-profile.md` / `voice-notes.md` in your `voicePath` (or `~/.claude/skills/devlog/voice/`).
214
- - **Tweak the UI:** override the `--devlog-*` CSS variables in `examples/react/DevLogPage.css` to match your theme.
215
- - **Add more projects:** `npx @natjswenson/devlog add-project` (no manual JSON editing required).
216
-
217
- ## Troubleshooting
218
-
219
- **`sh: devlog: command not found` when running `npx`:** you're inside a checkout of this repo. The local `package.json` name collides with the published one. Run `npx` from somewhere else, e.g. `cd ~ && npx @natjswenson/devlog ...`.
220
-
221
- **Init prompts show `78` after placeholder text:** that's an artifact of how some output capture tools render `\x1b7`/`\x1b8` (cursor save/restore) escape sequences. In a real interactive terminal, you won't see it.
222
-
223
- **Preview is blank / no tabs / no entries:** check the browser console. If you see CJS interop errors related to `react-dom/client`, `style-to-js`, or `react-markdown`, you're on a pre-0.1.6 release — upgrade with `npm cache clean --force && rm -rf ~/.npm/_npx && npx --yes @natjswenson/devlog@latest preview`.
224
-
225
- **Init can't find `gh`:** install via [cli.github.com](https://cli.github.com/) and run `gh auth login`.
226
-
227
- **`Config validation failed: ...`** — the validator rejected something in your `config.json`. Run `npx @natjswenson/devlog config` for a detailed diagnosis. Common causes:
228
- - A field has shell metacharacters (`;` `&` `|` `` ` `` `$` etc) — see SKILL.md for the full list
229
- - A project key contains `..` or `/`
230
- - A path doesn't exist on disk
231
-
232
- **Preview shows "Setup required":** you deployed the preview app standalone but didn't set the env vars. Set `VITE_DEVLOG_OWNER`, `VITE_DEVLOG_REPO`, `VITE_DEVLOG_PROJECTS` (JSON-stringified array) in your hosting environment.
233
-
234
- ## Versioning
235
-
236
- Releases are documented in [CHANGELOG.md](./CHANGELOG.md). The package follows semver — bug fixes/security patches in patch releases (0.1.x), behavior changes in minor (0.x.0).
237
-
238
- ## License
239
-
240
- MIT