tuimon 0.1.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 (50) hide show
  1. package/CLAUDE.md +80 -0
  2. package/README.md +153 -0
  3. package/client/tuimon-client.js +44 -0
  4. package/dist/browser.d.ts +7 -0
  5. package/dist/browser.d.ts.map +1 -0
  6. package/dist/browser.js +57 -0
  7. package/dist/browser.js.map +1 -0
  8. package/dist/cli.d.ts +3 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +87 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/detect.d.ts +8 -0
  13. package/dist/detect.d.ts.map +1 -0
  14. package/dist/detect.js +141 -0
  15. package/dist/detect.js.map +1 -0
  16. package/dist/encoder.d.ts +4 -0
  17. package/dist/encoder.d.ts.map +1 -0
  18. package/dist/encoder.js +115 -0
  19. package/dist/encoder.js.map +1 -0
  20. package/dist/fkeybar.d.ts +5 -0
  21. package/dist/fkeybar.d.ts.map +1 -0
  22. package/dist/fkeybar.js +89 -0
  23. package/dist/fkeybar.js.map +1 -0
  24. package/dist/index.d.ts +7 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +166 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/keyhandler.d.ts +5 -0
  29. package/dist/keyhandler.d.ts.map +1 -0
  30. package/dist/keyhandler.js +20 -0
  31. package/dist/keyhandler.js.map +1 -0
  32. package/dist/router.d.ts +10 -0
  33. package/dist/router.d.ts.map +1 -0
  34. package/dist/router.js +154 -0
  35. package/dist/router.js.map +1 -0
  36. package/dist/server.d.ts +5 -0
  37. package/dist/server.d.ts.map +1 -0
  38. package/dist/server.js +142 -0
  39. package/dist/server.js.map +1 -0
  40. package/dist/types.d.ts +108 -0
  41. package/dist/types.d.ts.map +1 -0
  42. package/dist/types.js +3 -0
  43. package/dist/types.js.map +1 -0
  44. package/package.json +44 -0
  45. package/templates/internal/confirm-quit.html +94 -0
  46. package/templates/starter/pages/cpu-detail.html +176 -0
  47. package/templates/starter/pages/memory-detail.html +166 -0
  48. package/templates/starter/pages/overview.html +186 -0
  49. package/templates/starter/tuimon.config.ts +87 -0
  50. package/tsconfig.json +23 -0
