clideck 1.30.0 → 1.30.2

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.
@@ -28,12 +28,12 @@
28
28
  "presetId": "codex",
29
29
  "name": "Codex",
30
30
  "icon": "/img/codex.png",
31
- "command": "codex --no-alt-screen",
31
+ "command": "codex",
32
32
  "minVersion": "0.118.0",
33
33
  "installCmd": "npm install -g @openai/codex",
34
34
  "isAgent": true,
35
35
  "canResume": true,
36
- "resumeCommand": "codex resume {{sessionId}} --no-alt-screen",
36
+ "resumeCommand": "codex resume {{sessionId}}",
37
37
  "sessionIdPattern": "Session:\\s+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})",
38
38
  "outputMarker": "\u2022",
39
39
  "telemetryConfigPath": "~/.codex/config.toml",
package/config.js CHANGED
@@ -129,10 +129,13 @@ function migrate(cfg) {
129
129
  if (cmd.telemetryStatus === undefined) cmd.telemetryStatus = null;
130
130
  // Sync bridge config from preset
131
131
  if (preset?.bridge) cmd.bridge = preset.bridge;
132
- // Codex: add --no-alt-screen to avoid blank screen in embedded xterm
132
+ // Codex: keep shipped default commands aligned with the current preset.
133
+ // Only rewrite the known default strings so custom Codex commands stay intact.
133
134
  if (preset?.presetId === 'codex') {
134
- if (cmd.command === 'codex') cmd.command = preset.command;
135
- if (cmd.resumeCommand === 'codex resume {{sessionId}}') cmd.resumeCommand = preset.resumeCommand;
135
+ if (cmd.command === 'codex' || cmd.command === 'codex --no-alt-screen') cmd.command = preset.command;
136
+ if (cmd.resumeCommand === 'codex resume {{sessionId}}' || cmd.resumeCommand === 'codex resume {{sessionId}} --no-alt-screen') {
137
+ cmd.resumeCommand = preset.resumeCommand;
138
+ }
136
139
  }
137
140
  }
138
141
  // Auto-add any shipped presets not yet in the commands list
package/handlers.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const { readFileSync, writeFileSync, mkdirSync, existsSync, copyFileSync, unlinkSync } = require('fs');
2
2
  const { join, dirname } = require('path');
3
- const { execFileSync } = require('child_process');
3
+ const { execFileSync, execFile } = require('child_process');
4
4
  const os = require('os');
5
5
  const config = require('./config');
6
6
  const sessions = require('./sessions');
@@ -397,6 +397,28 @@ function onConnection(ws) {
397
397
  break;
398
398
  }
399
399
 
