@ghosty-ai/cli 0.1.0 → 0.1.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/dist/cli.js CHANGED
@@ -30,12 +30,12 @@ async function main() {
30
30
  const [, , command, ...args] = process.argv;
31
31
  switch (command) {
32
32
  case "create": {
33
- const { runCreate } = await import("./create-MLDT2ZRH.js");
33
+ const { runCreate } = await import("./create-24B6CJE4.js");
34
34
  await runCreate(args[0]);
35
35
  break;
36
36
  }
37
37
  case "dev": {
38
- const { runDev } = await import("./dev-WPS3QYGP.js");
38
+ const { runDev } = await import("./dev-Q6MCZHRF.js");
39
39
  await runDev();
40
40
  break;
41
41
  }
@@ -25,93 +25,98 @@ var MANIFEST_TEMPLATE = `{
25
25
  }
26
26
  `;
27
27
  function mainTsTemplate(name) {
28
+ const displayName = name.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
28
29
  return `import { createPlugin } from '@ghosty-ai/sdk';
29
30
 
30
31
  const plugin = createPlugin();
31
32
 
32
- // Set context for the AI chat overlay
33
- plugin.setContext({
34
- title: '${name}',
35
- data: { message: 'Hello from ${name}!' },
36
- summary: 'This plugin is running.',
37
- });
38
-
39
- // Listen for theme changes
40
33
  plugin.onThemeChange((theme) => {
41
34
  document.documentElement.setAttribute('data-theme', theme);
42
35
  });
43
36
 
44
- // Signal that the plugin is ready
37
+ plugin.setContext({
38
+ title: '${displayName}',
39
+ data: {},
40
+ summary: '${displayName} plugin.',
41
+ });
42
+
45
43
  plugin.ready();
46
44
 
47
- // Your plugin code goes here
48
- const app = document.getElementById('app');
49
- if (app) {
50
- app.innerHTML = \`
51
- <div class="container">
52
- <h1>${name}</h1>
53
- <p>Edit <code>main.ts</code> and save to see changes.</p>
54
- </div>
55
- \`;
56
- }
45
+ document.body.innerHTML = \`
46
+ <div class="welcome">
47
+ <h1>Ghosty</h1>
48
+ <a href="https://dev.ghosty.to" target="_blank" rel="noopener">dev.ghosty.to</a>
49
+ <p>Edit <strong>main.ts</strong> to start building your plugin.</p>
50
+ </div>
51
+ \`;
57
52
  `;
58
53
  }
59
- var STYLES_TEMPLATE = `/* Ghosty Plugin Styles */
54
+ var STYLES_TEMPLATE = `*, *::before, *::after {
55
+ margin: 0;
56
+ padding: 0;
57
+ box-sizing: border-box;
58
+ }
60
59
 
61
60
  :root {
62
61
  --bg: #ffffff;
63
- --text: #23272a;
64
- --text-secondary: #6b7280;
65
- --surface: #f9fafb;
66
- --border: #e5e7eb;
67
- --primary: #5865f2;
62
+ --text: #1a1a1a;
63
+ --text-secondary: #9ca3af;
64
+ --border: #f0f0f0;
68
65
  }
69
66
 
70
67
  [data-theme='dark'] {
71
- --bg: #171717;
68
+ --bg: #0d0d0d;
72
69
  --text: #ffffff;
73
- --text-secondary: #8b8b8b;
74
- --surface: #1f1f1f;
75
- --border: #292929;
76
- --primary: #7983f5;
77
- }
78
-
79
- *, *::before, *::after {
80
- margin: 0;
81
- padding: 0;
82
- box-sizing: border-box;
70
+ --text-secondary: #555;
71
+ --border: #1a1a1a;
83
72
  }
84
73
 
85
74
  body {
86
75
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
87
76
  background: var(--bg);
88
77
  color: var(--text);
89
- line-height: 1.5;
90
- transition: background 300ms, color 300ms;
78
+ min-height: 100vh;
79
+ transition: background 500ms, color 500ms;
91
80
  }
92
81
 
93
- .container {
94
- max-width: 600px;
95
- margin: 2rem auto;
96
- padding: 0 1rem;
82
+ .welcome {
83
+ display: flex;
84
+ flex-direction: column;
85
+ align-items: center;
86
+ justify-content: center;
87
+ min-height: 100vh;
88
+ gap: 0.5rem;
89
+ text-align: center;
90
+ padding: 2rem;
97
91
  }
98
92
 
99
- h1 {
100
- font-size: 1.5rem;
101
- font-weight: 700;
102
- margin-bottom: 0.5rem;
93
+ .welcome h1 {
94
+ font-family: 'Plus Jakarta Sans', 'Inter', -apple-system, sans-serif;
95
+ font-size: 2.5rem;
96
+ font-weight: 800;
97
+ letter-spacing: -0.03em;
103
98
  }
104
99
 
105
- p {
100
+ .welcome a {
101
+ font-size: 1rem;
106
102
  color: var(--text-secondary);
103
+ text-decoration: none;
104
+ transition: color 200ms;
107
105
  }
108
106
 
109
- code {
110
- background: var(--surface);
111
- border: 1px solid var(--border);
112
- border-radius: 4px;
113
- padding: 0.125rem 0.375rem;
114
- font-size: 0.875em;
107
+ .welcome a:hover {
108
+ color: var(--text);
109
+ text-decoration: underline;
110
+ }
111
+
112
+ .welcome p {
113
+ font-size: 0.875rem;
114
+ color: var(--text-secondary);
115
+ margin-top: 1.5rem;
116
+ }
117
+
118
+ .welcome p strong {
119
+ color: var(--text);
115
120
  }
116
121
  `;
117
122
  async function runCreate(nameArg) {
@@ -238,23 +238,6 @@ function generateShellHtml(options) {
238
238
 
239
239
  .iframe-wrap { flex: 1; position: relative; background: #000; }
240
240
  .iframe-wrap iframe { width: 100%; height: 100%; border: 0; }
241
-
242
- .debug { flex-shrink: 0; background: #111; border-top: 1px solid #292929; display: flex; flex-direction: column; max-height: 220px; transition: max-height 200ms; }
243
- .debug.collapsed { max-height: 32px; }
244
- .debug-header { display: flex; align-items: center; justify-content: space-between; padding: 0 16px; height: 32px; background: #171717; cursor: pointer; user-select: none; flex-shrink: 0; }
245
- .debug-header span { font-size: 11px; font-weight: 600; color: rgba(255,255,255,0.4); }
246
- .debug-count { background: #292929; padding: 1px 7px; border-radius: 9999px; font-size: 10px; color: rgba(255,255,255,0.5); margin-left: 8px; }
247
- .debug-log { flex: 1; overflow-y: auto; padding: 6px 16px; font-family: 'SF Mono', 'Cascadia Code', Consolas, monospace; font-size: 11px; line-height: 1.7; }
248
- .debug-log::-webkit-scrollbar { width: 5px; }
249
- .debug-log::-webkit-scrollbar-thumb { background: #333; border-radius: 3px; }
250
- .msg { padding: 1px 0; opacity: 0.8; }
251
- .msg:hover { opacity: 1; }
252
- .msg-time { color: rgba(255,255,255,0.2); margin-right: 8px; }
253
- .msg-in { color: #4ade80; }
254
- .msg-out { color: #facc15; }
255
- .msg-sys { color: #7983f5; }
256
- .msg-type { font-weight: 600; }
257
- .msg-payload { color: rgba(255,255,255,0.3); margin-left: 6px; }
258
241
  </style>
259
242
  </head>
260
243
  <body>
@@ -269,44 +252,17 @@ function generateShellHtml(options) {
269
252
  </div>
270
253
 
271
254
  <div class="iframe-wrap">
272
- <iframe id="frame" src="/plugin/index.html" sandbox="allow-scripts"></iframe>
273
- </div>
274
-
275
- <div class="debug" id="debug">
276
- <div class="debug-header" id="debugToggle">
277
- <div><span>Bridge</span><span class="debug-count" id="msgCount">0</span></div>
278
- <span id="arrow">&#9660;</span>
279
- </div>
280
- <div class="debug-log" id="log"></div>
255
+ <iframe id="frame" src="/plugin/index.html" sandbox="allow-scripts allow-popups"></iframe>
281
256
  </div>
282
257
 
283
258
  <script>
284
259
  var theme = 'dark';
285
260
  var manifest = ${manifestJson};
286
261
  var frame = document.getElementById('frame');
287
- var log = document.getElementById('log');
288
- var msgTotal = 0;
289
-
290
- function ts() {
291
- return new Date().toLocaleTimeString('en-US', { hour12: false, fractionalSecondDigits: 3 });
292
- }
293
-
294
- function logMsg(dir, type, payload) {
295
- var el = document.createElement('div');
296
- el.className = 'msg';
297
- var cls = dir === 'IN' ? 'msg-in' : dir === 'OUT' ? 'msg-out' : 'msg-sys';
298
- var pl = payload !== undefined ? JSON.stringify(payload).slice(0, 300) : '';
299
- el.innerHTML = '<span class="msg-time">' + ts() + '</span><span class="' + cls + ' msg-type">' + dir + ' ' + type + '</span>' + (pl ? '<span class="msg-payload">' + pl + '</span>' : '');
300
- log.appendChild(el);
301
- log.scrollTop = log.scrollHeight;
302
- msgTotal++;
303
- document.getElementById('msgCount').textContent = msgTotal;
304
- }
305
262
 
306
263
  function send(type, messageId, payload) {
307
264
  if (!frame.contentWindow) return;
308
265
  frame.contentWindow.postMessage({ protocol: 'ghosty-bridge', version: 1, type: type, messageId: messageId, payload: payload }, '*');
309
- logMsg('OUT', type, payload);
310
266
  }
311
267
 
312
268
  window.addEventListener('message', function(e) {
@@ -314,35 +270,25 @@ function generateShellHtml(options) {
314
270
  if (!msg || msg.protocol !== 'ghosty-bridge' || msg.version !== 1) return;
315
271
  if (e.source !== frame.contentWindow) return;
316
272
 
317
- logMsg('IN', msg.type, msg.payload);
318
-
319
273
  switch (msg.type) {
320
274
  case 'GHOSTY_READY':
321
275
  send('GHOSTY_THEME_CHANGE', 'init-' + Date.now(), { theme: theme });
322
276
  break;
323
-
324
277
  case 'GHOSTY_SET_CONTEXT':
325
278
  break;
326
-
327
279
  case 'GHOSTY_GET_USER':
328
280
  send('GHOSTY_GET_USER_RESPONSE', msg.messageId, { displayName: 'Developer', avatarUrl: null, theme: theme });
329
281
  break;
330
-
331
282
  case 'GHOSTY_GET_MANIFEST':
332
283
  send('GHOSTY_GET_MANIFEST_RESPONSE', msg.messageId, manifest);
333
284
  break;
334
-
335
285
  case 'GHOSTY_GET_MEDIA_BASE':
336
286
  send('GHOSTY_GET_MEDIA_BASE_RESPONSE', msg.messageId, { apiBaseUrl: 'http://localhost:${port}', pluginId: 'dev' });
337
287
  break;
338
-
339
288
  case 'GHOSTY_FETCH':
340
289
  var url = (msg.payload && msg.payload.url) || '';
341
290
  var opts = (msg.payload && msg.payload.options) || {};
342
- if (!url) {
343
- send('GHOSTY_FETCH_RESPONSE', msg.messageId, { ok: false, status: 0, data: 'No URL', contentType: '' });
344
- break;
345
- }
291
+ if (!url) { send('GHOSTY_FETCH_RESPONSE', msg.messageId, { ok: false, status: 0, data: 'No URL', contentType: '' }); break; }
346
292
  fetch('/proxy?url=' + encodeURIComponent(url), {
347
293
  method: opts.method || 'GET',
348
294
  headers: Object.assign({ 'x-proxy-method': opts.method || 'GET' }, opts.headers || {}),
@@ -350,14 +296,10 @@ function generateShellHtml(options) {
350
296
  })
351
297
  .then(function(res) { return res.json(); })
352
298
  .then(function(data) { send('GHOSTY_FETCH_RESPONSE', msg.messageId, data); })
353
- .catch(function(err) {
354
- send('GHOSTY_FETCH_RESPONSE', msg.messageId, { ok: false, status: 0, data: err.message, contentType: '' });
355
- });
299
+ .catch(function(err) { send('GHOSTY_FETCH_RESPONSE', msg.messageId, { ok: false, status: 0, data: err.message, contentType: '' }); });
356
300
  break;
357
-
358
301
  case 'GHOSTY_REGISTER_TOOLS':
359
302
  break;
360
-
361
303
  case 'GHOSTY_TOOL_CALL_RESPONSE':
362
304
  break;
363
305
  }
@@ -372,24 +314,11 @@ function generateShellHtml(options) {
372
314
  send('GHOSTY_THEME_CHANGE', 'theme-' + Date.now(), { theme: theme });
373
315
  });
374
316
 
375
- // Debug toggle
376
- var debugPanel = document.getElementById('debug');
377
- document.getElementById('debugToggle').addEventListener('click', function() {
378
- debugPanel.classList.toggle('collapsed');
379
- document.getElementById('arrow').innerHTML = debugPanel.classList.contains('collapsed') ? '&#9650;' : '&#9660;';
380
- });
381
-
382
317
  // Hot reload
383
318
  (function connect() {
384
319
  var ws = new WebSocket('ws://localhost:${port}/__ws');
385
320
  ws.onmessage = function(e) {
386
- if (e.data === 'reload') {
387
- frame.src = frame.src;
388
- logMsg('SYS', 'HOT_RELOAD', { message: 'Rebuilt, reloading...' });
389
- }
390
- if (e.data.startsWith('error:')) {
391
- logMsg('SYS', 'BUILD_ERROR', { message: e.data.slice(6) });
392
- }
321
+ if (e.data === 'reload') { frame.src = frame.src; }
393
322
  };
394
323
  ws.onclose = function() { setTimeout(connect, 1000); };
395
324
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghosty-ai/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "CLI tools for Ghosty plugin development — scaffold, preview, and test plugins locally.",
5
5
  "license": "MIT",
6
6
  "type": "module",