package/CLAUDE.md ADDED
@@ -0,0 +1,80 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Build & Development Commands
6
+
7
+ ```bash
8
+ npm run build # tsc → dist/
9
+ npm run dev # tsc --watch
10
+ npm test # vitest run (single pass)
11
+ npm run test:watch # vitest (watch mode)
12
+ npm run test:coverage # vitest run --coverage
13
+ npm run typecheck # tsc --noEmit
14
+ npm run lint # eslint src --ext .ts
15
+ npm run format # prettier --write src
16
+ ```
17
+
18
+ Run a single test file: `npx vitest run src/__tests__/router.test.ts`
19
+ Run tests matching a pattern: `npx vitest run --grep "shortcut navigation"`
20
+
21
+ ## Architecture
22
+
23
+ TuiMon renders HTML pages in a headless Chromium browser, screenshots them as PNG, and streams images to the terminal via Kitty/Sixel graphics protocols. Developers write dashboards as plain HTML/CSS/JS.
24
+
25
+ ### Startup Sequence (src/index.ts)
26
+
27
+ `tuimon.start(options)` orchestrates everything in this order:
28
+
29
+ 1. **detect.ts** — probe terminal for Kitty/Sixel/iTerm2 support and pixel dimensions
30
+ 2. **server.ts** — spin up an HTTP server on localhost:7337+ serving HTML pages from a common root directory
31
+ 3. **browser.ts** — launch headless Chromium via Playwright, set viewport to terminal pixel dimensions
32
+ 4. **router.ts** — create navigation state machine wired to navigate/render/setKeys callbacks
33
+ 5. **keyhandler.ts** — enable stdin raw mode, forward raw key strings to router.handleKey
34
+ 6. **fkeybar.ts** — render F-key status bar on the terminal's last row
35
+
36
+ ### Render Pipeline
37
+
38
+ ```
39
+ dash.render(data) → browser.pushData(data) → page.__tuimon_update__(data)
40
+ → setTimeout(renderDelay) → browser.screenshot() → encodeAndRender(png, protocol)
41
+ ```
42
+
43
+ The encoder writes directly to stdout: Kitty uses base64 PNG chunked at 4096 bytes; Sixel uses sharp to convert to raw pixels then builds sixel bands.
44
+
45
+ ### Router State Machine (src/router.ts)
46
+
47
+ Three states: `overview` → `detail` → `confirm-quit`. This is the navigation core:
48
+ - **overview**: shortcut keys navigate to detail pages; ESC opens confirm-quit
49
+ - **detail**: ESC returns to overview; shortcuts ignored
50
+ - **confirm-quit**: Y exits, N/ESC returns to previous state; all F-keys ignored
51
+ - **Ctrl+C**: immediate exit from any state
52
+
53
+ F-key escape sequences are mapped in a lookup table (e.g., `\x1bOP` → F1, `\x1b[15~` → F5).
54
+
55
+ ### Client Bridge (client/tuimon-client.js)
56
+
57
+ Auto-injected into served HTML pages by the server. Exposes `window.TuiMon.onUpdate(cb)` and `window.TuiMon.set(selector, value)`. Data attributes `data-tm-key` and `data-tm-label` on HTML elements get automatic shortcut badges.
58
+
59
+ ## TypeScript Rules
60
+
61
+ - **Strict mode** with `noUncheckedIndexedAccess`, `exactOptionalPropertyTypes`, `noImplicitReturns`
62
+ - **ESM only** — module: NodeNext, all imports use `.js` extension
63
+ - All shared interfaces live in `src/types.ts` — modules import types from there
64
+ - iterm2 protocol maps to kitty for encoding (only 'kitty' | 'sixel' reach the encoder)
65
+
66
+ ## Testing Patterns
67
+
68
+ Tests live in `src/__tests__/`. Setup file (`setup.ts`) converts `process.stdout.columns/rows` to getter properties for `vi.spyOn` compatibility.
69
+
70
+ - **Module mocking**: `vi.mock('../module.js', () => ({ ... }))` at file top
71
+ - **Dynamic imports**: tests use `await import('../module.js')` after `vi.resetModules()` for env-dependent modules (detect, router)
72
+ - **stdout capture**: `vi.spyOn(process.stdout, 'write').mockImplementation(() => true)` then collect calls
73
+ - **stdin simulation**: create `EventEmitter` with `setRawMode`/`resume` stubs, mock `process.stdin`
74
+ - **Server tests**: create real temp directories with `mkdirSync`, track handles for cleanup in `afterEach`
75
+
76
+ Coverage thresholds: 80% lines/functions/statements, 75% branches. cli.ts is excluded.
77
+
78
+ ## Formatting
79
+
80
+ No semicolons, single quotes, trailing commas, 100 char width, 2-space indent (see .prettierrc).
package/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # TuiMon
2
+
3
+ > Render beautiful HTML dashboards directly in your terminal.
4
+
5
+ ## Terminal Requirements
6
+
7
+ | Terminal | Protocol | Status |
8
+ |-----------|----------|------------|
9
+ | Kitty | Kitty | Supported |
10
+ | Ghostty | Kitty | Supported |
11
+ | WezTerm | Kitty | Supported |
12
+ | iTerm2 | iTerm2 | Supported |
13
+ | VSCode | Sixel | Supported* |
14
+ | mlterm | Sixel | Supported |
15
+
16
+ \* Sixel support may vary by terminal version.
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ npx tuimon init
22
+ npx tuimon check
23
+ npx tuimon start
24
+ ```
25
+
26
+ Or install globally:
27
+
28
+ ```bash
29
+ npm install -g tuimon
30
+ tuimon init && tuimon start
31
+ ```
32
+
33
+ ## How It Works
34
+
35
+ TuiMon renders your HTML pages in a headless Chromium browser via Playwright, screenshots them as PNG, and streams the images to your terminal using the Kitty graphics protocol (or Sixel as fallback). You write dashboards as normal HTML/CSS/JS — any charting library works.
36
+
37
+ ## Multi-Page Navigation
38
+
39
+ Define multiple pages with keyboard shortcuts:
40
+
41
+ ```typescript
42
+ const dash = await tuimon.start({
43
+ pages: {
44
+ overview: {
45
+ html: './pages/overview.html',
46
+ default: true,
47
+ label: 'Overview',
48
+ },
49
+ cpu: {
50
+ html: './pages/cpu-detail.html',
51
+ shortcut: 'g',
52
+ label: 'CPU Detail',
53
+ },
54
+ memory: {
55
+ html: './pages/memory-detail.html',
56
+ shortcut: 'm',
57
+ label: 'Memory',
58
+ },
59
+ },
60
+ })
61
+ ```
62
+
63
+ - Press a shortcut key from the overview to jump to a detail page
64
+ - Press **ESC** on a detail page to return to overview
65
+ - Press **ESC** on overview to show quit confirmation
66
+ - Press **Ctrl+C** anywhere to exit immediately
67
+
68
+ Add shortcut badges to HTML panels with data attributes:
69
+
70
+ ```html
71
+ <div class="panel" data-tm-key="g" data-tm-label="CPU Detail">
72
+ <!-- panel content -->
73
+ </div>
74
+ ```
75
+
76
+ ## Per-Page F-Key Bindings
77
+
78
+ Each page defines its own F-key actions:
79
+
80
+ ```typescript
81
+ pages: {
82
+ overview: {
83
+ html: './pages/overview.html',
84
+ default: true,
85
+ keys: {
86
+ F5: { label: 'Refresh', action: async () => dash.render(await getData()) },
87
+ F10: { label: 'Quit', action: () => process.exit(0) },
88
+ },
89
+ },
90
+ }
91
+ ```
92
+
93
+ The F-key bar at the bottom always reflects the active page's bindings.
94
+
95
+ ## API Reference
96
+
97
+ ### `tuimon.start(options: TuiMonOptions): Promise<TuiMonDashboard>`
98
+
99
+ ```typescript
100
+ interface TuiMonOptions {
101
+ pages: Record<string, PageConfig>
102
+ data?: () => Record<string, unknown> | Promise<Record<string, unknown>>
103
+ refresh?: number // auto-render interval in ms
104
+ renderDelay?: number // delay after pushData before screenshot (default: 50)
105
+ }
106
+
107
+ interface PageConfig {
108
+ html: string // path to HTML file
109
+ default?: boolean // exactly one page must be default
110
+ shortcut?: string // single lowercase letter
111
+ label?: string // human-readable name
112
+ keys?: Partial<Record<FKey, KeyBinding>>
113
+ }
114
+
115
+ interface KeyBinding {
116
+ label: string
117
+ action: () => void | Promise<void>
118
+ }
119
+ ```
120
+
121
+ ### `dash.render(data): Promise<void>`
122
+
123
+ Push data to the current page and re-render.
124
+
125
+ ### `dash.stop(): Promise<void>`
126
+
127
+ Gracefully shut down — restores terminal state.
128
+
129
+ ## Client Library
130
+
131
+ In your HTML pages, use the injected `TuiMon` object:
132
+
133
+ ```javascript
134
+ // Listen for data updates
135
+ TuiMon.onUpdate(function(data) {
136
+ TuiMon.set('#cpu', data.cpu)
137
+ TuiMon.set('#memory', data.memory + '%')
138
+ })
139
+
140
+ // TuiMon.set(selector, value) — sets text content or applies styles
141
+ // TuiMon.notify(message, duration) — dispatches a notification event
142
+ ```
143
+
144
+ ## Contributing
145
+
146
+ - **TDD required** — write tests first, implementation second
147
+ - Coverage thresholds: 80% lines, 80% functions, 75% branches
148
+ - `npm test` must pass before any PR
149
+ - Strict TypeScript — `strict: true`, no `any`
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,44 @@
1
+ ;(function () {
2
+ 'use strict'
3
+
4
+ window.__tuimon_ready__ = false
5
+
6
+ window.__tuimon_update__ = function (data) {
7
+ window.__tuimon_ready__ = false
8
+ window.dispatchEvent(new CustomEvent('tuimon:update', { detail: data }))
9
+ window.__tuimon_ready__ = true
10
+ }
11
+
12
+ window.TuiMon = {
13
+ onUpdate(callback) {
14
+ window.addEventListener('tuimon:update', function (e) { callback(e.detail) })
15
+ },
16
+
17
+ set(selector, value) {
18
+ var el = document.querySelector(selector)
19
+ if (!el) return
20
+ if (typeof value === 'string') el.textContent = value
21
+ else if (typeof value === 'number') el.textContent = value.toLocaleString()
22
+ else if (typeof value === 'object' && value !== null) Object.assign(el.style, value)
23
+ },
24
+
25
+ notify(message, duration) {
26
+ duration = duration || 2000
27
+ window.dispatchEvent(new CustomEvent('tuimon:notify', { detail: { message: message, duration: duration } }))
28
+ },
29
+ }
30
+
31
+ // Auto-add shortcut badges to panels with data-tm-key
32
+ document.addEventListener('DOMContentLoaded', function () {
33
+ document.querySelectorAll('[data-tm-key]').forEach(function (panel) {
34
+ var key = panel.getAttribute('data-tm-key')
35
+ var label = panel.getAttribute('data-tm-label') || ''
36
+ if (!key) return
37
+ var badge = document.createElement('div')
38
+ badge.style.cssText = 'position:absolute;top:8px;right:8px;background:rgba(0,0,0,0.6);color:#58a6ff;padding:2px 8px;border-radius:4px;font-size:12px;font-family:monospace;pointer-events:none;z-index:10;'
39
+ badge.textContent = '[' + key.toUpperCase() + ']' + (label ? ' ' + label : '')
40
+ panel.style.position = panel.style.position || 'relative'
41
+ panel.appendChild(badge)
42
+ })
43
+ })
44
+ })()
@@ -0,0 +1,7 @@
1
+ import type { BrowserHandle } from './types.js';
2
+ export declare function createBrowser({ url, width, height, }: {
3
+ url: string;
4
+ width: number;
5
+ height: number;
6
+ }): Promise<BrowserHandle>;
7
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,wBAAsB,aAAa,CAAC,EAClC,GAAG,EACH,KAAK,EACL,MAAM,GACP,EAAE;IACD,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,aAAa,CAAC,CA8DzB"}
@@ -0,0 +1,57 @@
1
+ import { chromium } from 'playwright';
2
+ export async function createBrowser({ url, width, height, }) {
3
+ const browser = await chromium.launch({ headless: true });
4
+ const context = await browser.newContext();
5
+ const page = await context.newPage();
6
+ await page.setViewportSize({ width, height });
7
+ await page.goto(url, { waitUntil: 'domcontentloaded' });
8
+ let crashCount = 0;
9
+ page.on('crash', async () => {
10
+ crashCount++;
11
+ if (crashCount > 3) {
12
+ process.stderr.write('[tuimon] page crashed repeatedly — giving up on reload\n');
13
+ return;
14
+ }
15
+ process.stderr.write(`[tuimon] page crashed (attempt ${crashCount}/3), reloading\n`);
16
+ try {
17
+ await page.reload();
18
+ }
19
+ catch {
20
+ // ignore reload failures
21
+ }
22
+ });
23
+ page.on('pageerror', (err) => {
24
+ process.stderr.write(`tuimon: page error: ${err.message}\n`);
25
+ });
26
+ return {
27
+ async screenshot() {
28
+ const buf = await page.screenshot({ type: 'png' });
29
+ return Buffer.from(buf);
30
+ },
31
+ async pushData(data) {
32
+ await page.evaluate((d) => {
33
+ const win = globalThis;
34
+ if (typeof win['__tuimon_update__'] === 'function') {
35
+ ;
36
+ win['__tuimon_update__'](d);
37
+ }
38
+ }, data);
39
+ try {
40
+ await page.waitForFunction(() => globalThis['__tuimon_ready__'] === true, { timeout: 2000 });
41
+ }
42
+ catch {
43
+ // timeout is acceptable — page may not have the client script yet
44
+ }
45
+ },
46
+ async navigate(newUrl) {
47
+ await page.goto(newUrl, { waitUntil: 'domcontentloaded' });
48
+ },
49
+ async resize(w, h) {
50
+ await page.setViewportSize({ width: w, height: h });
51
+ },
52
+ async close() {
53
+ await browser.close();
54
+ },
55
+ };
56
+ }
57
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAGrC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAClC,GAAG,EACH,KAAK,EACL,MAAM,GAKP;IACC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACzD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAA;IAC1C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;IAEpC,MAAM,IAAI,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAA;IAC7C,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAA;IAEvD,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE;QAC1B,UAAU,EAAE,CAAA;QACZ,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;YAChF,OAAM;QACR,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,UAAU,kBAAkB,CAAC,CAAA;QACpF,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,MAAM,EAAE,CAAA;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,EAAE;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,GAAG,CAAC,OAAO,IAAI,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;IAEF,OAAO;QACL,KAAK,CAAC,UAAU;YACd,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;YAClD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACzB,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,IAA6B;YAC1C,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAA0B,EAAE,EAAE;gBACjD,MAAM,GAAG,GAAG,UAAqC,CAAA;gBACjD,IAAI,OAAO,GAAG,CAAC,mBAAmB,CAAC,KAAK,UAAU,EAAE,CAAC;oBACnD,CAAC;oBAAC,GAAG,CAAC,mBAAmB,CAA0C,CAAC,CAAC,CAAC,CAAA;gBACxE,CAAC;YACH,CAAC,EAAE,IAAI,CAAC,CAAA;YACR,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,eAAe,CACxB,GAAG,EAAE,CAAE,UAAsC,CAAC,kBAAkB,CAAC,KAAK,IAAI,EAC1E,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAA;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,kEAAkE;YACpE,CAAC;QACH,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,MAAc;YAC3B,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAAC,CAAA;QAC5D,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,CAAS,EAAE,CAAS;YAC/B,MAAM,IAAI,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;QACrD,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA;QACvB,CAAC;KACF,CAAA;AACH,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import path from 'node:path';
4
+ import { existsSync, mkdirSync, cpSync } from 'node:fs';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { detectGraphicsSupport } from './detect.js';
7
+ process.on('unhandledRejection', (reason) => {
8
+ console.error('[tuimon] Unhandled rejection:', reason);
9
+ process.exit(1);
10
+ });
11
+ process.on('uncaughtException', (error) => {
12
+ console.error('[tuimon] Uncaught exception:', error);
13
+ process.exit(1);
14
+ });
15
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
+ const pkgRoot = path.resolve(__dirname, '..');
17
+ const program = new Command();
18
+ program
19
+ .name('tuimon')
20
+ .description('Render beautiful HTML dashboards directly in your terminal.')
21
+ .version('0.1.0');
22
+ program
23
+ .command('start')
24
+ .description('Start a TuiMon dashboard')
25
+ .option('-c, --config <path>', 'Path to config file', 'tuimon.config.ts')
26
+ .action(async (opts) => {
27
+ const configPath = path.resolve(process.cwd(), opts.config);
28
+ if (!existsSync(configPath)) {
29
+ console.error(`[tuimon] Config file not found: ${configPath}`);
30
+ console.error('[tuimon] Run "tuimon init" to create a starter project.');
31
+ process.exit(1);
32
+ }
33
+ // Dynamic import of the config — it self-starts
34
+ await import(configPath);
35
+ });
36
+ program
37
+ .command('init')
38
+ .description('Scaffold a starter TuiMon project in the current directory')
39
+ .action(() => {
40
+ const starterDir = path.resolve(pkgRoot, 'templates', 'starter');
41
+ const targetDir = process.cwd();
42
+ const pagesDir = path.join(targetDir, 'pages');
43
+ const configFile = path.join(targetDir, 'tuimon.config.ts');
44
+ if (existsSync(configFile)) {
45
+ console.error('[tuimon] tuimon.config.ts already exists. Aborting.');
46
+ process.exit(1);
47
+ }
48
+ mkdirSync(pagesDir, { recursive: true });
49
+ cpSync(path.join(starterDir, 'pages'), pagesDir, { recursive: true });
50
+ cpSync(path.join(starterDir, 'tuimon.config.ts'), configFile);
51
+ console.log('TuiMon project initialized!');
52
+ console.log('');
53
+ console.log(' Files created:');
54
+ console.log(' pages/overview.html');
55
+ console.log(' pages/cpu-detail.html');
56
+ console.log(' pages/memory-detail.html');
57
+ console.log(' tuimon.config.ts');
58
+ console.log('');
59
+ console.log(' Next steps:');
60
+ console.log(' npx tuimon start');
61
+ });
62
+ program
63
+ .command('check')
64
+ .description('Check terminal graphics support')
65
+ .action(async () => {
66
+ const support = await detectGraphicsSupport();
67
+ console.log('');
68
+ console.log('TuiMon Terminal Check');
69
+ console.log('\u2500'.repeat(21));
70
+ console.log(`Kitty protocol: ${support.kitty ? '\u2713 supported' : '\u2717 not detected'}`);
71
+ console.log(`Sixel protocol: ${support.sixel ? '\u2713 supported' : '\u2717 not detected'}`);
72
+ console.log(`iTerm2 protocol: ${support.iterm2 ? '\u2713 supported' : '\u2717 not detected'}`);
73
+ console.log('');
74
+ if (support.protocol) {
75
+ console.log(`\u2713 Will use: ${support.protocol}`);
76
+ const term = process.env['TERM_PROGRAM'] ?? process.env['TERM'] ?? 'unknown';
77
+ console.log(` ${term}`);
78
+ }
79
+ else {
80
+ console.log('\u2717 No supported graphics protocol detected.');
81
+ console.log(' TuiMon requires Kitty, iTerm2, or Sixel graphics support.');
82
+ }
83
+ console.log('');
84
+ process.exit(support.protocol ? 0 : 1);
85
+ });
86
+ program.parse();
87
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { GraphicsSupport, TerminalDimensions } from './types.js';
2
+ export declare function detectGraphicsSupport(opts?: {
3
+ skipQuery?: boolean;
4
+ }): Promise<GraphicsSupport>;
5
+ export declare function getTerminalDimensions(opts?: {
6
+ skipQuery?: boolean;
7
+ }): Promise<TerminalDimensions>;
8
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAwGrE,wBAAsB,qBAAqB,CACzC,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,eAAe,CAAC,CA2B1B;AAED,wBAAsB,qBAAqB,CACzC,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAqB7B"}
package/dist/detect.js ADDED
@@ -0,0 +1,141 @@
1
+ // ─── Env-based detection helpers ─────────────────────────────────────────────
2
+ const KITTY_TERM_PROGRAMS = ['WezTerm', 'ghostty', 'Ghostty'];
3
+ const ITERM2_TERM_PROGRAMS = ['iTerm.app', 'iTerm2'];
4
+ function detectKittyEnv() {
5
+ const term = process.env.TERM ?? '';
6
+ const termProgram = process.env.TERM_PROGRAM ?? '';
7
+ if (term === 'xterm-kitty')
8
+ return true;
9
+ if (KITTY_TERM_PROGRAMS.includes(termProgram))
10
+ return true;
11
+ return false;
12
+ }
13
+ function detectIterm2Env() {
14
+ const termProgram = process.env.TERM_PROGRAM ?? '';
15
+ return ITERM2_TERM_PROGRAMS.includes(termProgram);
16
+ }
17
+ function detectSixelEnv() {
18
+ const term = process.env.TERM ?? '';
19
+ const termProgram = process.env.TERM_PROGRAM ?? '';
20
+ if (term === 'mlterm')
21
+ return true;
22
+ if (termProgram === 'vscode')
23
+ return true;
24
+ return false;
25
+ }
26
+ // ─── Terminal query helpers ──────────────────────────────────────────────────
27
+ let queryLock = Promise.resolve();
28
+ function queryKittySupport() {
29
+ return new Promise((resolve) => {
30
+ const timeout = setTimeout(() => {
31
+ cleanup();
32
+ resolve(false);
33
+ }, 500);
34
+ const onData = (data) => {
35
+ const str = data.toString();
36
+ if (str.includes('_G')) {
37
+ cleanup();
38
+ resolve(true);
39
+ }
40
+ };
41
+ const cleanup = () => {
42
+ clearTimeout(timeout);
43
+ process.stdin.removeListener('data', onData);
44
+ if (wasRaw !== undefined) {
45
+ try {
46
+ process.stdin.setRawMode(wasRaw);
47
+ }
48
+ catch { }
49
+ }
50
+ };
51
+ let wasRaw;
52
+ try {
53
+ wasRaw = process.stdin.isRaw;
54
+ process.stdin.setRawMode(true);
55
+ }
56
+ catch { }
57
+ process.stdin.on('data', onData);
58
+ process.stdout.write('\x1b_Ga=q;\x1b\\');
59
+ });
60
+ }
61
+ function queryPixelDimensions() {
62
+ return new Promise((resolve) => {
63
+ const timeout = setTimeout(() => {
64
+ cleanup();
65
+ resolve(null);
66
+ }, 500);
67
+ const onData = (data) => {
68
+ const str = data.toString();
69
+ // Response format: \x1b[4;<height>;<width>t
70
+ const match = str.match(/\x1b\[4;(\d+);(\d+)t/);
71
+ if (match) {
72
+ cleanup();
73
+ resolve({ width: parseInt(match[2] ?? '0', 10), height: parseInt(match[1] ?? '0', 10) });
74
+ }
75
+ };
76
+ const cleanup = () => {
77
+ clearTimeout(timeout);
78
+ process.stdin.removeListener('data', onData);
79
+ if (wasRaw !== undefined) {
80
+ try {
81
+ process.stdin.setRawMode(wasRaw);
82
+ }
83
+ catch { }
84
+ }
85
+ };
86
+ let wasRaw;
87
+ try {
88
+ wasRaw = process.stdin.isRaw;
89
+ process.stdin.setRawMode(true);
90
+ }
91
+ catch { }
92
+ process.stdin.on('data', onData);
93
+ process.stdout.write('\x1b[14t');
94
+ });
95
+ }
96
+ // ─── Public API ──────────────────────────────────────────────────────────────
97
+ export async function detectGraphicsSupport(opts) {
98
+ const skipQuery = opts?.skipQuery ?? false;
99
+ // Start with environment-based detection
100
+ let kitty = detectKittyEnv();
101
+ const iterm2 = detectIterm2Env();
102
+ const sixel = detectSixelEnv();
103
+ // If not skipping queries and env didn't detect kitty, try querying (serialized)
104
+ if (!skipQuery && !kitty) {
105
+ await queryLock;
106
+ const p = queryKittySupport();
107
+ queryLock = p.catch(() => { });
108
+ kitty = await p;
109
+ }
110
+ // Determine protocol with priority: kitty > iterm2 > sixel
111
+ let protocol = null;
112
+ if (kitty) {
113
+ protocol = 'kitty';
114
+ }
115
+ else if (iterm2) {
116
+ protocol = 'iterm2';
117
+ }
118
+ else if (sixel) {
119
+ protocol = 'sixel';
120
+ }
121
+ return { kitty, sixel, iterm2, protocol };
122
+ }
123
+ export async function getTerminalDimensions(opts) {
124
+ const skipQuery = opts?.skipQuery ?? false;
125
+ const cols = process.stdout.columns ?? 80;
126
+ const rows = process.stdout.rows ?? 24;
127
+ let pixelWidth = 1600;
128
+ let pixelHeight = 900;
129
+ if (!skipQuery) {
130
+ await queryLock;
131
+ const p = queryPixelDimensions();
132
+ queryLock = p.catch(() => { });
133
+ const queried = await p;
134
+ if (queried) {
135
+ pixelWidth = queried.width;
136
+ pixelHeight = queried.height;
137
+ }
138
+ }
139
+ return { cols, rows, pixelWidth, pixelHeight };
140
+ }
141
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function encodeAndRender(buffer: Buffer, opts: {
2
+ protocol: 'kitty' | 'sixel';
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=encoder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../src/encoder.ts"],"names":[],"mappings":"AAKA,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAA;CAAE,GACpC,OAAO,CAAC,IAAI,CAAC,CAMf"}