400
+ case 'project.openPath': {
401
+ const proj = cfg.projects?.find(p => p.id === msg.id);
402
+ if (!proj?.path) {
403
+ ws.send(JSON.stringify({ type: 'project.openPath.result', id: msg.id, success: false, error: 'Project path is not set' }));
404
+ break;
405
+ }
406
+ const cmd = process.platform === 'darwin'
407
+ ? 'open'
408
+ : process.platform === 'win32'
409
+ ? 'explorer'
410
+ : 'xdg-open';
411
+ execFile(cmd, [proj.path], { shell: process.platform === 'win32' }, (err) => {
412
+ ws.send(JSON.stringify({
413
+ type: 'project.openPath.result',
414
+ id: msg.id,
415
+ success: !err,
416
+ error: err ? err.message : '',
417
+ }));
418
+ });
419
+ break;
420
+ }
421
+
400
422
  case 'dirs.list': {
401
423
  const target = msg.path || cfg.defaultPath;
402
424
  const result = listDirs(target, !!msg.showHidden);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clideck",
3
- "version": "1.30.0",
3
+ "version": "1.30.2",
4
4
  "description": "One screen for all your AI coding agents — run, monitor, and manage multiple CLI agents from a single browser tab",
5
5
  "main": "server.js",
6
6
  "bin": {
@@ -10,6 +10,7 @@ const DATA_DIR = join(require('os').homedir(), '.clideck', 'autopilot');
10
10
  const projects = new Map(); // projectId → Project
11
11
  const tokenUsage = new Map(); // projectId → { input, output }
12
12
  const menuPending = new Set(); // sessionIds with a menu awaiting auto-approve
13
+ const idleCaptureTimers = new Map(); // sessionId → timeout id for deferred idle capture
13
14
  let api = null;
14
15
  let piAi = null;
15
16
 
@@ -84,6 +85,7 @@ function latestAgentOutput(id) {
84
85
  // --- Consumed state (persisted per-project: role → boolean) ---
85
86
 
86
87
  function captureIdleOutput(id, pid, proj) {
88
+ idleCaptureTimers.delete(id);
87
89
  if (!projects.has(pid)) return;
88
90
  if (proj.status.get(id)) return;
89
91
  const w = proj.workers.get(id);
@@ -114,6 +116,19 @@ function captureIdleOutput(id, pid, proj) {
114
116
  }
115
117
  }
116
118
 
119
+ function clearIdleCaptureTimer(id) {
120
+ const timer = idleCaptureTimers.get(id);
121
+ if (timer) {
122
+ clearTimeout(timer);
123
+ idleCaptureTimers.delete(id);
124
+ }
125
+ }
126
+
127
+ function scheduleIdleCapture(id, pid, proj) {
128
+ clearIdleCaptureTimer(id);
129
+ idleCaptureTimers.set(id, setTimeout(() => captureIdleOutput(id, pid, proj), 5000));
130
+ }
131
+
117
132
  function resetProjectState(pid) {
118
133
  try { unlinkSync(kbPath(pid)); } catch {}
119
134
  }
@@ -165,10 +180,14 @@ function workerByRole(proj, role) {
165
180
  return null;
166
181
  }
167
182
 
183
+ function isAutopilotWorkerSession(s) {
184
+ return s.projectId && s.roleName && s.presetId !== 'shell';
185
+ }
186
+
168
187
  function discoverWorkers(pid) {
169
188
  const workers = new Map();
170
189
  const status = new Map();
171
- for (const s of api.getSessions().filter(s => s.projectId === pid && s.roleName)) {
190
+ for (const s of api.getSessions().filter(s => s.projectId === pid && isAutopilotWorkerSession(s))) {
172
191
  workers.set(s.id, { role: s.roleName, name: s.name, presetId: s.presetId });
173
192
  // Sessions start idle. Status is tracked by notifyStatus() on every
174
193
  // working/idle transition. If s.working is undefined, no transition was
@@ -182,7 +201,7 @@ function discoverWorkers(pid) {
182
201
  function refreshWorkers(pid, proj) {
183
202
  const live = new Map();
184
203
  const liveStatus = new Map();
185
- for (const s of api.getSessions().filter(s => s.projectId === pid && s.roleName)) {
204
+ for (const s of api.getSessions().filter(s => s.projectId === pid && isAutopilotWorkerSession(s))) {
186
205
  live.set(s.id, { role: s.roleName, name: s.name, presetId: s.presetId });
187
206
  liveStatus.set(s.id, s.working === true);
188
207
  }
@@ -669,6 +688,7 @@ async function start(pid) {
669
688
  function stop(pid, keepPill) {
670
689
  const proj = projects.get(pid);
671
690
  if (!proj) return;
691
+ for (const [sid] of proj.workers) clearIdleCaptureTimer(sid);
672
692
  for (const [sid] of proj.workers) api.setAutoApproveMenu(sid, false);
673
693
  projects.delete(pid);
674
694
  // api.log(`Stopped: ${pid}`);
@@ -710,7 +730,10 @@ module.exports.init = function (pluginApi) {
710
730
  api.onMenuDetected((id, choices) => {
711
731
  if (!choices?.length) return;
712
732
  const [pid] = projectFor(id);
713
- if (pid) menuPending.add(id);
733
+ if (pid) {
734
+ menuPending.add(id);
735
+ clearIdleCaptureTimer(id);
736
+ }
714
737
  });
715
738
 
716
739
  // Status change — the main routing trigger (only when ALL workers are idle)
@@ -721,9 +744,13 @@ module.exports.init = function (pluginApi) {
721
744
  const w = proj.workers.get(id);
722
745
  const role = w?.role || id.slice(0, 8);
723
746
 
724
- if (working) { menuPending.delete(id); }
747
+ if (working) {
748
+ menuPending.delete(id);
749
+ clearIdleCaptureTimer(id);
750
+ }
725
751
 
726
752
  if (!working && menuPending.has(id)) {
753
+ clearIdleCaptureTimer(id);
727
754
  menuPending.delete(id);
728
755
  // api.log(`[status] ${role} → IDLE (menu pending — suppressed)`);
729
756
  return;
@@ -740,7 +767,7 @@ module.exports.init = function (pluginApi) {
740
767
  if (!proj.workers.has(id)) return;
741
768
 
742
769
  api.appendPillLog(pillId, `${role} → idle`);
743
- setTimeout(() => captureIdleOutput(id, pid, proj), 5000);
770
+ scheduleIdleCapture(id, pid, proj);
744
771
  });
745
772
 
746
773
  // Frontend queries
package/public/js/app.js CHANGED
@@ -15,19 +15,13 @@ import { renderPrompts } from './prompts.js';
15
15
  import { renderRoles } from './roles.js';
16
16
 
17
17
  const shownAgentHealthToasts = new Set();
18
+ let reconnectReplaySkip = null;
18
19
 
19
20
  function connect() {
20
21
  state.ws = new WebSocket(`ws://${location.host}`);
21
22
 
22
23
  state.ws.onopen = () => {
23
- for (const [, e] of state.terms) { e.ro.disconnect(); e.term.dispose(); e.el.remove(); }
24
- state.terms.clear();
25
- state.pills.clear();
26
- state.activePill = null;
27
- document.getElementById('session-list').innerHTML = '';
28
- document.getElementById('pill-log-panel')?.remove();
29
- state.active = null;
30
- document.getElementById('empty').style.display = 'flex';
24
+ reconnectReplaySkip = new Set(state.terms.keys());
31
25
  send({ type: 'remote.status' });
32
26
  };
33
27
 
@@ -64,8 +58,16 @@ function connect() {
64
58
  renderResumable();
65
59
  break;
66
60
  case 'sessions':
67
- msg.list.forEach(s => addTerminal(s.id, s.name, s.themeId, s.commandId, s.projectId, s.muted, s.lastPreview, s.presetId));
68
- if (msg.list.length) select(msg.list[0].id);
61
+ {
62
+ const liveIds = new Set(msg.list.map(s => s.id));
63
+ for (const id of [...state.terms.keys()]) {
64
+ if (!liveIds.has(id)) removeTerminal(id);
65
+ }
66
+ msg.list.forEach(s => addTerminal(s.id, s.name, s.themeId, s.commandId, s.projectId, s.muted, s.lastPreview, s.presetId));
67
+ if (!state.active || !state.terms.has(state.active)) {
68
+ if (msg.list.length) select(msg.list[0].id);
69
+ }
70
+ }
69
71
  break;
70
72
  case 'created':
71
73
  if (!state.terms.has(msg.id)) addTerminal(msg.id, msg.name, msg.themeId, msg.commandId, msg.projectId, msg.muted, msg.lastPreview, msg.presetId);
@@ -75,6 +77,7 @@ function connect() {
75
77
  break;
76
78
  case 'output': {
77
79
  const entry = state.terms.get(msg.id);
80
+ if (msg.replay && reconnectReplaySkip?.has(msg.id) && entry) break;
78
81
  if (entry && !entry.queue(msg.data)) entry.term.write(msg.data);
79
82
  updatePreview(msg.id);
80
83
  markUnread(msg.id);
@@ -104,6 +107,7 @@ function connect() {
104
107
  }
105
108
  case 'session.history': {
106
109
  const entry = state.terms.get(msg.id);
110
+ if (msg.replay && reconnectReplaySkip?.has(msg.id) && entry) break;
107
111
  if (entry && !entry.queue(msg.text + '\n')) entry.term.write(msg.text + '\n');
108
112
  updatePreview(msg.id);
109
113
  break;
@@ -231,6 +235,9 @@ function connect() {
231
235
  }
232
236
  break;
233
237
  }
238
+ case 'project.openPath.result':
239
+ if (!msg.success) showToast(msg.error || 'Failed to open project folder', { type: 'error' });
240
+ break;
234
241
  case 'sessions.saved':
235
242
  flashSaveIndicator();
236
243
  break;
@@ -251,8 +258,16 @@ function connect() {
251
258
  break;
252
259
  }
253
260
  case 'pills':
254
- state.pills.clear();
255
- for (const p of msg.list) addPill(p);
261
+ {
262
+ const liveIds = new Set(msg.list.map(p => p.id));
263
+ for (const id of [...state.pills.keys()]) {
264
+ if (!liveIds.has(id)) removePill(id);
265
+ }
266
+ for (const p of msg.list) {
267
+ if (state.pills.has(p.id)) updatePill(p);
268
+ else addPill(p);
269
+ }
270
+ }
256
271
  break;
257
272
  case 'pill.added':
258
273
  addPill(msg.pill);
@@ -326,6 +341,11 @@ sessionList.addEventListener('click', (e) => {
326
341
 
327
342
  // Project header click — toggle collapse (skip if just finished a drag)
328
343
  const projHeader = e.target.closest('.project-header');
344
+ if (e.target.closest('.project-path-btn')) {
345
+ const projId = e.target.closest('.project-header')?.dataset.projectId;
346
+ if (projId) send({ type: 'project.openPath', id: projId });
347
+ return;
348
+ }
329
349
  if (e.target.closest('.plugin-project-btn')) return; // handled by btn's own click listener
330
350
  if (projHeader && !e.target.closest('.project-menu-btn') && !wasDragging()) {
331
351
  toggleProjectCollapse(projHeader.dataset.projectId);
@@ -62,12 +62,14 @@ function startBounce(container) {
62
62
  return { el: c, x: 10 + i * rand(14, 22), y: floor - rand(0, 15), vx: rand(0.6, 1.3), vy: -rand(2.5, 5), r: radii[i] };
63
63
  });
64
64
 
65
- let raf;
66
- function step() {
65
+ let raf, lastFrame = 0;
66
+ function step(now = performance.now()) {
67
+ const dt = lastFrame ? Math.min((now - lastFrame) / 16.67, 4) : 1;
68
+ lastFrame = now;
67
69
  balls.forEach(b => {
68
- b.vy += gravity;
69
- b.x += b.vx;
70
- b.y += b.vy;
70
+ b.vy += gravity * dt;
71
+ b.x += b.vx * dt;
72
+ b.y += b.vy * dt;
71
73
  if (b.y > floor) { b.y = floor; b.vy *= -restitution; }
72
74
  });
73
75
  for (let i = 0; i < balls.length; i++) {
@@ -440,16 +442,19 @@ export function addTerminal(id, name, themeId, commandId, projectId, muted, last
440
442
  fitRaf = requestAnimationFrame(() => { fitRaf = 0; doFit(); });
441
443
  });
442
444
  ro.observe(el);
443
- // Safety: if RO hasn't fired within 500ms, flush anyway to avoid unbounded queue.
444
- // If the element is hidden (background tab), force a reasonable default size so the PTY
445
- // doesn't stay at a tiny default and produce garbled output.
445
+ // Safety: if RO hasn't fired within 500ms, let visible terminals proceed.
446
+ // For hidden/unmeasured terminals, keep the PTY at a reasonable fallback size
447
+ // but do not flush queued output until a real measured fit happens; replaying
448
+ // buffered output into fake geometry is what leaves the rebuilt terminal messy
449
+ // after refresh/logout/login.
446
450
  setTimeout(() => {
447
451
  if (!fitted) {
448
- fitted = true;
449
452
  if (!el.offsetWidth) {
450
453
  term.resize(120, 30);
451
454
  send({ type: 'resize', id, cols: 120, rows: 30 });
455
+ return;
452
456
  }
457
+ fitted = true;
453
458
  for (const chunk of pending) term.write(chunk);
454
459
  pending = null;
455
460
  updatePreview(id);
@@ -781,6 +786,7 @@ export function startProjectRename(projectId) {
781
786
  // --- Project grouping ---
782
787
 
783
788
  const CHEVRON_SVG = `<svg class="w-3 h-3 transition-transform" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path d="M6 9l6 6 6-6"/></svg>`;
789
+ const PATH_SVG = `<svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7.5A1.5 1.5 0 0 1 4.5 6h4.379a1.5 1.5 0 0 1 1.06.44l1.122 1.12a1.5 1.5 0 0 0 1.06.44H19.5A1.5 1.5 0 0 1 21 9.5v8A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5v-10Z"/></svg>`;
784
790
 
785
791
  const PROJECT_COLORS = ['#3b82f6', '#8b5cf6', '#ec4899', '#f59e0b', '#10b981', '#ef4444', '#06b6d4', '#84cc16'];
786
792
 
@@ -817,6 +823,9 @@ export function regroupSessions() {
817
823
  <span class="w-2 h-2 rounded-full flex-shrink-0" style="background:${projectColor(proj)}"></span>
818
824
  <span class="project-name flex-1 text-[11px] font-semibold uppercase tracking-wider text-slate-500 truncate">${esc(proj.name)}</span>
819
825
  <span class="project-count text-[10px] text-slate-600">0</span>
826
+ <button class="project-path-btn opacity-0 group-hover:opacity-100 ${proj.path ? 'text-slate-600 hover:text-slate-300' : 'text-slate-700 cursor-default'} flex-shrink-0 transition-opacity p-0.5" title="${proj.path ? 'Open project folder' : 'Project path not set'}" ${proj.path ? '' : 'disabled'}>
827
+ ${PATH_SVG}
828
+ </button>
820
829
  <span class="project-plugin-actions"></span>
821
830
  <button class="project-menu-btn opacity-0 group-hover:opacity-100 text-slate-600 hover:text-slate-400 flex-shrink-0 transition-opacity p-0.5" title="Project menu">
822
831
  <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 20 20"><circle cx="10" cy="4" r="1.5" fill="currentColor"/><circle cx="10" cy="10" r="1.5" fill="currentColor"/><circle cx="10" cy="16" r="1.5" fill="currentColor"/></svg>
@@ -1 +1 @@
1
- *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--color-base:#020617;--color-surface:#0f172a;--color-raised:#1e293b;--color-muted:#334155;--color-border:#475569;--color-subtle:#64748b;--color-dim:#94a3b8;--color-soft:#cbd5e1;--color-text:#e2e8f0;--color-bright:#f8fafc;--color-overlay:rgba(0,0,0,.6);--color-shadow:rgba(0,0,0,.5);--color-dialog:#1e293b;--color-stats-bg:rgba(0,0,0,.95);--color-accent-subtle:rgba(59,130,246,.15);--color-rail:#1d1f1f;--color-rail-active:#2a323f;--color-sidebar:#161717;--color-sidebar-input:#0f1010;--color-sidebar-border:#2e2f2f;--color-chat-hover:#2e2f2f;--color-chat-active:#2e2f2f;--color-rail-badge-bg:#5cbd6d;--color-rail-badge-text:#0a0a0a}.light{--color-base:#edeef1;--color-surface:#f7f8fa;--color-raised:#fff;--color-muted:#e4e6ea;--color-border:#d1d5db;--color-subtle:#8b919a;--color-dim:#5f6672;--color-soft:#3d4450;--color-text:#1a1d24;--color-bright:#0c0e12;--color-overlay:rgba(0,0,0,.25);--color-shadow:rgba(0,0,0,.08);--color-dialog:#fff;--color-stats-bg:hsla(0,0%,100%,.92);--color-accent-subtle:rgba(59,130,246,.08);--color-rail:#fcfdfd;--color-rail-active:#eae9e7;--color-sidebar:#f9fafa;--color-sidebar-input:#fff;--color-sidebar-border:#e0deda;--color-chat-hover:#f6f5f5;--color-chat-active:#eff0f0;--color-rail-badge-bg:#51a868;--color-rail-badge-text:#fff}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.collapse{visibility:collapse}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-1{inset:.25rem}.-right-1{right:-.25rem}.-top-1{top:-.25rem}.bottom-0{bottom:0}.bottom-5{bottom:1.25rem}.left-2\.5{left:.625rem}.right-0{right:0}.right-3{right:.75rem}.right-5{right:1.25rem}.top-1\/2{top:50%}.top-2{top:.5rem}.z-10{z-index:10}.z-\[200\]{z-index:200}.z-\[250\]{z-index:250}.z-\[260\]{z-index:260}.z-\[300\]{z-index:300}.z-\[400\]{z-index:400}.z-\[500\]{z-index:500}.mx-4{margin-left:1rem;margin-right:1rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.-mt-2{margin-top:-.5rem}.-mt-px{margin-top:-1px}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.ml-0\.5{margin-left:.125rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-1\.5{margin-right:.375rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.\!hidden{display:none!important}.hidden{display:none}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[180px\]{height:180px}.h-\[18px\]{height:18px}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[160px\]{max-height:160px}.max-h-\[400px\]{max-height:400px}.max-h-\[460px\]{max-height:460px}.min-h-0{min-height:0}.min-h-\[200px\]{min-height:200px}.w-12{width:3rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-44{width:11rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-\[180px\]{width:180px}.w-\[18px\]{width:18px}.w-\[340px\]{width:340px}.w-\[354px\]{width:354px}.w-\[360px\]{width:360px}.w-\[420px\]{width:420px}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[160px\]{min-width:160px}.min-w-\[16px\]{min-width:16px}.min-w-\[220px\]{min-width:220px}.min-w-\[260px\]{min-width:260px}.min-w-\[354px\]{min-width:354px}.max-w-2xl{max-width:42rem}.max-w-full{max-width:100%}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.cursor-wait{cursor:wait}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-y{resize:vertical}.resize{resize:both}.list-disc{list-style-type:disc}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-px>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1px*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-blue-400{--tw-border-opacity:1;border-color:rgb(96 165 250/var(--tw-border-opacity,1))}.border-red-500\/30{border-color:rgba(239,68,68,.3)}.border-slate-600{--tw-border-opacity:1;border-color:rgb(71 85 105/var(--tw-border-opacity,1))}.border-slate-700{--tw-border-opacity:1;border-color:rgb(51 65 85/var(--tw-border-opacity,1))}.border-slate-700\/30{border-color:rgba(51,65,85,.3)}.border-slate-700\/40{border-color:rgba(51,65,85,.4)}.border-slate-700\/50{border-color:rgba(51,65,85,.5)}.border-slate-700\/60{border-color:rgba(51,65,85,.6)}.border-slate-900{--tw-border-opacity:1;border-color:rgb(15 23 42/var(--tw-border-opacity,1))}.border-transparent{border-color:transparent}.bg-amber-500\/10{background-color:rgba(245,158,11,.1)}.bg-black\/60{background-color:rgba(0,0,0,.6)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/15{background-color:rgba(59,130,246,.15)}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-emerald-600\/20{background-color:rgba(5,150,105,.2)}.bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.bg-red-600\/20{background-color:rgba(220,38,38,.2)}.bg-rose-500\/10{background-color:rgba(244,63,94,.1)}.bg-slate-700{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.bg-slate-700\/50{background-color:rgba(51,65,85,.5)}.bg-slate-700\/60{background-color:rgba(51,65,85,.6)}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity,1))}.bg-slate-800\/30{background-color:rgba(30,41,59,.3)}.bg-slate-800\/40{background-color:rgba(30,41,59,.4)}.bg-slate-800\/50{background-color:rgba(30,41,59,.5)}.bg-slate-800\/60{background-color:rgba(30,41,59,.6)}.bg-slate-800\/80{background-color:rgba(30,41,59,.8)}.bg-slate-800\/95{background-color:rgba(30,41,59,.95)}.bg-slate-900{--tw-bg-opacity:1;background-color:rgb(15 23 42/var(--tw-bg-opacity,1))}.bg-slate-900\/70{background-color:rgba(15,23,42,.7)}.bg-slate-950{--tw-bg-opacity:1;background-color:rgb(2 6 23/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-\[3px\]{padding:3px}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-\[5px\]{padding-top:5px;padding-bottom:5px}.py-\[7px\]{padding-top:7px;padding-bottom:7px}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pb-2\.5{padding-bottom:.625rem}.pb-3{padding-bottom:.75rem}.pb-3\.5{padding-bottom:.875rem}.pl-2{padding-left:.5rem}.pl-4{padding-left:1rem}.pl-9{padding-left:2.25rem}.pr-3{padding-right:.75rem}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.pt-3\.5{padding-top:.875rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-\[1\.45\]{line-height:1.45}.leading-\[1\.4\]{line-height:1.4}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-amber-400{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-amber-400\/80{color:rgba(251,191,36,.8)}.text-amber-500{--tw-text-opacity:1;color:rgb(245 158 11/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-emerald-400{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-emerald-400\/80{color:rgba(52,211,153,.8)}.text-emerald-500{--tw-text-opacity:1;color:rgb(16 185 129/var(--tw-text-opacity,1))}.text-emerald-500\/70{color:rgba(16,185,129,.7)}.text-indigo-400{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-rose-400{--tw-text-opacity:1;color:rgb(251 113 133/var(--tw-text-opacity,1))}.text-rose-400\/80{color:rgba(251,113,133,.8)}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-yellow-500{--tw-text-opacity:1;color:rgb(234 179 8/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.placeholder-slate-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(100 116 139/var(--tw-placeholder-opacity,1))}.placeholder-slate-500::placeholder{--tw-placeholder-opacity:1;color:rgb(100 116 139/var(--tw-placeholder-opacity,1))}.placeholder-slate-600::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity,1))}.placeholder-slate-600::placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity,1))}.accent-blue-500{accent-color:#3b82f6}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.shadow-black\/40{--tw-shadow-color:rgba(0,0,0,.4);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/50{--tw-shadow-color:rgba(0,0,0,.5);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/60{--tw-shadow-color:rgba(0,0,0,.6);--tw-shadow:var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-white\/40{--tw-ring-color:hsla(0,0%,100%,.4)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.backdrop-blur-sm,.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.bg-slate-950{background-color:var(--color-base)!important}.bg-slate-900{background-color:var(--color-surface)!important}.bg-slate-800{background-color:var(--color-raised)!important}.bg-slate-700{background-color:var(--color-muted)!important}.bg-slate-800\/50{background-color:color-mix(in srgb,var(--color-raised) 50%,transparent)!important}.bg-slate-800\/30{background-color:color-mix(in srgb,var(--color-raised) 30%,transparent)!important}.bg-slate-800\/60{background-color:color-mix(in srgb,var(--color-raised) 60%,transparent)!important}.bg-slate-800\/80{background-color:color-mix(in srgb,var(--color-raised) 80%,transparent)!important}.bg-slate-900\/70{background-color:color-mix(in srgb,var(--color-surface) 70%,transparent)!important}.bg-slate-800\/95{background-color:color-mix(in srgb,var(--color-raised) 95%,transparent)!important}.bg-slate-700\/50{background-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.bg-slate-700\/60{background-color:color-mix(in srgb,var(--color-muted) 60%,transparent)!important}.hover\:bg-slate-700:hover{background-color:var(--color-muted)!important}.hover\:bg-slate-800:hover{background-color:var(--color-raised)!important}.hover\:bg-slate-800\/50:hover{background-color:color-mix(in srgb,var(--color-raised) 50%,transparent)!important}.hover\:bg-slate-800\/30:hover{background-color:color-mix(in srgb,var(--color-raised) 30%,transparent)!important}.hover\:bg-slate-700\/50:hover{background-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.hover\:bg-slate-700\/70:hover{background-color:color-mix(in srgb,var(--color-muted) 70%,transparent)!important}.text-slate-200{color:var(--color-text)!important}.text-slate-300{color:var(--color-soft)!important}.text-slate-400{color:var(--color-dim)!important}.text-slate-500{color:var(--color-subtle)!important}.text-slate-600{color:var(--color-border)!important}.hover\:text-slate-200:hover{color:var(--color-text)!important}.hover\:text-slate-300:hover{color:var(--color-soft)!important}.hover\:text-slate-400:hover{color:var(--color-dim)!important}.border-slate-600{border-color:var(--color-border)!important}.border-slate-700{border-color:var(--color-muted)!important}.border-slate-700\/50{border-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.border-slate-700\/40{border-color:color-mix(in srgb,var(--color-muted) 40%,transparent)!important}.border-slate-700\/60{border-color:color-mix(in srgb,var(--color-muted) 60%,transparent)!important}.border-slate-600\/60{border-color:color-mix(in srgb,var(--color-border) 60%,transparent)!important}.hover\:border-slate-500:hover{border-color:var(--color-subtle)!important}.focus\:border-slate-600\/60:focus{border-color:color-mix(in srgb,var(--color-border) 60%,transparent)!important}.focus\:bg-slate-800\/80:focus{background-color:color-mix(in srgb,var(--color-raised) 80%,transparent)!important}.placeholder-slate-500::-moz-placeholder{color:var(--color-subtle)!important}.placeholder-slate-500::placeholder{color:var(--color-subtle)!important}.placeholder-slate-600::-moz-placeholder{color:var(--color-border)!important}.placeholder-slate-600::placeholder{color:var(--color-border)!important}.ring-slate-500{--tw-ring-color:var(--color-subtle)!important}.bg-black\/60{background-color:var(--color-overlay)!important}.shadow-black\/40,.shadow-black\/50,.shadow-black\/60{--tw-shadow-color:var(--color-shadow)!important}.disabled\:bg-slate-600:disabled{background-color:var(--color-border)!important}.disabled\:text-slate-400:disabled{color:var(--color-dim)!important}:root{--color-preview:#a2a2a2;--color-time:#7c7d7d;--color-time-recent:#5cbd6d;--color-dormant:#555;--color-proj-meta:#7c7d7d;--color-search-bg:#2e2f2f;--color-search-text:#acacac;--color-session-hover:hsla(0,0%,100%,.04);--color-header-icon:#cbd5e1;--color-rail-icon:#a5a6a6}.light{--color-preview:#626262;--color-time:#666;--color-time-recent:#51a868;--color-dormant:#aaa;--color-proj-meta:#666;--color-search-bg:#f6f5f5;--color-search-text:#626262;--color-session-hover:rgba(0,0,0,.04);--color-header-icon:#3d4450;--color-rail-icon:#636261}.session-preview{color:var(--color-preview)!important}.session-time{color:var(--color-time)!important}.session-time.recent{color:var(--color-time-recent)!important}.session-status.dormant{color:var(--color-dormant)!important}.group[data-id]:hover,.pill-row:hover,.resumable-row:hover{background-color:var(--color-session-hover)!important}.project-count,.project-menu-btn{color:var(--color-proj-meta)!important}#search-input{background-color:var(--color-search-bg)!important;color:var(--color-search-text)!important}#search-input::-moz-placeholder{color:var(--color-search-text)!important;opacity:.7}#search-input::placeholder{color:var(--color-search-text)!important;opacity:.7}.relative:has(#search-input)>svg{color:var(--color-search-text)!important}.rail-btn:not(.text-slate-200){color:var(--color-rail-icon)!important}.rail-btn.bg-slate-800{background-color:var(--color-rail-active)!important}.icon-btn{color:var(--color-header-icon)!important;border-color:var(--color-border)!important;font-weight:700}.icon-btn svg{stroke-width:2}:root{--color-separator:#2e2f2f}.light{--color-separator:#d8d3cd}#nav-rail{background-color:var(--color-rail)!important}#sidebar{background-color:var(--color-sidebar)!important;border-right-color:var(--color-separator)!important}#sidebar input[type=text],#sidebar select{background-color:var(--color-sidebar-input)!important;border-color:var(--color-sidebar-border)!important}.group:hover{background-color:var(--color-chat-hover)!important}.group.active-session{background-color:var(--color-chat-active)!important}.theme-toggle{position:relative;width:36px;height:36px}.theme-toggle svg{position:absolute;inset:0;margin:auto;transition:opacity .3s ease,transform .3s ease}.theme-toggle .icon-sun{opacity:0;transform:rotate(-90deg) scale(.5)}.light .theme-toggle .icon-sun,.theme-toggle .icon-moon{opacity:1;transform:rotate(0) scale(1)}.light .theme-toggle .icon-moon{opacity:0;transform:rotate(90deg) scale(.5)}html{transition:color .3s ease,background-color .3s ease}.term-wrap{visibility:hidden;position:absolute;overflow:hidden;top:4px;left:4px;right:4px;bottom:0}.term-wrap.active{visibility:visible}.term-wrap .xterm{height:100%}.save-indicator{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;border:1px solid var(--color-search-text);margin-right:4px;opacity:.35;transition:opacity .4s ease}.save-indicator.saved{opacity:.5}.save-indicator .save-tick{color:var(--color-time-recent);display:block}.save-indicator .save-spin{display:none;color:var(--color-dim);animation:save-rotate 1.5s cubic-bezier(.4,0,.2,1) infinite}.save-indicator.saving .save-tick{display:none}.save-indicator.saving .save-spin{display:block}.save-indicator.saving{opacity:.5}@keyframes save-rotate{to{transform:rotate(1turn)}}.tmx-toast{box-shadow:0 25px 50px -12px rgba(0,0,0,.5)}.light .tmx-toast{box-shadow:0 25px 50px -12px rgba(0,0,0,.25),0 0 0 1px rgba(0,0,0,.05)}.drop-highlight{border-radius:.25rem;background-color:rgba(59,130,246,.1);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(59,130,246,.3)}.project-drop-line{height:2px;margin:.125rem .5rem;border-radius:9999px;--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.plugin-chevron.collapsed,.project-chevron.collapsed svg{transform:rotate(-90deg)}.tmx-scroll{scrollbar-width:thin;scrollbar-color:transparent transparent}.tmx-scroll::-webkit-scrollbar{width:10px}.tmx-scroll::-webkit-scrollbar-track{background:transparent}.tmx-scroll::-webkit-scrollbar-thumb{background:transparent;border:2px solid transparent;border-radius:9999px;-webkit-transition:background-color .2s ease,border-color .2s ease;transition:background-color .2s ease,border-color .2s ease}.tmx-scroll.is-scrolling,.tmx-scroll:hover{scrollbar-color:color-mix(in srgb,var(--color-muted) 78%,transparent) color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-track,.tmx-scroll:hover::-webkit-scrollbar-track{background:color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-thumb,.tmx-scroll:hover::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--color-muted) 78%,transparent);border-color:color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-thumb:hover,.tmx-scroll:hover::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--color-subtle) 85%,transparent)}.prompt-autocomplete{position:fixed;width:340px;background:var(--color-raised);border:1px solid var(--color-muted);border-radius:10px;box-shadow:0 20px 40px -8px rgba(0,0,0,.5);z-index:100;display:flex;flex-direction:column;overflow:hidden;animation:pa-in .15s ease}@keyframes pa-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.pa-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid color-mix(in srgb,var(--color-muted) 50%,transparent)}.pa-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--color-subtle)}.pa-query{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--color-dim);background:color-mix(in srgb,var(--color-muted) 40%,transparent);padding:2px 6px;border-radius:4px}.pa-list{overflow-y:auto;padding:4px;max-height:184px}.pa-item{padding:8px 10px;border-radius:6px;cursor:pointer;transition:background-color .1s}.pa-item:hover,.pa-selected{background:color-mix(in srgb,var(--color-muted) 40%,transparent)}.pa-name{font-size:13px;font-weight:500;color:var(--color-text)}.pa-name,.pa-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pa-text{font-size:11px;color:var(--color-subtle);margin-top:2px}.pa-item mark{background:rgba(59,130,246,.25);color:inherit;border-radius:2px;padding:0 1px}.pa-footer{display:flex;gap:12px;justify-content:center;padding:6px 12px;border-top:1px solid color-mix(in srgb,var(--color-muted) 50%,transparent);font-size:10px;color:var(--color-subtle)}.pa-footer kbd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;padding:1px 4px;border-radius:3px;background:color-mix(in srgb,var(--color-muted) 50%,transparent);color:var(--color-dim)}.pa-empty{padding:20px 12px;text-align:center;font-size:13px;color:var(--color-subtle)}.pa-hint{padding:0 12px 12px;text-align:center;font-size:11px;color:var(--color-border)}.pa-hint kbd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:color-mix(in srgb,var(--color-muted) 50%,transparent);padding:1px 4px;border-radius:3px}.empty\:hidden:empty{display:none}.hover\:scale-125:hover{--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-slate-500:hover{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity,1))}.hover\:bg-amber-500\/20:hover{background-color:rgba(245,158,11,.2)}.hover\:bg-blue-500:hover{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.hover\:bg-blue-500\/20:hover{background-color:rgba(59,130,246,.2)}.hover\:bg-red-500:hover{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.hover\:bg-rose-500\/20:hover{background-color:rgba(244,63,94,.2)}.hover\:bg-slate-700:hover{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.hover\:bg-slate-700\/50:hover{background-color:rgba(51,65,85,.5)}.hover\:bg-slate-700\/60:hover{background-color:rgba(51,65,85,.6)}.hover\:bg-slate-700\/70:hover{background-color:rgba(51,65,85,.7)}.hover\:bg-slate-800\/30:hover{background-color:rgba(30,41,59,.3)}.hover\:bg-slate-800\/40:hover{background-color:rgba(30,41,59,.4)}.hover\:bg-slate-800\/50:hover{background-color:rgba(30,41,59,.5)}.hover\:text-amber-300:hover{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.hover\:text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.hover\:text-emerald-300:hover{--tw-text-opacity:1;color:rgb(110 231 183/var(--tw-text-opacity,1))}.hover\:text-emerald-400:hover{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.hover\:text-indigo-400:hover{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-red-400:hover{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.hover\:text-rose-300:hover{--tw-text-opacity:1;color:rgb(253 164 175/var(--tw-text-opacity,1))}.hover\:text-slate-200:hover{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.hover\:text-slate-300:hover{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.hover\:text-slate-400:hover{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.hover\:ring-2:hover{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.hover\:ring-slate-500:hover{--tw-ring-opacity:1;--tw-ring-color:rgb(100 116 139/var(--tw-ring-opacity,1))}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.focus\:border-slate-600\/60:focus{border-color:rgba(71,85,105,.6)}.focus\:bg-slate-800\/80:focus{background-color:rgba(30,41,59,.8)}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-500\/30:focus{--tw-ring-color:rgba(59,130,246,.3)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-slate-600:disabled{--tw-bg-opacity:1;background-color:rgb(71 85 105/var(--tw-bg-opacity,1))}.disabled\:text-slate-400:disabled{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.group:hover .group-hover\:opacity-100{opacity:1}
1
+ *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--color-base:#020617;--color-surface:#0f172a;--color-raised:#1e293b;--color-muted:#334155;--color-border:#475569;--color-subtle:#64748b;--color-dim:#94a3b8;--color-soft:#cbd5e1;--color-text:#e2e8f0;--color-bright:#f8fafc;--color-overlay:rgba(0,0,0,.6);--color-shadow:rgba(0,0,0,.5);--color-dialog:#1e293b;--color-stats-bg:rgba(0,0,0,.95);--color-accent-subtle:rgba(59,130,246,.15);--color-rail:#1d1f1f;--color-rail-active:#2a323f;--color-sidebar:#161717;--color-sidebar-input:#0f1010;--color-sidebar-border:#2e2f2f;--color-chat-hover:#2e2f2f;--color-chat-active:#2e2f2f;--color-rail-badge-bg:#5cbd6d;--color-rail-badge-text:#0a0a0a}.light{--color-base:#edeef1;--color-surface:#f7f8fa;--color-raised:#fff;--color-muted:#e4e6ea;--color-border:#d1d5db;--color-subtle:#8b919a;--color-dim:#5f6672;--color-soft:#3d4450;--color-text:#1a1d24;--color-bright:#0c0e12;--color-overlay:rgba(0,0,0,.25);--color-shadow:rgba(0,0,0,.08);--color-dialog:#fff;--color-stats-bg:hsla(0,0%,100%,.92);--color-accent-subtle:rgba(59,130,246,.08);--color-rail:#fcfdfd;--color-rail-active:#eae9e7;--color-sidebar:#f9fafa;--color-sidebar-input:#fff;--color-sidebar-border:#e0deda;--color-chat-hover:#f6f5f5;--color-chat-active:#eff0f0;--color-rail-badge-bg:#51a868;--color-rail-badge-text:#fff}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.visible{visibility:visible}.collapse{visibility:collapse}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-1{inset:.25rem}.-right-1{right:-.25rem}.-top-1{top:-.25rem}.bottom-0{bottom:0}.bottom-5{bottom:1.25rem}.left-2\.5{left:.625rem}.right-0{right:0}.right-3{right:.75rem}.right-5{right:1.25rem}.top-1\/2{top:50%}.top-2{top:.5rem}.z-10{z-index:10}.z-\[200\]{z-index:200}.z-\[250\]{z-index:250}.z-\[260\]{z-index:260}.z-\[300\]{z-index:300}.z-\[400\]{z-index:400}.z-\[500\]{z-index:500}.mx-4{margin-left:1rem;margin-right:1rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.-mt-2{margin-top:-.5rem}.-mt-px{margin-top:-1px}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-5{margin-bottom:1.25rem}.ml-0\.5{margin-left:.125rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-6{margin-left:1.5rem}.ml-auto{margin-left:auto}.mr-1\.5{margin-right:.375rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.\!hidden{display:none!important}.hidden{display:none}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[180px\]{height:180px}.h-\[18px\]{height:18px}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[160px\]{max-height:160px}.max-h-\[400px\]{max-height:400px}.max-h-\[460px\]{max-height:460px}.min-h-0{min-height:0}.min-h-\[200px\]{min-height:200px}.w-12{width:3rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-44{width:11rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-\[180px\]{width:180px}.w-\[18px\]{width:18px}.w-\[340px\]{width:340px}.w-\[354px\]{width:354px}.w-\[360px\]{width:360px}.w-\[420px\]{width:420px}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[160px\]{min-width:160px}.min-w-\[16px\]{min-width:16px}.min-w-\[220px\]{min-width:220px}.min-w-\[260px\]{min-width:260px}.min-w-\[354px\]{min-width:354px}.max-w-2xl{max-width:42rem}.max-w-full{max-width:100%}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.scale-110{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.cursor-wait{cursor:wait}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-y{resize:vertical}.resize{resize:both}.list-disc{list-style-type:disc}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-px>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1px*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre{white-space:pre}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-blue-400{--tw-border-opacity:1;border-color:rgb(96 165 250/var(--tw-border-opacity,1))}.border-red-500\/30{border-color:rgba(239,68,68,.3)}.border-slate-600{--tw-border-opacity:1;border-color:rgb(71 85 105/var(--tw-border-opacity,1))}.border-slate-700{--tw-border-opacity:1;border-color:rgb(51 65 85/var(--tw-border-opacity,1))}.border-slate-700\/30{border-color:rgba(51,65,85,.3)}.border-slate-700\/40{border-color:rgba(51,65,85,.4)}.border-slate-700\/50{border-color:rgba(51,65,85,.5)}.border-slate-700\/60{border-color:rgba(51,65,85,.6)}.border-slate-900{--tw-border-opacity:1;border-color:rgb(15 23 42/var(--tw-border-opacity,1))}.border-transparent{border-color:transparent}.bg-amber-500\/10{background-color:rgba(245,158,11,.1)}.bg-black\/60{background-color:rgba(0,0,0,.6)}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-blue-500\/15{background-color:rgba(59,130,246,.15)}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-emerald-600\/20{background-color:rgba(5,150,105,.2)}.bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.bg-red-600\/20{background-color:rgba(220,38,38,.2)}.bg-rose-500\/10{background-color:rgba(244,63,94,.1)}.bg-slate-700{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.bg-slate-700\/50{background-color:rgba(51,65,85,.5)}.bg-slate-700\/60{background-color:rgba(51,65,85,.6)}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity,1))}.bg-slate-800\/30{background-color:rgba(30,41,59,.3)}.bg-slate-800\/40{background-color:rgba(30,41,59,.4)}.bg-slate-800\/50{background-color:rgba(30,41,59,.5)}.bg-slate-800\/60{background-color:rgba(30,41,59,.6)}.bg-slate-800\/80{background-color:rgba(30,41,59,.8)}.bg-slate-800\/95{background-color:rgba(30,41,59,.95)}.bg-slate-900{--tw-bg-opacity:1;background-color:rgb(15 23 42/var(--tw-bg-opacity,1))}.bg-slate-900\/70{background-color:rgba(15,23,42,.7)}.bg-slate-950{--tw-bg-opacity:1;background-color:rgb(2 6 23/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.p-\[3px\]{padding:3px}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-\[5px\]{padding-top:5px;padding-bottom:5px}.py-\[7px\]{padding-top:7px;padding-bottom:7px}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pb-2\.5{padding-bottom:.625rem}.pb-3{padding-bottom:.75rem}.pb-3\.5{padding-bottom:.875rem}.pl-2{padding-left:.5rem}.pl-4{padding-left:1rem}.pl-9{padding-left:2.25rem}.pr-3{padding-right:.75rem}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.pt-3\.5{padding-top:.875rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-\[1\.45\]{line-height:1.45}.leading-\[1\.4\]{line-height:1.4}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-amber-400{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-amber-400\/80{color:rgba(251,191,36,.8)}.text-amber-500{--tw-text-opacity:1;color:rgb(245 158 11/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.text-emerald-400{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-emerald-400\/80{color:rgba(52,211,153,.8)}.text-emerald-500{--tw-text-opacity:1;color:rgb(16 185 129/var(--tw-text-opacity,1))}.text-emerald-500\/70{color:rgba(16,185,129,.7)}.text-indigo-400{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity,1))}.text-red-400{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.text-rose-400{--tw-text-opacity:1;color:rgb(251 113 133/var(--tw-text-opacity,1))}.text-rose-400\/80{color:rgba(251,113,133,.8)}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-yellow-500{--tw-text-opacity:1;color:rgb(234 179 8/var(--tw-text-opacity,1))}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.placeholder-slate-500::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(100 116 139/var(--tw-placeholder-opacity,1))}.placeholder-slate-500::placeholder{--tw-placeholder-opacity:1;color:rgb(100 116 139/var(--tw-placeholder-opacity,1))}.placeholder-slate-600::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity,1))}.placeholder-slate-600::placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity,1))}.accent-blue-500{accent-color:#3b82f6}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.shadow-black\/40{--tw-shadow-color:rgba(0,0,0,.4);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/50{--tw-shadow-color:rgba(0,0,0,.5);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/60{--tw-shadow-color:rgba(0,0,0,.6);--tw-shadow:var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-white\/40{--tw-ring-color:hsla(0,0%,100%,.4)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.backdrop-blur-sm,.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.bg-slate-950{background-color:var(--color-base)!important}.bg-slate-900{background-color:var(--color-surface)!important}.bg-slate-800{background-color:var(--color-raised)!important}.bg-slate-700{background-color:var(--color-muted)!important}.bg-slate-800\/50{background-color:color-mix(in srgb,var(--color-raised) 50%,transparent)!important}.bg-slate-800\/30{background-color:color-mix(in srgb,var(--color-raised) 30%,transparent)!important}.bg-slate-800\/60{background-color:color-mix(in srgb,var(--color-raised) 60%,transparent)!important}.bg-slate-800\/80{background-color:color-mix(in srgb,var(--color-raised) 80%,transparent)!important}.bg-slate-900\/70{background-color:color-mix(in srgb,var(--color-surface) 70%,transparent)!important}.bg-slate-800\/95{background-color:color-mix(in srgb,var(--color-raised) 95%,transparent)!important}.bg-slate-700\/50{background-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.bg-slate-700\/60{background-color:color-mix(in srgb,var(--color-muted) 60%,transparent)!important}.hover\:bg-slate-700:hover{background-color:var(--color-muted)!important}.hover\:bg-slate-800:hover{background-color:var(--color-raised)!important}.hover\:bg-slate-800\/50:hover{background-color:color-mix(in srgb,var(--color-raised) 50%,transparent)!important}.hover\:bg-slate-800\/30:hover{background-color:color-mix(in srgb,var(--color-raised) 30%,transparent)!important}.hover\:bg-slate-700\/50:hover{background-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.hover\:bg-slate-700\/70:hover{background-color:color-mix(in srgb,var(--color-muted) 70%,transparent)!important}.text-slate-200{color:var(--color-text)!important}.text-slate-300{color:var(--color-soft)!important}.text-slate-400{color:var(--color-dim)!important}.text-slate-500{color:var(--color-subtle)!important}.text-slate-600{color:var(--color-border)!important}.hover\:text-slate-200:hover{color:var(--color-text)!important}.hover\:text-slate-300:hover{color:var(--color-soft)!important}.hover\:text-slate-400:hover{color:var(--color-dim)!important}.border-slate-600{border-color:var(--color-border)!important}.border-slate-700{border-color:var(--color-muted)!important}.border-slate-700\/50{border-color:color-mix(in srgb,var(--color-muted) 50%,transparent)!important}.border-slate-700\/40{border-color:color-mix(in srgb,var(--color-muted) 40%,transparent)!important}.border-slate-700\/60{border-color:color-mix(in srgb,var(--color-muted) 60%,transparent)!important}.border-slate-600\/60{border-color:color-mix(in srgb,var(--color-border) 60%,transparent)!important}.hover\:border-slate-500:hover{border-color:var(--color-subtle)!important}.focus\:border-slate-600\/60:focus{border-color:color-mix(in srgb,var(--color-border) 60%,transparent)!important}.focus\:bg-slate-800\/80:focus{background-color:color-mix(in srgb,var(--color-raised) 80%,transparent)!important}.placeholder-slate-500::-moz-placeholder{color:var(--color-subtle)!important}.placeholder-slate-500::placeholder{color:var(--color-subtle)!important}.placeholder-slate-600::-moz-placeholder{color:var(--color-border)!important}.placeholder-slate-600::placeholder{color:var(--color-border)!important}.ring-slate-500{--tw-ring-color:var(--color-subtle)!important}.bg-black\/60{background-color:var(--color-overlay)!important}.shadow-black\/40,.shadow-black\/50,.shadow-black\/60{--tw-shadow-color:var(--color-shadow)!important}.disabled\:bg-slate-600:disabled{background-color:var(--color-border)!important}.disabled\:text-slate-400:disabled{color:var(--color-dim)!important}:root{--color-preview:#a2a2a2;--color-time:#7c7d7d;--color-time-recent:#5cbd6d;--color-dormant:#555;--color-proj-meta:#7c7d7d;--color-search-bg:#2e2f2f;--color-search-text:#acacac;--color-session-hover:hsla(0,0%,100%,.04);--color-header-icon:#cbd5e1;--color-rail-icon:#a5a6a6}.light{--color-preview:#626262;--color-time:#666;--color-time-recent:#51a868;--color-dormant:#aaa;--color-proj-meta:#666;--color-search-bg:#f6f5f5;--color-search-text:#626262;--color-session-hover:rgba(0,0,0,.04);--color-header-icon:#3d4450;--color-rail-icon:#636261}.session-preview{color:var(--color-preview)!important}.session-time{color:var(--color-time)!important}.session-time.recent{color:var(--color-time-recent)!important}.session-status.dormant{color:var(--color-dormant)!important}.group[data-id]:hover,.pill-row:hover,.resumable-row:hover{background-color:var(--color-session-hover)!important}.project-count,.project-menu-btn{color:var(--color-proj-meta)!important}#search-input{background-color:var(--color-search-bg)!important;color:var(--color-search-text)!important}#search-input::-moz-placeholder{color:var(--color-search-text)!important;opacity:.7}#search-input::placeholder{color:var(--color-search-text)!important;opacity:.7}.relative:has(#search-input)>svg{color:var(--color-search-text)!important}.rail-btn:not(.text-slate-200){color:var(--color-rail-icon)!important}.rail-btn.bg-slate-800{background-color:var(--color-rail-active)!important}.icon-btn{color:var(--color-header-icon)!important;border-color:var(--color-border)!important;font-weight:700}.icon-btn svg{stroke-width:2}:root{--color-separator:#2e2f2f}.light{--color-separator:#d8d3cd}#nav-rail{background-color:var(--color-rail)!important}#sidebar{background-color:var(--color-sidebar)!important;border-right-color:var(--color-separator)!important}#sidebar input[type=text],#sidebar select{background-color:var(--color-sidebar-input)!important;border-color:var(--color-sidebar-border)!important}.group:hover{background-color:var(--color-chat-hover)!important}.group.active-session{background-color:var(--color-chat-active)!important}.theme-toggle{position:relative;width:36px;height:36px}.theme-toggle svg{position:absolute;inset:0;margin:auto;transition:opacity .3s ease,transform .3s ease}.theme-toggle .icon-sun{opacity:0;transform:rotate(-90deg) scale(.5)}.light .theme-toggle .icon-sun,.theme-toggle .icon-moon{opacity:1;transform:rotate(0) scale(1)}.light .theme-toggle .icon-moon{opacity:0;transform:rotate(90deg) scale(.5)}html{transition:color .3s ease,background-color .3s ease}.term-wrap{visibility:hidden;position:absolute;overflow:hidden;top:4px;left:4px;right:4px;bottom:0}.term-wrap.active{visibility:visible}.term-wrap .xterm{height:100%}.save-indicator{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;border:1px solid var(--color-search-text);margin-right:4px;opacity:.35;transition:opacity .4s ease}.save-indicator.saved{opacity:.5}.save-indicator .save-tick{color:var(--color-time-recent);display:block}.save-indicator .save-spin{display:none;color:var(--color-dim);animation:save-rotate 1.5s cubic-bezier(.4,0,.2,1) infinite}.save-indicator.saving .save-tick{display:none}.save-indicator.saving .save-spin{display:block}.save-indicator.saving{opacity:.5}@keyframes save-rotate{to{transform:rotate(1turn)}}.tmx-toast{box-shadow:0 25px 50px -12px rgba(0,0,0,.5)}.light .tmx-toast{box-shadow:0 25px 50px -12px rgba(0,0,0,.25),0 0 0 1px rgba(0,0,0,.05)}.drop-highlight{border-radius:.25rem;background-color:rgba(59,130,246,.1);--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(59,130,246,.3)}.project-drop-line{height:2px;margin:.125rem .5rem;border-radius:9999px;--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.plugin-chevron.collapsed,.project-chevron.collapsed svg{transform:rotate(-90deg)}.tmx-scroll{scrollbar-width:thin;scrollbar-color:transparent transparent}.tmx-scroll::-webkit-scrollbar{width:10px}.tmx-scroll::-webkit-scrollbar-track{background:transparent}.tmx-scroll::-webkit-scrollbar-thumb{background:transparent;border:2px solid transparent;border-radius:9999px;-webkit-transition:background-color .2s ease,border-color .2s ease;transition:background-color .2s ease,border-color .2s ease}.tmx-scroll.is-scrolling,.tmx-scroll:hover{scrollbar-color:color-mix(in srgb,var(--color-muted) 78%,transparent) color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-track,.tmx-scroll:hover::-webkit-scrollbar-track{background:color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-thumb,.tmx-scroll:hover::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--color-muted) 78%,transparent);border-color:color-mix(in srgb,var(--color-sidebar) 70%,transparent)}.tmx-scroll.is-scrolling::-webkit-scrollbar-thumb:hover,.tmx-scroll:hover::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--color-subtle) 85%,transparent)}.prompt-autocomplete{position:fixed;width:340px;background:var(--color-raised);border:1px solid var(--color-muted);border-radius:10px;box-shadow:0 20px 40px -8px rgba(0,0,0,.5);z-index:100;display:flex;flex-direction:column;overflow:hidden;animation:pa-in .15s ease}@keyframes pa-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.pa-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-bottom:1px solid color-mix(in srgb,var(--color-muted) 50%,transparent)}.pa-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--color-subtle)}.pa-query{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--color-dim);background:color-mix(in srgb,var(--color-muted) 40%,transparent);padding:2px 6px;border-radius:4px}.pa-list{overflow-y:auto;padding:4px;max-height:184px}.pa-item{padding:8px 10px;border-radius:6px;cursor:pointer;transition:background-color .1s}.pa-item:hover,.pa-selected{background:color-mix(in srgb,var(--color-muted) 40%,transparent)}.pa-name{font-size:13px;font-weight:500;color:var(--color-text)}.pa-name,.pa-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pa-text{font-size:11px;color:var(--color-subtle);margin-top:2px}.pa-item mark{background:rgba(59,130,246,.25);color:inherit;border-radius:2px;padding:0 1px}.pa-footer{display:flex;gap:12px;justify-content:center;padding:6px 12px;border-top:1px solid color-mix(in srgb,var(--color-muted) 50%,transparent);font-size:10px;color:var(--color-subtle)}.pa-footer kbd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;padding:1px 4px;border-radius:3px;background:color-mix(in srgb,var(--color-muted) 50%,transparent);color:var(--color-dim)}.pa-empty{padding:20px 12px;text-align:center;font-size:13px;color:var(--color-subtle)}.pa-hint{padding:0 12px 12px;text-align:center;font-size:11px;color:var(--color-border)}.pa-hint kbd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:color-mix(in srgb,var(--color-muted) 50%,transparent);padding:1px 4px;border-radius:3px}.empty\:hidden:empty{display:none}.hover\:scale-125:hover{--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-slate-500:hover{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity,1))}.hover\:bg-amber-500\/20:hover{background-color:rgba(245,158,11,.2)}.hover\:bg-blue-500:hover{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.hover\:bg-blue-500\/20:hover{background-color:rgba(59,130,246,.2)}.hover\:bg-red-500:hover{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.hover\:bg-rose-500\/20:hover{background-color:rgba(244,63,94,.2)}.hover\:bg-slate-700:hover{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.hover\:bg-slate-700\/50:hover{background-color:rgba(51,65,85,.5)}.hover\:bg-slate-700\/60:hover{background-color:rgba(51,65,85,.6)}.hover\:bg-slate-700\/70:hover{background-color:rgba(51,65,85,.7)}.hover\:bg-slate-800\/30:hover{background-color:rgba(30,41,59,.3)}.hover\:bg-slate-800\/40:hover{background-color:rgba(30,41,59,.4)}.hover\:bg-slate-800\/50:hover{background-color:rgba(30,41,59,.5)}.hover\:text-amber-300:hover{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.hover\:text-blue-300:hover{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.hover\:text-emerald-300:hover{--tw-text-opacity:1;color:rgb(110 231 183/var(--tw-text-opacity,1))}.hover\:text-emerald-400:hover{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.hover\:text-indigo-400:hover{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity,1))}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-red-400:hover{--tw-text-opacity:1;color:rgb(248 113 113/var(--tw-text-opacity,1))}.hover\:text-rose-300:hover{--tw-text-opacity:1;color:rgb(253 164 175/var(--tw-text-opacity,1))}.hover\:text-slate-200:hover{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.hover\:text-slate-300:hover{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.hover\:text-slate-400:hover{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.hover\:ring-2:hover{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.hover\:ring-slate-500:hover{--tw-ring-opacity:1;--tw-ring-color:rgb(100 116 139/var(--tw-ring-opacity,1))}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.focus\:border-slate-600\/60:focus{border-color:rgba(71,85,105,.6)}.focus\:bg-slate-800\/80:focus{background-color:rgba(30,41,59,.8)}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-500\/30:focus{--tw-ring-color:rgba(59,130,246,.3)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-slate-600:disabled{--tw-bg-opacity:1;background-color:rgb(71 85 105/var(--tw-bg-opacity,1))}.disabled\:text-slate-400:disabled{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.group:hover .group-hover\:opacity-100{opacity:1}
package/sessions.js CHANGED
@@ -447,9 +447,15 @@ function sendBuffers(ws) {
447
447
  for (const [id, s] of sessions) {
448
448
  if (['claude-code', 'codex', 'gemini-cli', 'opencode'].includes(s.presetId) && !s.working) {
449
449
  const text = transcript.getReplayText(id, s.presetId);
450
- if (text) { ws.send(JSON.stringify({ type: 'session.history', id, text })); continue; }
450
+ if (text) {
451
+ ws.send(JSON.stringify({ type: 'session.history', id, text, replay: true }));
452
+ continue;
453
+ }
454
+ }
455
+ if (s.chunks.length) {
456
+ const data = s.chunks.join('');
457
+ ws.send(JSON.stringify({ type: 'output', id, data, replay: true }));
451
458
  }
452
- if (s.chunks.length) ws.send(JSON.stringify({ type: 'output', id, data: s.chunks.join('') }));
453
459
  }
454
460
  }
455
461
 
@@ -0,0 +1,48 @@
1
+ # Awesome Lists — Submission Log
2
+
3
+ ## Merged
4
+
5
+ | Repo | Stars | Section | Link | Date |
6
+ |------|-------|---------|------|------|
7
+ | Piebald-AI/awesome-gemini-cli | 387 | Agent Orchestration & CLI Tools | [PR #33](https://github.com/Piebald-AI/awesome-gemini-cli/pull/33) | 2026-04-05 |
8
+ | ai-for-developers/awesome-ai-coding-tools | 1.6k | Shell & CLI Assistants | [PR #202](https://github.com/ai-for-developers/awesome-ai-coding-tools/pull/202) | 2026-04-07 |
9
+
10
+ ## Open
11
+
12
+ | Repo | Stars | Section | Link | Date |
13
+ |------|-------|---------|------|------|
14
+ | e2b-dev/awesome-ai-agents | 27k | Open-source projects (alphabetical) | [PR #685](https://github.com/e2b-dev/awesome-ai-agents/pull/685) | 2026-04-05 |
15
+ | mahseema/awesome-ai-tools | 4.7k | Code | [PR #1027](https://github.com/mahseema/awesome-ai-tools/pull/1027) | 2026-04-05 |
16
+ | Jenqyang/Awesome-AI-Agents | 1k | Tools | [PR #143](https://github.com/Jenqyang/Awesome-AI-Agents/pull/143) | 2026-04-05 |
17
+ | rohitg00/awesome-claude-code-toolkit | 1k | Companion Apps & GUIs | [PR #211](https://github.com/rohitg00/awesome-claude-code-toolkit/pull/211) | 2026-04-05 |
18
+ | andyrewlee/awesome-agent-orchestrators | 185 | Parallel Agent Runners | [PR #27](https://github.com/andyrewlee/awesome-agent-orchestrators/pull/27) | 2026-04-06 |
19
+ | bradAGI/awesome-cli-coding-agents | 121 | Session managers & parallel runners | [PR #39](https://github.com/bradAGI/awesome-cli-coding-agents/pull/39) | 2026-04-06 |
20
+ | webfuse-com/awesome-claude | 1.3k | Applications > Desktop | [PR #166](https://github.com/webfuse-com/awesome-claude/pull/166) | 2026-04-06 |
21
+ | ikaijua/Awesome-AITools | 5.8k | AI Agent | [PR #431](https://github.com/ikaijua/Awesome-AITools/pull/431) | 2026-04-06 |
22
+
23
+ ## Rejected
24
+
25
+ | Repo | Stars | Reason | Link | Date |
26
+ |------|-------|--------|------|------|
27
+ | kyrolabs/awesome-agents | 2.1k | Auto-rejected: brand new repo | [PR #331](https://github.com/kyrolabs/awesome-agents/pull/331) | 2026-04-05 |
28
+ | hesreallyhim/awesome-claude-code | 36.3k | Used gh CLI, requires web form only | [Issue #1366](https://github.com/hesreallyhim/awesome-claude-code/issues/1366) | 2026-04-05 |
29
+
30
+ ## Parked (retry later)
31
+
32
+ | Repo | Stars | Requirement | Retry when |
33
+ |------|-------|-------------|------------|
34
+ | hesreallyhim/awesome-claude-code | 36.3k | Web form only, 7-day cooldown | April 12 — submit via [web form](https://github.com/hesreallyhim/awesome-claude-code/issues/new?template=recommend-resource.yml), category: Alternative Clients > General |
35
+ | agarrharr/awesome-cli-apps | 19.2k | 90 days old + 20 stars | After June 1 |
36
+ | alvinunreal/awesome-opensource-ai | 2.3k | 100+ stars for EMERGING.md | When we hit 100 stars |
37
+ | kyrolabs/awesome-agents | 2.1k | Needs repo traction | When we hit ~200 stars |
38
+
39
+ ## Skipped
40
+
41
+ | Repo | Stars | Reason |
42
+ |------|-------|--------|
43
+ | sourcegraph/awesome-code-ai | 1.6k | Archived |
44
+ | agamm/awesome-developer-first | 1.6k | Paid products only |
45
+ | slavakurilyak/awesome-ai-agents | 1.3k | YAML data format, complex, lower ROI |
46
+ | VoltAgent/awesome-agent-skills | 14k | Skills list, not tools |
47
+ | heilcheng/awesome-agent-skills | 3.6k | Skills list, not tools |
48
+ | Shubhamsaboo/awesome-llm-apps | 104.6k | LLM app tutorials, not tools — wrong fit |
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: awesome-lists
3
+ description: Publish our open source repo in GitHub awesome lists. Search for relevant lists, evaluate them, craft entries matching each list's format, and submit PRs/issues.
4
+ ---
5
+
6
+ # Publish to GitHub Awesome Lists
7
+
8
+ Get our repo listed in popular GitHub awesome lists to drive organic discovery.
9
+
10
+ ## Step 1: Craft the entry message
11
+
12
+ Before searching for lists, decide what to say. Read our README.md carefully — match its tone exactly (lowercase, direct, Karpathy-style, no marketing language).
13
+
14
+ Write three versions of the entry description:
15
+ - **Long** (~2 sentences) — for lists that allow detailed entries
16
+ - **Medium** (~1 sentence) — for standard lists
17
+ - **Short** (under 15 words) — for tight table formats
18
+
19
+ Rules:
20
+ - No "your" — it's a marketing trap
21
+ - No adjectives like "powerful", "seamless", "cutting-edge", "revolutionary"
22
+ - Lead with what it looks like to use (e.g. "WhatsApp-like interface") — concrete references everyone understands
23
+ - Highlight the three differentiators: chat-style multi-agent UI, autopilot routing while afk, mobile remote
24
+ - State what it does, not what it "enables" or "empowers"
25
+
26
+ Show the drafts to the user for approval before proceeding.
27
+
28
+ ## Step 2: Search for awesome lists
29
+
30
+ Use the internal search tool to find candidate lists:
31
+
32
+ ```bash
33
+ (cd /Users/rusty/Projects/temp/gpt-oss-20b-MXFP4-Q8 && npm run search:cli -- '{"queries":[
34
+ "awesome AI coding agents CLI tools github list site:github.com",
35
+ "awesome AI development tools terminal agents github site:github.com",
36
+ "awesome list claude code codex gemini CLI agents site:github.com",
37
+ "awesome open source AI tools agents frameworks github site:github.com",
38
+ "awesome AI code assistants IDE tools github list site:github.com",
39
+ "awesome terminal tools developer productivity AI github site:github.com",
40
+ "awesome AI agents autonomous coding tools curated list site:github.com"
41
+ ]}')
42
+ ```
43
+
44
+ You can send up to 7 queries at once. Results arrive as JSON with `results[].items[].link` and `.title`.
45
+
46
+ Extract unique GitHub repo URLs from results.
47
+
48
+ ## Step 3: Evaluate candidates
49
+
50
+ For each repo found, get the star count:
51
+
52
+ ```bash
53
+ gh api "repos/OWNER/REPO" --jq '.stargazers_count'
54
+ ```
55
+
56
+ Run this in a batch for all candidates. Sort by stars descending.
57
+
58
+ **Drop immediately:**
59
+ - Archived repos
60
+ - Repos requiring paid products only
61
+ - Repos that are skill/SKILL.md lists (not tool lists) — unless we have a matching skill to submit
62
+ - Repos where we don't meet minimum star/age requirements
63
+
64
+ **Check our repo stats too:**
65
+ ```bash
66
+ gh api repos/rustykuntz/clideck --jq '{stars: .stargazers_count, created: .created_at}'
67
+ ```
68
+
69
+ Compare against each list's requirements (some need 20+ stars, 90+ days, 100+ stars, etc).
70
+
71
+ ## Step 4: Read contributing rules for each target
72
+
73
+ For every list we plan to submit to, fetch and read:
74
+ 1. `CONTRIBUTING.md` (try main branch, then master)
75
+ 2. `.github/PULL_REQUEST_TEMPLATE.md`
76
+ 3. The README itself — check the entry format by looking at 2-3 existing entries near where ours would go
77
+
78
+ **Pay attention to:**
79
+ - Submission method: PR vs issue form vs Google Form (some ban PRs — e.g. awesome-claude-code uses issue forms only, PRs = ban)
80
+ - **CLI vs web-only**: some repos (e.g. hesreallyhim/awesome-claude-code) explicitly ban `gh` CLI submissions and require the GitHub web UI form. Check issue templates for "does not allow resource submissions via the `gh` CLI" language. These must be submitted by the user manually — prepare the form field values and hand them over.
81
+ - Entry format: plain markdown list, table rows, HTML details blocks — match exactly
82
+ - Ordering: alphabetical vs bottom-of-section
83
+ - Required elements: stars badges, specific badge styles, checklist items
84
+ - Star/age minimums
85
+ - PR title format (some require exact patterns like "Add APP_NAME")
86
+ - Whether they use data files (YAML/JSON) instead of README edits
87
+ - Auto-reject rules: some repos auto-close PRs from new repos with low stars/short history (e.g. kyrolabs/awesome-agents). Don't submit if we clearly don't meet the bar — it looks bad.
88
+
89
+ **Build a table for the user** summarizing each target: repo, stars, section, format, submission method, blockers.
90
+
91
+ ## Step 5: Fork and submit
92
+
93
+ For each target repo:
94
+
95
+ ```bash
96
+ # Fork
97
+ gh repo fork OWNER/REPO --clone=false
98
+
99
+ # Sync fork
100
+ gh repo sync rustykuntz/FORK
101
+
102
+ # Create branch
103
+ SHA=$(gh api repos/rustykuntz/FORK/git/ref/heads/main --jq '.object.sha')
104
+ gh api repos/rustykuntz/FORK/git/refs -f ref=refs/heads/add-clideck -f sha="$SHA"
105
+
106
+ # Get file content and SHA
107
+ gh api -X GET repos/rustykuntz/FORK/contents/README.md --field ref=add-clideck --jq '.sha'
108
+ ```
109
+
110
+ To edit and upload via API (avoids cloning):
111
+
112
+ 1. Download the file content
113
+ 2. Insert our entry at the correct position (use python3 for multiline insertions — awk/sed break on complex entries)
114
+ 3. Base64 encode the updated content
115
+ 4. Push via Contents API:
116
+
117
+ ```bash
118
+ gh api repos/rustykuntz/FORK/contents/README.md \
119
+ -X PUT \
120
+ -f message="Add clideck to SECTION_NAME" \
121
+ -f content="$ENCODED" \
122
+ -f sha="$FILE_SHA" \
123
+ -f branch=add-clideck
124
+ ```
125
+
126
+ 5. **Always verify** the edit before creating the PR:
127
+ ```bash
128
+ gh api -X GET repos/rustykuntz/FORK/contents/README.md --field ref=add-clideck --jq '.content' | base64 -d | grep -B2 -A2 "clideck"
129
+ ```
130
+
131
+ 6. Create PR matching the repo's requirements:
132
+ ```bash
133
+ gh pr create --repo OWNER/REPO \
134
+ --head rustykuntz:add-clideck \
135
+ --title "TITLE MATCHING THEIR FORMAT" \
136
+ --body "BODY WITH THEIR CHECKLIST/TEMPLATE"
137
+ ```
138
+
139
+ For issue-based submissions (like awesome-claude-code):
140
+ ```bash
141
+ gh issue create --repo OWNER/REPO --title "TITLE" --body "BODY"
142
+ ```
143
+
144
+ ## Step 6: Track results
145
+
146
+ Print a final summary table with all submissions: repo, stars, type (PR/issue), link, and any blockers.
147
+
148
+ Note any lists that are parked (we don't meet requirements yet) with the specific threshold we need to hit and when to retry.
@@ -0,0 +1,224 @@
1
+ ---
2
+ name: research-experiment
3
+ description: Coordinate autonomous research experiments across multiple coding agents using isolated git worktrees. Use when a user wants the main agent to define a goal, constraints, acceptance criteria, and experiment boundaries, then dispatch Codex/Claude/Gemini or other agents to independently search for solutions without touching production code.
4
+ ---
5
+
6
+ # Research Experiment
7
+
8
+ Use this skill to run parallel, autonomous experiments safely.
9
+
10
+ There are two roles:
11
+
12
+ - Main Agent: owns the research brief, workspace setup, researcher prompts, verification, and merge decision.
13
+ - Experiment Agent: owns independent exploration inside one assigned worktree and must not redefine the experiment.
14
+
15
+ If the user says "you are the main agent", follow the Main Agent Role. If the user says "you are an experiment agent" or "researcher agent", follow the Experiment Agent Role.
16
+
17
+ ## Main Agent Role
18
+
19
+ The main agent defines the experiment and coordinates researchers. It must not let each researcher invent different goals or acceptance criteria.
20
+
21
+ ## Main Agent Workflow
22
+
23
+ 1. Convert the user request into an experiment brief:
24
+ - Goal: the outcome to achieve.
25
+ - Acceptance criteria: exact tests, benchmarks, or review gates.
26
+ - Hard constraints: what must not change.
27
+ - Quality bar: what counts as meaningful progress versus noise.
28
+ - Shared resources: ports, GPUs, model caches, services, datasets, credentials, or external APIs.
29
+ - Stop conditions: when researchers may quit.
30
+
31
+ 2. Identify the production repository root:
32
+ - Use `git rev-parse --show-toplevel` when inside a git repo.
33
+ - If the project has nested repos, identify which repo owns the files under experiment.
34
+ - Do not assume the current working directory is the repo root.
35
+
36
+ 3. Create per-researcher worktrees inside the project folder, not beside it:
37
+ - Prefer a project-local directory such as `<project>/.research-worktrees/<slug>-<n>`.
38
+ - Keep worktree directories inside the main project folder so agents do not need extra filesystem permissions.
39
+ - Do not create sibling worktrees such as `../project_research_1` unless the user explicitly asks.
40
+ - Never point a researcher at the production checkout for edits.
41
+ - Use unique branches, for example `research/<slug>-1`, `research/<slug>-2`.
42
+
43
+ 4. Give every researcher the same goal and rules:
44
+ - Do not assign fixed technical roles unless the user explicitly asks.
45
+ - Let each researcher decide the approach and iterate independently.
46
+ - Include the exact worktree path, branch, allowed edit scope, forbidden files, verification commands, and report format.
47
+ - Save the canonical brief to the experiment folder before dispatching researchers.
48
+
49
+ 5. Verify centrally:
50
+ - Researchers may run local checks in their worktree, but the main agent owns authoritative acceptance verification.
51
+ - If benchmarks contend for scarce resources, run final benchmarks sequentially from the main agent.
52
+ - Merge nothing unless it passes acceptance criteria and clears the quality bar.
53
+
54
+ ## Experiment Folder
55
+
56
+ The main agent should create one experiment folder under the main project, for example:
57
+
58
+ ```text
59
+ .research-worktrees/<experiment-slug>/
60
+ ```
61
+
62
+ Inside it, create:
63
+
64
+ - `EXPERIMENT.md`: the canonical brief, baseline, quality gate, constraints, assignments, commands, and report format.
65
+ - `<slug>-experiment-1/`: worktree for researcher 1.
66
+ - `<slug>-experiment-2/`: worktree for researcher 2.
67
+ - `<slug>-experiment-3/`: worktree for researcher 3.
68
+ - `<slug>-experiment-1/LOG.md`: progress log for researcher 1.
69
+ - `<slug>-experiment-2/LOG.md`: progress log for researcher 2.
70
+ - `<slug>-experiment-3/LOG.md`: progress log for researcher 3.
71
+
72
+ Researcher prompts should tell agents to read `EXPERIMENT.md` first and then follow only their assigned workspace, branch, log file, and resource values.
73
+
74
+ The main agent may check each researcher log during the experiment to monitor progress without interrupting researchers. Researcher agents should append concise entries after each meaningful experiment loop:
75
+
76
+ - Hypothesis tried.
77
+ - Files changed.
78
+ - Command run.
79
+ - Result versus same-session baseline.
80
+ - Keep/reject decision.
81
+ - Current blocker, if any.
82
+
83
+ ## Worktree Setup
84
+
85
+ Use project-local worktrees. The worktree directory must live under the main project folder:
86
+
87
+ ```bash
88
+ mkdir -p .research-worktrees
89
+ mkdir -p .research-worktrees/<experiment-slug>
90
+ git worktree add .research-worktrees/<experiment-slug>/<slug>-experiment-1 -b research/<slug>-1
91
+ git worktree add .research-worktrees/<experiment-slug>/<slug>-experiment-2 -b research/<slug>-2
92
+ git worktree add .research-worktrees/<experiment-slug>/<slug>-experiment-3 -b research/<slug>-3
93
+ ```
94
+
95
+ If a branch already exists, choose a new suffix. Do not delete or overwrite existing worktrees unless the user explicitly asks.
96
+
97
+ When the target files live in a nested repo, run the worktree commands from that nested repo root but still put the worktree folders under the main project folder. Example:
98
+
99
+ ```bash
100
+ cd path/to/nested/repo
101
+ mkdir -p /absolute/path/to/main-project/.research-worktrees
102
+ mkdir -p /absolute/path/to/main-project/.research-worktrees/<experiment-slug>
103
+ git worktree add /absolute/path/to/main-project/.research-worktrees/<experiment-slug>/<slug>-experiment-1 -b research/<slug>-1
104
+ ```
105
+
106
+ ## Baseline And Quality Gate
107
+
108
+ Before changing code, each researcher must run the exact benchmark or check command once from their assigned worktree and record it as their same-session baseline.
109
+
110
+ Compare final results against:
111
+
112
+ - The user/main-agent supplied baseline.
113
+ - The researcher’s same-session baseline.
114
+
115
+ The main agent/user defines the quality gate for each experiment. Examples:
116
+
117
+ - Test suite must pass.
118
+ - Benchmark score must not regress.
119
+ - ASR must recover at least N words from generated TTS.
120
+ - Human listening check required.
121
+
122
+ Do not invent or weaken the quality gate. If the gate is unclear, ask the main agent before accepting a result.
123
+
124
+ ## Experiment Agent Role
125
+
126
+ The experiment agent executes the fixed brief from the main agent. It uses this skill for discipline and workflow only.
127
+
128
+ Follow only your assigned researcher section from the experiment brief. Do not edit outside your assigned worktree.
129
+ Create any temporary files, profiling scripts, generated outputs, scratch notes, and helper artifacts inside your assigned worktree. Do not use `/tmp`, `/var/tmp`, home-directory scratch folders, or sibling project folders unless the brief explicitly allows it.
130
+
131
+ The experiment agent must not redefine:
132
+
133
+ - Goal.
134
+ - Constraints.
135
+ - Quality gate.
136
+ - Benchmark commands.
137
+ - Acceptance criteria.
138
+ - Assigned workspace or branch.
139
+
140
+ If any of those are missing or ambiguous, ask the main agent for clarification before accepting a result. Do not make up a weaker gate.
141
+
142
+ ## Experiment Agent Autonomy
143
+
144
+ DO NOT STOP EXPERIMENTING UNLESS YOU ACHIEVED THE GOALS OR ABSOLUTELY NECESSARY.
145
+
146
+ - Do NOT ask the user if you should continue.
147
+ - The user may be away from the computer and expects the experiment to continue until you achieve the experiment goals, so keep working until the task is naturally complete.
148
+ - You are autonomous. If you are unsure how to proceed, re-read the skill, goals, context, think differently, try different innovative approaches, and continue.
149
+ - Stop only if something out of your control blocks you from continuing. Otherwise continue experimenting until goals are achieved or the useful paths are exhausted.
150
+
151
+ ## Researcher Prompt Template
152
+
153
+ Include this block, or an equivalent adapted version, in every researcher prompt:
154
+
155
+ ```text
156
+ You are an autonomous research agent for this experiment.
157
+
158
+ Goal:
159
+ <goal>
160
+
161
+ Experiment rules and boundaries:
162
+ <rules>
163
+
164
+ Assigned workspace:
165
+ <absolute path to your worktree>
166
+
167
+ Canonical experiment brief:
168
+ <absolute path to EXPERIMENT.md>
169
+
170
+ Assigned experiment log:
171
+ <absolute path to your LOG.md>
172
+
173
+ You must work only inside your assigned worktree unless the brief explicitly allows another path. Do not edit, overwrite, or revert files in the production checkout. Do not change benchmark scoring, test fixtures, or acceptance criteria unless the brief explicitly asks for that.
174
+ Read the canonical experiment brief before making changes. Follow only your assigned researcher section. Do not redefine the goal, constraints, quality gate, benchmark commands, acceptance criteria, workspace, branch, port, log path, or resource assignments. Do not edit outside your assigned worktree.
175
+ If you need temp folders, profiling scripts, scratch files, benchmark outputs, or helper artifacts, create them inside your assigned worktree. Do not use `/tmp`, `/var/tmp`, home-directory scratch folders, or sibling project folders unless the brief explicitly allows it.
176
+
177
+ DO NOT STOP EXPERIMENTING UNLESS YOU ACHIEVED THE GOALS OR ABSOLUTELY NECESSARY.
178
+ - Do NOT ask the user if you should continue.
179
+ - The user may be away from the computer and expects the experiment to continue until you achieve the experiment goals, so keep working until the task is naturally complete.
180
+ - You are autonomous. If you are unsure how to proceed, re-read the skill, goals, context, think differently, try different innovative approaches, and continue.
181
+ - Stop only if something out of your control blocks you from continuing. Otherwise continue experimenting until goals are achieved or useful paths are exhausted.
182
+
183
+ Loop:
184
+ 1. Inspect the code and constraints.
185
+ 2. Form hypotheses.
186
+ 3. Try a small, explainable experiment.
187
+ 4. Run relevant verification.
188
+ 5. Keep, revise, or reject the attempt.
189
+ 6. Repeat until the goal is achieved, useful paths are exhausted, or an external blocker prevents progress.
190
+
191
+ Report format:
192
+ - Worktree path and branch.
193
+ - Changed files.
194
+ - Commands run and exact relevant output.
195
+ - Results against acceptance criteria.
196
+ - Failed attempts and why they were rejected.
197
+ - Whether you recommend merging the patch.
198
+ - Any cleanup needed: running servers, ports, PIDs, temp files.
199
+
200
+ Also append concise progress entries to your assigned experiment log after each meaningful experiment loop.
201
+ ```
202
+
203
+ ## Shared Resource Rules
204
+
205
+ For resources that can contaminate results or conflict across agents:
206
+
207
+ - Assign unique ports, output directories, cache directories, and branch names.
208
+ - Do not run final GPU/MPS benchmarks concurrently across researchers.
209
+ - Prefer researcher-local smoke tests and main-agent final benchmarks.
210
+ - Require researchers to stop servers they started, or report any still-running process clearly.
211
+
212
+ ## Merge Rules
213
+
214
+ The main agent must review researcher diffs before applying them to production.
215
+
216
+ Reject or keep separate any patch that:
217
+
218
+ - Touches production checkout files.
219
+ - Changes tests, benchmarks, fixtures, sample inputs, or scoring without permission.
220
+ - Passes only because the acceptance criteria were weakened.
221
+ - Produces only noisy or marginal improvement below the declared quality bar.
222
+ - Leaves unexplained background processes or shared state.
223
+
224
+ If a researcher accidentally edits the production checkout, preserve pre-existing user changes and move or recreate the experiment in an isolated worktree before continuing.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Research Experiment"
3
+ short_description: "Run parallel autonomous experiments in isolated git worktrees."
4
+ default_prompt: "Use this skill to prepare and coordinate autonomous research agents that experiment in isolated git worktrees without touching production code."
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: template-skill
3
+ description: Replace with description of the skill and when Claude should use it.
4
+ ---
5
+
6
+ # Insert instructions below
@@ -10,9 +10,42 @@ const codexMenuPoll = new Map(); // sessionId → interval (polling for menu aft
10
10
  const codexPendingStop = new Map(); // sessionId → ts (notify hook arrived; wait for next response.completed)
11
11
  const codexOutputDone = new Map(); // sessionId → ts (fallback if notify never fires)
12
12
  const codexPendingIdle = new Map(); // sessionId → timer (tiny settle before committing idle)
13
+ const codexToolPhasePending = new Set(); // sessionId set once Codex has announced a tool-call phase, cleared when the phase resolves
14
+ const codexPendingTools = new Map(); // sessionId → Set(callId) for approved Codex tool calls still awaiting a result
13
15
  let broadcastFn = null;
14
16
  let sessionsFn = null;
15
17
 
18
+ function getPendingToolSet(id) {
19
+ let set = codexPendingTools.get(id);
20
+ if (!set) { set = new Set(); codexPendingTools.set(id, set); }
21
+ return set;
22
+ }
23
+
24
+ function clearPendingTools(id) {
25
+ codexPendingTools.delete(id);
26
+ }
27
+
28
+ function addPendingTool(id, callId) {
29
+ if (!callId) return;
30
+ getPendingToolSet(id).add(callId);
31
+ }
32
+
33
+ function resolvePendingTool(id, callId) {
34
+ if (!callId) return;
35
+ const set = codexPendingTools.get(id);
36
+ if (!set) return;
37
+ set.delete(callId);
38
+ if (!set.size) codexPendingTools.delete(id);
39
+ }
40
+
41
+ function hasPendingTools(id) {
42
+ return !!codexPendingTools.get(id)?.size;
43
+ }
44
+
45
+ function hasPendingToolState(id) {
46
+ return codexToolPhasePending.has(id) || hasPendingTools(id);
47
+ }
48
+
16
49
  function init(broadcast, getSessions) {
17
50
  broadcastFn = broadcast;
18
51
  sessionsFn = getSessions;
@@ -77,11 +110,8 @@ function handleLogs(req, res) {
77
110
  // Debug telemetry logs — uncomment as needed, do not delete
78
111
  // if (serviceName === 'claude-code' && eventName) console.log(`[telemetry:claude] ${eventName}`);
79
112
  // if (serviceName === 'codex_cli_rs' && eventName) {
80
- // const details = Object.entries(attrs)
81
- // .filter(([k]) => k !== 'event.name')
82
- // .map(([k, v]) => `${k}=${JSON.stringify(v)}`)
83
- // .join(' ');
84
- // console.log(`[telemetry:codex] ${eventName} session=${resolvedId.slice(0,8)}${details ? ' ' + details : ''}`);
113
+ // const kind = attrs['event.kind'] ? ` kind=${attrs['event.kind']}` : '';
114
+ // console.log(`[telemetry:codex] ${eventName}${kind} session=${resolvedId.slice(0,8)}`);
85
115
  // }
86
116
  // if (serviceName === 'gemini-cli' && eventName) console.log(`[telemetry:gemini] ${eventName}`);
87
117
 
@@ -100,9 +130,18 @@ function handleLogs(req, res) {
100
130
  if (eventName === 'codex.user_prompt') {
101
131
  codexPendingStop.delete(resolvedId);
102
132
  codexOutputDone.delete(resolvedId);
133
+ codexToolPhasePending.delete(resolvedId);
134
+ clearPendingTools(resolvedId);
103
135
  broadcastFn?.({ type: 'session.status', id: resolvedId, working: true, source: 'telemetry' });
104
136
  }
105
137
 
138
+ // Codex can announce a function-call phase before the later tool_decision
139
+ // event carries a call_id. Block idle as soon as the tool phase is known,
140
+ // then refine it to call-specific tracking when tool_decision arrives.
141
+ if (eventName === 'codex.websocket_event' && attrs['event.kind'] === 'response.function_call_arguments.done') {
142
+ codexToolPhasePending.add(resolvedId);
143
+ }
144
+
106
145
  // Fallback: when notify does not fire, require an output item to finish
107
146
  // before treating the next response.completed as a real end-of-turn.
108
147
  if (eventName === 'codex.websocket_event' && attrs['event.kind'] === 'response.output_item.done') {
@@ -113,7 +152,10 @@ function handleLogs(req, res) {
113
152
  // Also poll briefly for a visible choice menu.
114
153
  if (eventName === 'codex.sse_event' && attrs['event.kind'] === 'response.completed') {
115
154
  const pendingStopAt = codexPendingStop.get(resolvedId);
116
- if (pendingStopAt && Date.now() - pendingStopAt <= 5000) {
155
+ if (hasPendingToolState(resolvedId)) {
156
+ // Tool execution is still in-flight; this completion only closed the
157
+ // function-call phase, not the user's full turn.
158
+ } else if (pendingStopAt && Date.now() - pendingStopAt <= 5000) {
117
159
  // console.log(`[codex] complete matched pending-stop session=${resolvedId.slice(0,8)} age=${Date.now() - pendingStopAt}ms`);
118
160
  codexPendingStop.delete(resolvedId);
119
161
  codexOutputDone.delete(resolvedId);
@@ -134,9 +176,18 @@ function handleLogs(req, res) {
134
176
  if (eventName === 'codex.tool_decision') {
135
177
  codexPendingStop.delete(resolvedId);
136
178
  codexOutputDone.delete(resolvedId);
179
+ if ((attrs.decision || '').toLowerCase() !== 'denied') {
180
+ addPendingTool(resolvedId, attrs.call_id || attrs['call.id']);
181
+ } else {
182
+ codexToolPhasePending.delete(resolvedId);
183
+ }
137
184
  cancelCodexMenuPoll(resolvedId);
138
185
  broadcastFn?.({ type: 'session.status', id: resolvedId, working: true, source: 'telemetry' });
139
186
  }
187
+ if (eventName === 'codex.tool_result') {
188
+ codexToolPhasePending.delete(resolvedId);
189
+ resolvePendingTool(resolvedId, attrs.call_id || attrs['call.id']);
190
+ }
140
191
  // Codex: user_prompt or next sse_event cancels menu poll
141
192
  if ((eventName === 'codex.user_prompt' || (eventName === 'codex.sse_event' && attrs['event.kind'] !== 'response.completed'))) {
142
193
  codexOutputDone.delete(resolvedId);
@@ -228,6 +279,8 @@ function clear(id) {
228
279
  cancelCodexPendingIdle(id);
229
280
  codexPendingStop.delete(id);
230
281
  codexOutputDone.delete(id);
282
+ codexToolPhasePending.delete(id);
283
+ clearPendingTools(id);
231
284
  const pending = pendingSetup.get(id);
232
285
  if (pending) { clearTimeout(pending.timer); pendingSetup.delete(id); }
233
286
  }