thinking-phrases 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.
Files changed (44) hide show
  1. package/README.md +370 -0
  2. package/bin/thinking-phrases.ts +8 -0
  3. package/configs/hn-top.config.json +83 -0
  4. package/launchd/com.austenstone.thinking-phrases.rss.plist +29 -0
  5. package/launchd/rss-update.error.log +27 -0
  6. package/launchd/rss-update.log +0 -0
  7. package/package.json +66 -0
  8. package/scripts/build.ts +96 -0
  9. package/scripts/install-rss-updater.zsh +69 -0
  10. package/scripts/run-rss-update.zsh +16 -0
  11. package/scripts/uninstall-rss-updater.zsh +11 -0
  12. package/scripts/update-rss-settings.ts +7 -0
  13. package/src/core/config.ts +704 -0
  14. package/src/core/githubModels.ts +208 -0
  15. package/src/core/interactive.ts +1053 -0
  16. package/src/core/presets.ts +77 -0
  17. package/src/core/runner.ts +375 -0
  18. package/src/core/scheduler.ts +84 -0
  19. package/src/core/sourceCatalog.ts +18 -0
  20. package/src/core/staticPacks.ts +66 -0
  21. package/src/core/types.ts +177 -0
  22. package/src/core/utils.ts +312 -0
  23. package/src/sinks/vscodeSettings.ts +44 -0
  24. package/src/sources/customJson.ts +174 -0
  25. package/src/sources/earthquakes.ts +100 -0
  26. package/src/sources/githubActivity.ts +598 -0
  27. package/src/sources/hackerNews.ts +75 -0
  28. package/src/sources/rss.ts +256 -0
  29. package/src/sources/stocks.ts +120 -0
  30. package/src/sources/weatherAlerts.ts +111 -0
  31. package/tips/dwyl-quotes.json +1616 -0
  32. package/tips/javascript-tips.json +102 -0
  33. package/tips/league-loading-screen-tips.json +102 -0
  34. package/tips/ruby-tips.json +110 -0
  35. package/tips/typescript-tips.json +126 -0
  36. package/tips/vscode/copilot.json +77 -0
  37. package/tips/vscode/debugging.json +37 -0
  38. package/tips/vscode/editor.json +52 -0
  39. package/tips/vscode/funny.json +42 -0
  40. package/tips/vscode/git.json +42 -0
  41. package/tips/vscode/shortcuts.json +127 -0
  42. package/tips/vscode/terminal.json +37 -0
  43. package/tips/wow-loading-screen-tips.json +111 -0
  44. package/tsconfig.json +15 -0
package/README.md ADDED
@@ -0,0 +1,370 @@
1
+ # Thinking Phrases
2
+
3
+ Turn your VS Code thinking indicator into a live dashboard. Static tip packs, real-time data sources, AI-powered summaries — all piped into [`chat.agent.thinking.phrases`](https://code.visualstudio.com/updates/v1_110#_custom-thinking-phrases).
4
+
5
+ ## Quick start
6
+
7
+ ```bash
8
+ npx thinking-phrases --interactive
9
+ ```
10
+
11
+ That's it. No install, no clone, no config files. The interactive CLI walks you through picking sources, previewing phrases, writing to VS Code settings, and optionally installing a macOS scheduler.
12
+
13
+ ## Features
14
+
15
+ ### 8 live data sources
16
+
17
+ | Source | What it shows | Example phrase |
18
+ |--------|--------------|----------------|
19
+ | **RSS / Atom** | Any feed URL | `Ars Technica — Linux 6.14 lands with… — 2h ago` |
20
+ | **Stocks** | Live ticker quotes via Yahoo Finance | `NVDA — $128.44 — ▼ 0.84%` |
21
+ | **Hacker News** | Top/new/best/ask/show/jobs | `Show HN: I built a database in a spreadsheet — 45m ago` |
22
+ | **Earthquakes** | USGS earthquake catalog near a ZIP | `M4.2 — 12 km NE of Ridgecrest, CA — 38m ago` |
23
+ | **Weather Alerts** | NOAA/NWS severe weather by ZIP | `Severe Thunderstorm Warning — Broward, FL — 12m ago` |
24
+ | **Custom JSON** | Any JSON API with configurable field mapping | `My API — Article title — 1h ago` |
25
+ | **GitHub Commits** | Recent repo or org commits with diffs | `vscode@c0ebf3e fix devtools entrypoint (+1 -1) 4h ago - @deepak1556` |
26
+ | **GitHub Feeds** | Org activity, timeline, security advisories | `@dependabot opened a pull request in copilot-sdk — 3m ago` |
27
+
28
+ ### AI-powered formatting
29
+
30
+ Enable [GitHub Models](https://docs.github.com/en/github-models) and the engine rewrites raw headlines into concise, factual phrases. For GitHub commits, it can digest the **full commit diff** so the summary reflects what actually changed.
31
+
32
+ ### Static phrase packs
33
+
34
+ Pre-built JSON packs for when you want something stable:
35
+
36
+ | Pack | Phrases |
37
+ |------|---------|
38
+ | VS Code tips (mac/win/linux) | 80 |
39
+ | JavaScript tips | 100 |
40
+ | TypeScript tips | 124 |
41
+ | Ruby tips | 108 |
42
+ | League of Legends loading tips | 100 |
43
+ | WoW loading screen tips | 109 |
44
+ | Inspirational quotes | 1,614 |
45
+
46
+ ### Interactive CLI
47
+
48
+ A guided terminal UI that walks you through source selection, config, preview, and installation — no flag memorization required.
49
+
50
+ ### macOS scheduler
51
+
52
+ A `launchd` job that refreshes your phrases on a cron-like interval. Set it to 5 minutes for stocks, an hour for news, whatever you want.
53
+
54
+ ### Multiple config profiles
55
+
56
+ Keep separate configs for different moods. `configs/github-timeline.config.json` for work, `configs/stocks-only.config.json` for market hours, swap between them.
57
+
58
+ ### One-liner examples
59
+
60
+ ```bash
61
+ # GitHub org activity feed
62
+ npx thinking-phrases --use-github --github-mode feed --github-feed-kind organization --github-org github --github-max-items 10
63
+
64
+ # Repo commits with AI summaries
65
+ npx thinking-phrases --use-github --github-mode repo-commits --github-repo microsoft/vscode --github-max-items 5 --use-models
66
+
67
+ # Stocks + RSS
68
+ npx thinking-phrases --stocks MSFT,NVDA,TSLA --feed https://github.blog/feed/
69
+
70
+ # Earthquakes near a ZIP
71
+ npx thinking-phrases --use-earthquakes --quake-zip 94103 --quake-min-magnitude 2
72
+
73
+ # Weather alerts near a ZIP
74
+ npx thinking-phrases --use-weather-alerts --weather-zip 33312
75
+
76
+ # Dry run (preview only, don't write)
77
+ npx thinking-phrases --dry-run --use-github --github-mode feed --github-feed-kind organization --github-org github
78
+
79
+ # Write to settings
80
+ npx thinking-phrases --use-github --github-mode feed --github-feed-kind organization --github-org github
81
+ ```
82
+
83
+ ### Install globally (optional)
84
+
85
+ ```bash
86
+ npm install -g thinking-phrases
87
+ thinking-phrases --interactive
88
+ ```
89
+
90
+ ### Clone for development
91
+
92
+ ```bash
93
+ git clone https://github.com/austenstone/thinking-phrases.git
94
+ cd thinking-phrases
95
+ npm install
96
+ npm run start:interactive
97
+ ```
98
+
99
+ ## Data sources
100
+
101
+ ### RSS / Atom feeds
102
+
103
+ Any RSS or Atom feed URL. Google News, GitHub Blog, Ars Technica, your company blog — whatever you want.
104
+
105
+ ```json
106
+ "feeds": [
107
+ { "url": "https://github.blog/feed/" },
108
+ { "url": "https://news.google.com/rss/headlines/section/topic/TECHNOLOGY?hl=en-US&gl=US&ceid=US:en" }
109
+ ]
110
+ ```
111
+
112
+ ### Stock quotes
113
+
114
+ Live prices via Yahoo Finance. Supports market state labels (pre-market, after-hours).
115
+
116
+ ```json
117
+ "stockQuotes": {
118
+ "enabled": true,
119
+ "symbols": ["MSFT", "NVDA", "TSLA", "AMZN", "GOOGL", "AMD"],
120
+ "includeMarketState": true
121
+ }
122
+ ```
123
+
124
+ ### Hacker News
125
+
126
+ Top, new, best, ask, show, or jobs feed. Configurable minimum score and item count.
127
+
128
+ ```json
129
+ "hackerNews": {
130
+ "enabled": true,
131
+ "feed": "top",
132
+ "maxItems": 10,
133
+ "minScore": 50
134
+ }
135
+ ```
136
+
137
+ ### Earthquakes (USGS)
138
+
139
+ Enter a ZIP code and the engine resolves it to lat/lon, then queries the USGS earthquake catalog within a configurable radius.
140
+
141
+ ```json
142
+ "earthquakes": {
143
+ "enabled": true,
144
+ "zipCode": "94103",
145
+ "minMagnitude": 2,
146
+ "radiusKm": 500,
147
+ "limit": 10
148
+ }
149
+ ```
150
+
151
+ ### Weather alerts (NOAA/NWS)
152
+
153
+ Enter a ZIP code and the engine resolves it to a state, then queries NOAA for active severe weather alerts.
154
+
155
+ ```json
156
+ "weatherAlerts": {
157
+ "enabled": true,
158
+ "zipCode": "33312",
159
+ "minimumSeverity": "moderate",
160
+ "limit": 10
161
+ }
162
+ ```
163
+
164
+ ### Custom JSON API
165
+
166
+ Point it at any JSON endpoint. Map title, content, link, source, date, and ID fields. Works with anything that returns an array of objects.
167
+
168
+ ```json
169
+ "customJson": {
170
+ "enabled": true,
171
+ "url": "https://hn.algolia.com/api/v1/search?tags=front_page",
172
+ "itemsPath": "hits",
173
+ "titleField": "title",
174
+ "linkField": "url",
175
+ "sourceLabel": "HN API",
176
+ "dateField": "created_at",
177
+ "idField": "objectID",
178
+ "maxItems": 10
179
+ }
180
+ ```
181
+
182
+ ### GitHub activity
183
+
184
+ Three modes for GitHub data:
185
+
186
+ **Repo commits** — recent commits from a specific repository. Includes short SHA, line deltas, and author handle in the phrase. When AI is enabled with extra context, the model gets the **full commit diff**.
187
+
188
+ ```json
189
+ "githubActivity": {
190
+ "enabled": true,
191
+ "mode": "repo-commits",
192
+ "repo": "microsoft/vscode",
193
+ "branch": "main",
194
+ "maxItems": 10,
195
+ "tokenEnvVar": "GITHUB_TOKEN"
196
+ }
197
+ ```
198
+
199
+ **Org commits** — recent push events across an entire GitHub organization. Fetches commit details for each push.
200
+
201
+ ```json
202
+ "githubActivity": {
203
+ "enabled": true,
204
+ "mode": "org-commits",
205
+ "org": "github",
206
+ "maxItems": 10
207
+ }
208
+ ```
209
+
210
+ **Feeds** — GitHub Atom feeds including organization activity, your personal timeline, security advisories, or any custom feed URL. Supports authenticated private feed discovery via `/feeds` with fallback to public org events.
211
+
212
+ ```json
213
+ "githubActivity": {
214
+ "enabled": true,
215
+ "mode": "feed",
216
+ "feedKind": "organization",
217
+ "org": "github",
218
+ "maxItems": 20
219
+ }
220
+ ```
221
+
222
+ Available feed kinds: `timeline`, `current-user-public`, `current-user`, `current-user-actor`, `security-advisories`, `organization`, `custom-url`.
223
+
224
+ ## GitHub Models (AI)
225
+
226
+ When enabled, the engine sends fetched items to GitHub Models for rewriting into concise, factual phrases. Falls back to the normal formatter if auth or inference fails.
227
+
228
+ For GitHub commits specifically, the model receives the full commit diff as additional context when extra content fetching is enabled — so it can summarize what actually changed, not just echo the commit message.
229
+
230
+ ```json
231
+ "githubModels": {
232
+ "enabled": true,
233
+ "model": "openai/gpt-4.1",
234
+ "fetchArticleContent": true
235
+ }
236
+ ```
237
+
238
+ ### Auth
239
+
240
+ Tokens are resolved in this order for both GitHub API and GitHub Models:
241
+
242
+ 1. Configured env var (`GITHUB_MODELS_TOKEN` / `GITHUB_TOKEN`)
243
+ 2. `GITHUB_TOKEN` env var
244
+ 3. `gh auth token` (GitHub CLI)
245
+
246
+ For GitHub activity, if a token causes 401/403 on public endpoints, it silently retries without auth.
247
+
248
+ ## Presets
249
+
250
+ The interactive installer includes built-in presets to get started fast:
251
+
252
+ | Preset | Sources |
253
+ |--------|---------|
254
+ | **Dev Pulse** | Google Tech news + Hacker News top stories |
255
+ | **Market Watch** | Big-tech stock quotes with fast-refresh defaults |
256
+ | **World Signals** | Earthquakes + severe weather + Hacker News best |
257
+
258
+ ## Scheduler (macOS)
259
+
260
+ The interactive installer can set up a `launchd` scheduler that refreshes your phrases on a timer. If you cloned the repo, you can also install it manually:
261
+
262
+ ```bash
263
+ npm run rss:install # default: every 3600s (1 hour)
264
+ npm run rss:install -- 300 # every 5 minutes
265
+ npm run rss:install -- 900 ./configs/stocks-only.config.json
266
+ ```
267
+
268
+ The scheduler runs at the OS level. Your VS Code settings update silently in the background.
269
+
270
+ ```bash
271
+ npm run rss:uninstall # remove the scheduler
272
+ npx thinking-phrases --uninstall # remove thinking phrases from settings
273
+ ```
274
+
275
+ ## Config profiles
276
+
277
+ Keep multiple configs in `configs/` and switch between them:
278
+
279
+ ```text
280
+ configs/
281
+ rss-settings.config.json
282
+ github-timeline.config.json
283
+ github-commits.config.json
284
+ google-news.config.json
285
+ google-technology-stocks.config.json
286
+ hn-best-earthquakes-weather-alerts.config.json
287
+ stocks-only.config.json
288
+ ```
289
+
290
+ ```bash
291
+ npm run rss:run -- --config configs/stocks-only.config.json
292
+ npm run rss:install -- 300 configs/stocks-only.config.json
293
+ ```
294
+
295
+ ## Static packs
296
+
297
+ ### VS Code tips
298
+
299
+ | Category | Count | Description |
300
+ |----------|-------|-------------|
301
+ | ⌨️ Shortcuts | 25 | Multi-cursor, navigation, selection, formatting |
302
+ | 🤖 Copilot | 15 | Chat, agent mode, inline chat, prompt files |
303
+ | 🔀 Git | 8 | Source control, blame, staging, timeline |
304
+ | 💻 Terminal | 7 | Splits, suggestions, integrated terminal |
305
+ | 🐛 Debugging | 7 | Breakpoints, logpoints, conditional stops |
306
+ | ✏️ Editor | 10 | Zen mode, sticky scroll, Emmet |
307
+ | 😄 Funny | 8 | Flavor text |
308
+
309
+ OS-aware format — each tip has `mac`, `windows`, and `linux` variants:
310
+
311
+ ```json
312
+ {
313
+ "mac": "⌘+D selects the next occurrence of a word. Keep pressing for more!",
314
+ "windows": "Ctrl+D selects the next occurrence of a word. Keep pressing for more!",
315
+ "linux": "Ctrl+D selects the next occurrence of a word. Keep pressing for more!"
316
+ }
317
+ ```
318
+
319
+ ### Other packs
320
+
321
+ Standalone string arrays — just drop them in:
322
+
323
+ - JavaScript tips (100)
324
+ - TypeScript tips (124)
325
+ - Ruby tips (108)
326
+ - League of Legends loading tips (100)
327
+ - WoW loading screen tips (109)
328
+ - Inspirational quotes (1,614 — from `dwyl/quotes`, GPL-2.0)
329
+
330
+ ## CLI reference
331
+
332
+ | Command | Description |
333
+ |---------|-------------|
334
+ | `npx thinking-phrases --interactive` | Guided interactive setup |
335
+ | `npx thinking-phrases --dry-run` | Preview phrases without writing |
336
+ | `npx thinking-phrases` | Write phrases to VS Code settings |
337
+ | `npx thinking-phrases --uninstall` | Remove thinking phrases from settings |
338
+
339
+ All `--flags` from the data source sections above work with any of these commands.
340
+
341
+ ## How it works
342
+
343
+ ```
344
+ Sources → Normalize → Format → Write
345
+ ```
346
+
347
+ 1. **Sources** fetch live data (RSS, stocks, GitHub, USGS, NOAA, JSON APIs)
348
+ 2. **Core** normalizes everything into article or stock items
349
+ 3. **Formatter** builds phrases — either basic `source — title — time` or AI-rewritten via GitHub Models
350
+ 4. **Sink** writes the final phrases into VS Code `settings.json`
351
+
352
+ The source catalog is modular. Each source is a simple `{ isEnabled, fetch }` object registered in the catalog. Adding a new source means writing one file and registering it.
353
+
354
+ ## Portability
355
+
356
+ Settings path auto-detection works on macOS, Linux, and Windows. Supports both VS Code Stable and Insiders. You can also pass `--settings` to point at any path.
357
+
358
+ ## References
359
+
360
+ - [VS Code Custom Thinking Phrases](https://code.visualstudio.com/updates/v1_110#_custom-thinking-phrases)
361
+ - [GitHub Models](https://docs.github.com/en/github-models/quickstart)
362
+ - [GitHub REST API — Feeds](https://docs.github.com/en/rest/activity/feeds)
363
+ - [GitHub REST API — Commits](https://docs.github.com/en/rest/commits/commits)
364
+ - [USGS Earthquake Catalog](https://earthquake.usgs.gov/fdsnws/event/1/)
365
+ - [NOAA/NWS Alerts API](https://www.weather.gov/documentation/services-web-api)
366
+ - [Yahoo Finance](https://finance.yahoo.com/)
367
+
368
+ ## License
369
+
370
+ MIT
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node --import=tsx
2
+ import { runDynamicPhrases } from '../src/core/runner.ts';
3
+
4
+ runDynamicPhrases().catch((error: unknown) => {
5
+ const message = error instanceof Error ? error.message : String(error);
6
+ console.error(`thinking-phrases: ${message}`);
7
+ process.exit(1);
8
+ });
@@ -0,0 +1,83 @@
1
+ {
2
+ "limit": 25,
3
+ "mode": "replace",
4
+ "target": "auto",
5
+ "verbose": false,
6
+ "debug": false,
7
+ "feeds": [],
8
+ "phraseFormatting": {
9
+ "includeSource": true,
10
+ "includeTime": true,
11
+ "maxLength": 140
12
+ },
13
+ "githubModels": {
14
+ "enabled": true,
15
+ "model": "openai/gpt-4.1",
16
+ "tokenEnvVar": "GITHUB_MODELS_TOKEN",
17
+ "maxInputItems": 10,
18
+ "maxTokens": 300,
19
+ "maxPhrasesPerArticle": 2,
20
+ "temperature": 0.2,
21
+ "fetchArticleContent": true,
22
+ "maxArticleContentLength": 6000
23
+ },
24
+ "stockQuotes": {
25
+ "enabled": false,
26
+ "symbols": [
27
+ "MSFT",
28
+ "NVDA",
29
+ "TSLA",
30
+ "AMZN",
31
+ "GOOGL",
32
+ "AMD"
33
+ ],
34
+ "includeMarketState": true
35
+ },
36
+ "hackerNews": {
37
+ "enabled": true,
38
+ "feed": "top",
39
+ "maxItems": 30,
40
+ "minScore": 50
41
+ },
42
+ "earthquakes": {
43
+ "enabled": false,
44
+ "zipCode": "",
45
+ "minMagnitude": 4,
46
+ "windowHours": 24,
47
+ "limit": 10,
48
+ "radiusKm": 500,
49
+ "orderBy": "time"
50
+ },
51
+ "weatherAlerts": {
52
+ "enabled": false,
53
+ "zipCode": "",
54
+ "area": "",
55
+ "minimumSeverity": "moderate",
56
+ "limit": 10
57
+ },
58
+ "customJson": {
59
+ "enabled": false,
60
+ "url": "",
61
+ "itemsPath": "",
62
+ "titleField": "title",
63
+ "contentField": "summary",
64
+ "linkField": "url",
65
+ "sourceField": "",
66
+ "sourceLabel": "",
67
+ "dateField": "publishedAt",
68
+ "idField": "id",
69
+ "maxItems": 10
70
+ },
71
+ "githubActivity": {
72
+ "enabled": false,
73
+ "mode": "repo-commits",
74
+ "repo": "microsoft/vscode",
75
+ "org": "github",
76
+ "branch": "",
77
+ "feedKind": "timeline",
78
+ "feedUrl": "",
79
+ "maxItems": 10,
80
+ "sinceHours": 24,
81
+ "tokenEnvVar": "GITHUB_TOKEN"
82
+ }
83
+ }
@@ -0,0 +1,29 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>Label</key>
6
+ <string>com.austenstone.thinking-phrases.rss</string>
7
+
8
+ <key>ProgramArguments</key>
9
+ <array>
10
+ <string>/bin/zsh</string>
11
+ <string>/Users/austenstone/source/vscode-copilot-tips/scripts/run-rss-update.zsh</string>
12
+ </array>
13
+
14
+ <key>RunAtLoad</key>
15
+ <true/>
16
+
17
+ <key>StartInterval</key>
18
+ <integer>3600</integer>
19
+
20
+ <key>StandardOutPath</key>
21
+ <string>/Users/austenstone/source/vscode-copilot-tips/launchd/rss-update.log</string>
22
+
23
+ <key>StandardErrorPath</key>
24
+ <string>/Users/austenstone/source/vscode-copilot-tips/launchd/rss-update.error.log</string>
25
+
26
+ <key>WorkingDirectory</key>
27
+ <string>/Users/austenstone/source/vscode-copilot-tips</string>
28
+ </dict>
29
+ </plist>
@@ -0,0 +1,27 @@
1
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
2
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
3
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
4
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
5
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
6
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
7
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
8
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
9
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
10
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
11
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
12
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
13
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
14
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
15
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
16
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
17
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
18
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
19
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
20
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
21
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
22
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
23
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
24
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
25
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
26
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
27
+ /Users/austenstone/.oh-my-zsh/oh-my-zsh.sh:55: ZSH_CUSTOM: parameter not set
File without changes
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "thinking-phrases",
3
+ "version": "1.0.1",
4
+ "description": "Live thinking phrases for VS Code — RSS, stocks, GitHub commits, earthquakes, weather, Hacker News, and more",
5
+ "type": "module",
6
+ "bin": {
7
+ "thinking-phrases": "./bin/thinking-phrases.ts"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "src/",
12
+ "scripts/",
13
+ "tips/",
14
+ "configs/",
15
+ "launchd/",
16
+ "tsconfig.json"
17
+ ],
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/austenstone/thinking-phrases.git"
21
+ },
22
+ "homepage": "https://github.com/austenstone/thinking-phrases",
23
+ "keywords": [
24
+ "vscode",
25
+ "thinking-phrases",
26
+ "copilot",
27
+ "rss",
28
+ "github",
29
+ "stocks",
30
+ "hacker-news",
31
+ "earthquakes",
32
+ "weather",
33
+ "cli"
34
+ ],
35
+ "scripts": {
36
+ "build": "tsx scripts/build.ts",
37
+ "start": "tsx bin/thinking-phrases.ts",
38
+ "start:interactive": "tsx bin/thinking-phrases.ts --interactive",
39
+ "start:dry-run": "tsx bin/thinking-phrases.ts --dry-run",
40
+ "rss:dry-run": "tsx scripts/update-rss-settings.ts --dry-run",
41
+ "rss:interactive": "tsx scripts/update-rss-settings.ts --interactive",
42
+ "rss:remove": "tsx scripts/update-rss-settings.ts --uninstall",
43
+ "rss:run": "tsx scripts/update-rss-settings.ts",
44
+ "rss:install": "zsh scripts/install-rss-updater.zsh",
45
+ "rss:uninstall": "zsh scripts/uninstall-rss-updater.zsh"
46
+ },
47
+ "dependencies": {
48
+ "@azure-rest/ai-inference": "^1.0.0-beta.6",
49
+ "@azure/core-auth": "^1.10.1",
50
+ "@clack/prompts": "^1.1.0",
51
+ "fast-xml-parser": "^5.4.2",
52
+ "jsonc-parser": "^3.3.1",
53
+ "picocolors": "^1.1.1",
54
+ "tsx": "^4.19.0",
55
+ "yahoo-finance2": "^3.13.2"
56
+ },
57
+ "devDependencies": {
58
+ "@types/json-schema": "^7.0.15",
59
+ "@types/node": "^25.3.5",
60
+ "typescript": "^5.7.0"
61
+ },
62
+ "engines": {
63
+ "node": ">=18"
64
+ },
65
+ "license": "MIT"
66
+ }
@@ -0,0 +1,96 @@
1
+ import { readFileSync, writeFileSync, readdirSync, mkdirSync, existsSync, rmSync } from 'node:fs';
2
+ import { join, dirname } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ interface Tip {
6
+ mac: string;
7
+ windows: string;
8
+ linux: string;
9
+ }
10
+
11
+ type Platform = keyof Tip;
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const TIPS_DIR = join(__dirname, '..', 'tips');
15
+ const VSCODE_TIPS_DIR = join(TIPS_DIR, 'vscode');
16
+ const OUT_DIR = join(__dirname, '..', 'out');
17
+
18
+ const PLATFORMS: Platform[] = ['mac', 'windows', 'linux'];
19
+
20
+ function loadTips(): { category: string; tips: Tip[] }[] {
21
+ const files = readdirSync(VSCODE_TIPS_DIR).filter(f => f.endsWith('.json')).sort();
22
+ return files.map(file => ({
23
+ category: file.replace('.json', ''),
24
+ tips: JSON.parse(readFileSync(join(VSCODE_TIPS_DIR, file), 'utf-8')) as Tip[],
25
+ }));
26
+ }
27
+
28
+ function loadStandalonePacks(): { name: string; phrases: string[] }[] {
29
+ const files = readdirSync(TIPS_DIR)
30
+ .filter(file => file.endsWith('.json'))
31
+ .sort();
32
+
33
+ return files.map(file => ({
34
+ name: file.replace('.json', ''),
35
+ phrases: JSON.parse(readFileSync(join(TIPS_DIR, file), 'utf-8')) as string[],
36
+ }));
37
+ }
38
+
39
+ function buildSettings(phrases: string[], mode: 'append' | 'replace' = 'append') {
40
+ return {
41
+ 'chat.agent.thinking.phrases': { mode, phrases },
42
+ };
43
+ }
44
+
45
+ function main() {
46
+ const categories = loadTips();
47
+ const standalonePacks = loadStandalonePacks();
48
+ const totalTips = categories.reduce((sum, c) => sum + c.tips.length, 0);
49
+
50
+ console.log(`Loaded ${totalTips} tips across ${categories.length} categories:`);
51
+ for (const c of categories) {
52
+ console.log(` ${c.category}: ${c.tips.length} tips`);
53
+ }
54
+
55
+ console.log(`Loaded ${standalonePacks.length} standalone pack${standalonePacks.length === 1 ? '' : 's'}:`);
56
+ for (const pack of standalonePacks) {
57
+ console.log(` ${pack.name}: ${pack.phrases.length} phrases`);
58
+ }
59
+
60
+ if (!existsSync(OUT_DIR)) {
61
+ mkdirSync(OUT_DIR, { recursive: true });
62
+ }
63
+
64
+ for (const platform of PLATFORMS) {
65
+ const phrases = categories.flatMap(c => c.tips.map(tip => tip[platform]));
66
+ const settings = buildSettings(phrases);
67
+ const outPath = join(OUT_DIR, `settings-${platform}.json`);
68
+ writeFileSync(outPath, JSON.stringify(settings, null, 2) + '\n');
69
+ console.log(`\nWrote ${outPath} (${phrases.length} phrases)`);
70
+ }
71
+
72
+ const allPhrases = categories.flatMap(category => category.tips.map(tip => tip.mac));
73
+ const vscodeTipsPath = join(OUT_DIR, 'vscode-tips.json');
74
+ writeFileSync(vscodeTipsPath, JSON.stringify(buildSettings(allPhrases), null, 2) + '\n');
75
+ console.log(`\nWrote ${vscodeTipsPath} (${allPhrases.length} tips)`);
76
+
77
+ const legacyAllTipsPath = join(OUT_DIR, 'all-tips.json');
78
+ if (existsSync(legacyAllTipsPath)) {
79
+ rmSync(legacyAllTipsPath);
80
+ console.log(`Removed ${legacyAllTipsPath}`);
81
+ }
82
+
83
+ for (const pack of standalonePacks) {
84
+ const outPath = join(OUT_DIR, `${pack.name}.json`);
85
+ writeFileSync(outPath, JSON.stringify(buildSettings(pack.phrases), null, 2) + '\n');
86
+ console.log(`Wrote ${outPath} (${pack.phrases.length} tips)`);
87
+ }
88
+
89
+ const wowLuaPath = join(OUT_DIR, 'LoadingScreenTips.lua');
90
+ if (existsSync(wowLuaPath)) {
91
+ rmSync(wowLuaPath);
92
+ console.log(`Removed ${wowLuaPath}`);
93
+ }
94
+ }
95
+
96
+ main();