Four self-contained HTML mockups (wireframe, flows, hi-fi, design system), four Dart theme files (clide, midnight, paper, terminal), and flat PNG renders. Reference material for the UI build — not runtime assets. Co-Authored-By: Claude <noreply@anthropic.com>
186 lines
58 KiB
HTML
186 lines
58 KiB
HTML
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>clide — interaction flows</title>
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body { background: #faf9f5; display: flex; align-items: center; justify-content: center; min-height: 100vh; font-family: -apple-system, BlinkMacSystemFont, sans-serif; }
|
||
#__bundler_loading { position: fixed; bottom: 20px; right: 20px; font: 13px/1.4 -apple-system, BlinkMacSystemFont, sans-serif; color: #666; background: #fff; padding: 8px 14px; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,0.12); z-index: 10000; }
|
||
#__bundler_thumbnail { position: fixed; inset: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: #faf9f5; z-index: 9999; }
|
||
#__bundler_thumbnail svg { width: 100%; height: 100%; object-fit: contain; }
|
||
#__bundler_placeholder { color: #999; font-size: 14px; }
|
||
</style>
|
||
<noscript>
|
||
<style>#__bundler_loading { display: none; }</style>
|
||
<div style="position:fixed;bottom:12px;left:12px;font:13px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;color:#999;background:rgba(255,255,255,0.9);padding:6px 12px;border-radius:6px;box-shadow:0 1px 4px rgba(0,0,0,0.08);z-index:10000;">
|
||
This page requires JavaScript to display.
|
||
</div>
|
||
</noscript>
|
||
</head>
|
||
<body>
|
||
<div id="__bundler_thumbnail">
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||
<rect width="100" height="100" fill="#F4F1EA"></rect>
|
||
<g stroke="#1A1A1A" stroke-width="1.2" fill="none">
|
||
<rect x="18" y="36" width="18" height="28"></rect>
|
||
<rect x="41" y="36" width="18" height="28"></rect>
|
||
<rect x="64" y="36" width="18" height="28"></rect>
|
||
<path d="M37 50 l3 0 M40 50 l-2 -2 M40 50 l-2 2" stroke="#C14B2A"></path>
|
||
<path d="M60 50 l3 0 M63 50 l-2 -2 M63 50 l-2 2" stroke="#C14B2A"></path>
|
||
</g>
|
||
<text x="50" y="82" text-anchor="middle" fill="#C14B2A" font-family="Caveat,cursive" font-size="9">flows</text>
|
||
</svg>
|
||
</div>
|
||
<div id="__bundler_loading">Unpacking...</div>
|
||
|
||
<script>
|
||
|
||
document.addEventListener('DOMContentLoaded', async function() {
|
||
const loading = document.getElementById('__bundler_loading');
|
||
function setStatus(msg) { if (loading) loading.textContent = msg; }
|
||
|
||
// Error sink persists across replaceWith since it's on window, not the DOM.
|
||
window.addEventListener('error', function(e) {
|
||
var p = document.body || document.documentElement;
|
||
var d = document.getElementById('__bundler_err') || p.appendChild(document.createElement('div'));
|
||
d.id = '__bundler_err';
|
||
d.style.cssText = 'position:fixed;bottom:12px;left:12px;right:12px;font:12px/1.4 ui-monospace,monospace;background:#2a1215;color:#ff8a80;padding:10px 14px;border-radius:8px;border:1px solid #5c2b2e;z-index:99999;white-space:pre-wrap;max-height:40vh;overflow:auto';
|
||
d.textContent = (d.textContent ? d.textContent + String.fromCharCode(10) : '') +
|
||
'[bundle] ' + (e.message || e.type) +
|
||
(e.filename ? ' (' + e.filename.slice(0, 60) + ':' + e.lineno + ')' : '');
|
||
}, true);
|
||
|
||
try {
|
||
const manifestEl = document.querySelector('script[type="__bundler/manifest"]');
|
||
const templateEl = document.querySelector('script[type="__bundler/template"]');
|
||
if (!manifestEl || !templateEl) {
|
||
setStatus('Error: missing bundle data');
|
||
console.error('[bundler] Missing script tags — manifestEl:', !!manifestEl, 'templateEl:', !!templateEl);
|
||
return;
|
||
}
|
||
|
||
const manifest = JSON.parse(manifestEl.textContent);
|
||
let template = JSON.parse(templateEl.textContent);
|
||
|
||
const uuids = Object.keys(manifest);
|
||
setStatus('Unpacking ' + uuids.length + ' assets...');
|
||
|
||
const blobUrls = {};
|
||
await Promise.all(uuids.map(async (uuid) => {
|
||
const entry = manifest[uuid];
|
||
try {
|
||
const binaryStr = atob(entry.data);
|
||
const bytes = new Uint8Array(binaryStr.length);
|
||
for (let i = 0; i < binaryStr.length; i++) bytes[i] = binaryStr.charCodeAt(i);
|
||
|
||
let finalBytes = bytes;
|
||
if (entry.compressed) {
|
||
if (typeof DecompressionStream !== 'undefined') {
|
||
const ds = new DecompressionStream('gzip');
|
||
const writer = ds.writable.getWriter();
|
||
const reader = ds.readable.getReader();
|
||
writer.write(bytes);
|
||
writer.close();
|
||
const chunks = [];
|
||
let totalLen = 0;
|
||
while (true) {
|
||
const { done, value } = await reader.read();
|
||
if (done) break;
|
||
chunks.push(value);
|
||
totalLen += value.length;
|
||
}
|
||
finalBytes = new Uint8Array(totalLen);
|
||
let offset = 0;
|
||
for (const chunk of chunks) { finalBytes.set(chunk, offset); offset += chunk.length; }
|
||
} else {
|
||
console.warn('DecompressionStream not available, asset ' + uuid + ' may not render');
|
||
}
|
||
}
|
||
|
||
blobUrls[uuid] = URL.createObjectURL(new Blob([finalBytes], { type: entry.mime }));
|
||
} catch (err) {
|
||
console.error('Failed to decode asset ' + uuid + ':', err);
|
||
blobUrls[uuid] = URL.createObjectURL(new Blob([], { type: entry.mime }));
|
||
}
|
||
}));
|
||
|
||
const extResEl = document.querySelector('script[type="__bundler/ext_resources"]');
|
||
const extResources = extResEl ? JSON.parse(extResEl.textContent) : [];
|
||
const resourceMap = {};
|
||
for (const entry of extResources) {
|
||
if (blobUrls[entry.uuid]) resourceMap[entry.id] = blobUrls[entry.uuid];
|
||
}
|
||
|
||
setStatus('Rendering...');
|
||
for (const uuid of uuids) template = template.split(uuid).join(blobUrls[uuid]);
|
||
|
||
// Strip integrity + crossorigin — blob URLs from a file:// document inherit
|
||
// a null origin, so crossorigin forces a CORS fetch that SRI then rejects.
|
||
// The manifest bytes are ours; SRI protects against CDN compromise, not this.
|
||
template = template.replace(/\s+integrity="[^"]*"/gi, '').replace(/\s+crossorigin="[^"]*"/gi, '');
|
||
|
||
const resourceScript = '<script>window.__resources = ' +
|
||
JSON.stringify(resourceMap).split('</' + 'script>').join('<\\/' + 'script>') +
|
||
';</' + 'script>';
|
||
// Inject after <head> so the DOCTYPE stays first; prepending the script
|
||
// would push the parser into quirks mode. DOMParser always emits a <head>
|
||
// (synthesizing one if the source HTML omitted it) but may carry
|
||
// attributes through, so match the full opening tag. slice() rather than
|
||
// replace() keeps us clear of $-pattern substitution in resourceScript.
|
||
const headOpen = template.match(/<head[^>]*>/i);
|
||
if (headOpen) {
|
||
const i = headOpen.index + headOpen[0].length;
|
||
template = template.slice(0, i) + resourceScript + template.slice(i);
|
||
}
|
||
|
||
// Parse the template and swap the root element. Scripts inserted via
|
||
// DOMParser/replaceWith are inert per spec — re-create each with
|
||
// createElement so they execute, awaiting onload for src scripts to
|
||
// preserve ordering (React before ReactDOM before Babel before text/babel).
|
||
const doc = new DOMParser().parseFromString(template, 'text/html');
|
||
document.documentElement.replaceWith(doc.documentElement);
|
||
const dead = Array.from(document.scripts);
|
||
for (const old of dead) {
|
||
const s = document.createElement('script');
|
||
for (const a of old.attributes) s.setAttribute(a.name, a.value);
|
||
s.textContent = old.textContent;
|
||
// text/babel scripts with a src: fetch and inline. transformScriptTags
|
||
// does XHR against the src, but blob:null/ from a file:// origin is
|
||
// silently dropped. Inlining makes it a plain inline babel script,
|
||
// which transformScriptTags handles unconditionally.
|
||
if ((s.type === 'text/babel' || s.type === 'text/jsx') && s.src) {
|
||
const r = await fetch(s.src);
|
||
s.textContent = await r.text();
|
||
s.removeAttribute('src');
|
||
}
|
||
const p = s.src ? new Promise(function(r) { s.onload = s.onerror = r; }) : null;
|
||
old.replaceWith(s);
|
||
if (p) await p;
|
||
}
|
||
// Babel standalone auto-transforms type=text/babel on DOMContentLoaded,
|
||
// which fired before we swapped the document. Trigger manually if present.
|
||
if (window.Babel && typeof window.Babel.transformScriptTags === 'function') {
|
||
window.Babel.transformScriptTags();
|
||
}
|
||
} catch (err) {
|
||
setStatus('Error unpacking: ' + err.message);
|
||
console.error('Bundle unpack error:', err);
|
||
}
|
||
});
|
||
|
||
</script>
|
||
|
||
<script type="__bundler/manifest">
|
||
{}
|
||
</script>
|
||
|
||
<script type="__bundler/ext_resources">
|
||
[]
|
||
</script>
|
||
|
||
<script type="__bundler/template">
|
||
"<!DOCTYPE html>\n<html lang=\"en\"><head>\n<meta charset=\"utf-8\">\n<title>clide — interaction flows<\u002Ftitle>\n\n<style>\n :root {\n --paper: #f4f1ea;\n --paper-2: #ece7db;\n --ink: #1a1a1a;\n --ink-2: #4a4a4a;\n --ink-3: #8a8a82;\n --accent: #c14b2a;\n --accent-2: #2a6fc1;\n --ok: #2d8a52;\n --warn: #b0821f;\n --err: #b03a2a;\n }\n html, body { margin:0; padding:0; background:var(--paper); color:var(--ink);\n font-family:\"IBM Plex Mono\",\"JetBrains Mono\",ui-monospace,Menlo,monospace; font-size:12px;}\n .sheet { max-width: 1600px; margin: 32px auto 80px; padding: 28px 36px 36px;\n background:var(--paper); border:1.5px solid var(--ink); position:relative;}\n .sheet::before {\n content:\"\"; position:absolute; inset:0;\n background-image:\n linear-gradient(to right, rgba(26,26,26,0.04) 1px, transparent 1px),\n linear-gradient(to bottom, rgba(26,26,26,0.04) 1px, transparent 1px);\n background-size:16px 16px; pointer-events:none;\n }\n .titleblock { display:flex; justify-content:space-between; align-items:flex-end;\n border-bottom:1px solid var(--ink); padding-bottom:10px; margin-bottom:24px;}\n .titleblock h1 { font-family:\"Josefin Sans\",\"Helvetica Neue\",sans-serif;\n font-weight:300; font-size:34px; margin:0; letter-spacing:0.02em;}\n .titleblock h1 em { font-style:normal; color:var(--ink-3); font-weight:300;}\n .titleblock .meta { font-size:11px; color:var(--ink-2); text-align:right; line-height:1.6;}\n .caption { font-size:11px; color:var(--ink-2); margin:-8px 0 20px; max-width:1100px;}\n\n .flow { margin: 28px 0 56px; position: relative;}\n .flow h2 {\n font-family:\"Josefin Sans\",sans-serif; font-weight:400; font-size:22px;\n letter-spacing:0.02em; margin:0 0 4px; }\n .flow h2 .idx {\n display:inline-block; border:1.5px solid var(--ink); border-radius:50%;\n width:26px; height:26px; line-height:22px; text-align:center;\n font-family:\"IBM Plex Mono\",monospace; font-size:12px; margin-right:10px;\n vertical-align:3px;\n }\n .flow .sub { font-size:11px; color:var(--ink-2); margin:0 0 14px; max-width:1000px;}\n .flow .sub code {\n font-family:inherit; background:var(--paper-2); padding:0 3px; color:var(--ink);\n }\n\n .frames {\n display: flex;\n gap: 18px;\n align-items: flex-start;\n overflow-x: auto;\n padding-bottom: 8px;\n }\n .frame {\n flex: 0 0 auto;\n width: 300px;\n min-height: 200px;\n border: 1.5px solid var(--ink);\n background: var(--paper);\n position: relative;\n display: flex;\n flex-direction: column;\n }\n .frame .cap {\n position: absolute;\n top: -22px;\n left: 0;\n font-size: 10px;\n color: var(--ink-2);\n letter-spacing: 0.04em;\n }\n .frame .cap b { color: var(--ink); font-weight: 600; }\n .frame .hdr {\n padding: 6px 10px;\n border-bottom: 1px solid var(--ink);\n background: var(--paper-2);\n font-size: 10px;\n color: var(--ink-2);\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .frame .hdr b { color: var(--ink); font-weight: 600; }\n .frame .inner { flex:1; padding: 8px 10px; position: relative; }\n\n /* mini app frame: sidebar/ws/context proportions at 300px width */\n .mini {\n display: grid;\n grid-template-columns: 60px 1fr 58px;\n grid-template-rows: 1fr 10px;\n height: 200px;\n gap: 0;\n border-top: 1px solid var(--ink);\n }\n .mini > div { border-right: 1px solid var(--ink); padding: 4px 5px; font-size: 9px; overflow: hidden;}\n .mini > .cx { border-right: 0; }\n .mini .sb-tabs, .mini .ws-tabs, .mini .cx-tabs {\n display: flex; gap: 2px; font-size: 8px; color: var(--ink-3);\n border-bottom: 1px dashed var(--ink-3); padding-bottom: 2px; margin-bottom: 3px;\n }\n .mini .sb-tabs b, .mini .ws-tabs b, .mini .cx-tabs b { color: var(--ink); }\n .mini .status {\n grid-column: 1 / -1; grid-row: 2;\n border-top: 1px solid var(--ink);\n border-right: 0 !important;\n background: var(--paper-2);\n display: flex; align-items: center;\n padding: 0 6px;\n font-size: 8px; color: var(--ink-3);\n justify-content: flex-end;\n }\n .mini .plug { display:inline-block; width:5px; height:5px; border-radius:50%; background: var(--ok); margin-right: 4px;}\n .mini .plug.bad { background: var(--err);}\n .mini .ln { height: 4px; background: rgba(26,26,26,0.15); margin: 2px 0;}\n .mini .ln.sh { width: 60%;}\n .mini .ln.md { width: 82%;}\n .mini .ln.lg { width: 95%;}\n .mini .selected { background: rgba(26,26,26,0.08); }\n .mini .term-block {\n background: #111; color: #ededed; padding: 4px 5px; border-radius: 2px;\n font-family:\"JetBrains Mono\",monospace; font-size: 8px; line-height: 1.4;\n }\n .mini .term-block .ok { color:#8fdc9b;}\n .mini .term-block .dim { color:#8a8a82;}\n\n /* modal overlay (for dialog flow) */\n .mini .modal-backdrop {\n position: absolute; inset: 0;\n background: rgba(0,0,0,0.5);\n display: flex; align-items: center; justify-content: center;\n z-index: 2;\n }\n .mini .modal {\n width: 190px; background: var(--paper);\n border: 1.5px solid var(--ink);\n padding: 6px; font-size: 9px;\n }\n .mini .modal .t { font-weight: 600; margin-bottom: 4px; border-bottom: 1px dashed var(--ink-3); padding-bottom: 3px;}\n .mini .modal .mrow { padding: 2px 3px; display: flex; justify-content: space-between; align-items: center;}\n .mini .modal .mrow.sel { background: rgba(26,26,26,0.12); }\n .mini .modal .mrow .kbd { color: var(--ink-3); font-size: 8px;}\n\n .mini-wrap { position: relative; }\n\n /* transitions / arrows between frames */\n .arrow-row {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 54px;\n min-height: 220px;\n font-family: \"Caveat\",\"Kalam\",cursive;\n color: var(--accent);\n font-size: 14px;\n position: relative;\n }\n .arrow-row .lbl {\n position: absolute;\n top: 18px;\n text-align: center;\n width: 100%;\n color: var(--accent);\n line-height: 1.1;\n }\n .arrow-row .tag {\n font-family:\"IBM Plex Mono\",monospace;\n font-size: 9px;\n border: 1.5px solid var(--accent);\n border-radius: 8px;\n padding: 0 5px;\n color: var(--accent);\n display: inline-block;\n }\n .arrow-row svg { overflow: visible; }\n\n /* states key */\n .states {\n display: grid; grid-template-columns: repeat(4, 1fr);\n gap: 10px 20px;\n border-top: 1px solid var(--ink);\n padding-top: 14px; margin-top: 18px;\n }\n .states h3 { margin: 0 0 6px; font-family:\"Josefin Sans\",sans-serif; font-weight:400; font-size:14px;}\n .states ul { margin:0; padding-left: 14px; }\n .states li { font-size: 10px; color: var(--ink-2); margin-bottom: 3px;}\n .states code { background: var(--paper-2); padding: 0 3px; color: var(--ink); font-family: inherit;}\n\n /* generic palette row */\n .row-item {\n display: flex; justify-content: space-between; align-items: center;\n font-size: 9px; padding: 2px 4px; color: var(--ink-2);\n }\n .row-item.act { background: rgba(26,26,26,0.12); color: var(--ink);}\n .row-item .k { color: var(--ink-3); font-size: 8px; }\n\n /* a note */\n .note {\n position: absolute; color: var(--accent);\n font-family: \"Caveat\",\"Kalam\",cursive; font-size: 13px;\n line-height: 1.1; max-width: 240px; pointer-events: none;\n }\n .legend-tag {\n display:inline-block; padding: 1px 5px; border:1px solid var(--ink-3);\n border-radius: 8px; font-size: 9px; color: var(--ink-2); margin-right: 4px;\n }\n .legend-tag.code { font-family: inherit; background: var(--paper-2); color: var(--ink); border-color: var(--ink);}\n\n .section-title {\n font-family:\"Josefin Sans\",sans-serif; font-size: 14px; font-weight: 400;\n letter-spacing: 0.04em; border-bottom: 1px solid var(--ink);\n padding-bottom: 4px; margin: 28px 0 10px;\n }\n\n /* branching flow */\n .branches {\n display: flex; gap: 18px; flex-wrap: wrap;\n }\n\n /* keyboard legend chips inside frames */\n .kbd {\n display: inline-block;\n border: 1px solid var(--ink-3);\n border-radius: 3px;\n padding: 0 4px;\n font-size: 8px;\n color: var(--ink-2);\n background: var(--paper-2);\n }\n<\u002Fstyle>\n<\u002Fhead>\n<body>\n\n<div class=\"sheet\">\n <div class=\"titleblock\">\n <div>\n <h1>clide <em>— interaction & navigation flows<\u002Fem><\u002Fh1>\n <div style=\"font-size:11px;color:var(--ink-2);margin-top:6px;\">\n Eight flows extrapolated from the codebase · <b>only interactions actually wired\n in the current code<\u002Fb> · red notes cite the relevant file\n <\u002Fdiv>\n <\u002Fdiv>\n <div class=\"meta\">\n <div>sources · <b>app/lib/builtin/**<\u002Fb><\u002Fdiv>\n <div>dialog · <b>kernel/src/dialog.dart<\u002Fb><\u002Fdiv>\n <div>commands · <b>kernel/src/commands/*<\u002Fb><\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <p class=\"caption\">\n Each strip is a storyboard: left = state before, arrow = user event\n (keystroke, click, IPC event), right = resulting UI state. Frames reuse the\n classicPreset three-column shell drawn small; black hatches = regions that\n change, greyed content = inactive.\n <\u002Fp>\n\n <!-- =================================================================== -->\n <div class=\"flow\">\n <h2><span class=\"idx\">1<\u002Fspan>Cold start → open project<\u002Fh2>\n <p class=\"sub\">\n <code>_RootShell<\u002Fcode> boots, <code>DefaultLayoutExtension<\u002Fcode>\n applies <code>classicPreset<\u002Fcode>. Workspace shows the lowest-priority\n tab — <code>Welcome<\u002Fcode> (<code>priority: −100<\u002Fcode>). Clicking\n <b>Open project<\u002Fb> fires <code>workspace.open-project<\u002Fcode> command\n (today returns a stub \"project picker lands in a later tier\").\n <\u002Fp>\n\n <div class=\"frames\">\n <!-- Frame 1: boot -->\n <div class=\"frame\">\n <div class=\"cap\"><b>A<\u002Fb> · first paint, no project<\u002Fdiv>\n <div class=\"hdr\"><b>clide<\u002Fb><span>boot<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div>\n <div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv>\n <div style=\"color:var(--ink-3);\">(no workspace)<\u002Fdiv>\n <\u002Fdiv>\n <div>\n <div class=\"ws-tabs\"><b>Welcome<\u002Fb>·Diff·Editor·Claude·Terminal<\u002Fdiv>\n <div style=\"text-align:center; padding:20px 6px;\">\n <div style=\"font-family:'Josefin Sans',sans-serif; font-size:22px; font-weight:300;\">clide<\u002Fdiv>\n <div style=\"font-size:8px; color:var(--ink-3); margin: 4px 0 14px;\">Flutter desktop IDE for Claude Code<\u002Fdiv>\n <div style=\"display:inline-block; border:1px solid var(--ink); padding: 3px 10px; font-size:9px;\">Open project<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\">\n <div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv>\n <div style=\"color:var(--ink-3); padding-top: 4px;\">Open a file to see its links.<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"status\"><span class=\"plug bad\"><\u002Fspan>disconnected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\">\n <span class=\"tag\">click<\u002Fspan><br>\n \"Open project\"\n <\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <!-- Frame 2: daemon connects, picker -->\n <div class=\"frame\">\n <div class=\"cap\"><b>B<\u002Fb> · dialog-queue spot (stub)<\u002Fdiv>\n <div class=\"hdr\"><b>Welcome<\u002Fb><span>workspace.open-project<\u002Fspan><\u002Fdiv>\n <div class=\"mini mini-wrap\">\n <div style=\"opacity:0.45\">\n <div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv>\n <\u002Fdiv>\n <div style=\"opacity:0.45\">\n <div class=\"ws-tabs\"><b>Welcome<\u002Fb>·Diff·Editor·Claude·Terminal<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\" style=\"opacity:0.45\">\n <div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv>\n <\u002Fdiv>\n <div class=\"status\"><span class=\"plug bad\"><\u002Fspan>disconnected<\u002Fdiv>\n <div class=\"modal-backdrop\">\n <div class=\"modal\">\n <div class=\"t\">Open project…<\u002Fdiv>\n <div class=\"mrow sel\">~/code/clide <span class=\"kbd\">⏎<\u002Fspan><\u002Fdiv>\n <div class=\"mrow\">~/code/notes<\u002Fdiv>\n <div class=\"mrow\">~/code/pql<\u002Fdiv>\n <div class=\"mrow\" style=\"color:var(--ink-3);\">Browse…<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\">\n <span class=\"tag\">daemon.up<\u002Fspan><br>files.root\n <\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <!-- Frame 3: project loaded -->\n <div class=\"frame\">\n <div class=\"cap\"><b>C<\u002Fb> · project loaded, Claude attaches<\u002Fdiv>\n <div class=\"hdr\"><b>clide<\u002Fb> · ~/code/clide<span>connected<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div>\n <div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv>\n <div>▾ clide/<\u002Fdiv>\n <div style=\"padding-left:6px;\">▾ app/<\u002Fdiv>\n <div style=\"padding-left:12px;\">▸ lib/<\u002Fdiv>\n <div style=\"padding-left:12px;\">□ pubspec.yaml<\u002Fdiv>\n <div style=\"padding-left:6px;\">▸ lib/<\u002Fdiv>\n <div style=\"padding-left:6px;\">□ CLAUDE.md<\u002Fdiv>\n <\u002Fdiv>\n <div>\n <div class=\"ws-tabs\">Welcome·Diff·Editor·<b>Claude<\u002Fb>·Terminal<\u002Fdiv>\n <div class=\"term-block\" style=\"margin-top:2px;\">\n <div><span class=\"dim\">$<\u002Fspan> tmux new -A -s clide-claude-a1b7f3<\u002Fdiv>\n <div><span class=\"ok\">▌<\u002Fspan> attached<\u002Fdiv>\n <div>> <span style=\"background:#ededed; color:#111;\"> <\u002Fspan><\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\">\n <div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv>\n <div style=\"color:var(--ink-3);\">(no active file)<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected · main<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <!-- =================================================================== -->\n <div class=\"flow\">\n <h2><span class=\"idx\">2<\u002Fspan>Open a file from the tree<\u002Fh2>\n <p class=\"sub\">\n <code>FileTreeView._openFile<\u002Fcode> fires\n <code>kernel.ipc.request('editor.open', {path})<\u002Fcode>. The daemon emits\n <code>editor.active-changed<\u002Fcode>; <code>EditorController<\u002Fcode> hydrates\n the new buffer; <code>BacklinksController<\u002Fcode> listens for the same\n event and repopulates the <code>Links<\u002Fcode> tab. The Editor tab\n activates but the Claude pane (tmux-persisted per D-041) keeps running\n in the background.\n <\u002Fp>\n\n <div class=\"frames\">\n <div class=\"frame\">\n <div class=\"cap\"><b>A<\u002Fb> · Claude pane active, tree expanded<\u002Fdiv>\n <div class=\"hdr\"><b>claude<\u002Fb> — primary<span>tmux · pid 48021<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div>\n <div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv>\n <div>▾ lib/<\u002Fdiv>\n <div style=\"padding-left:6px;\">▾ builtin/<\u002Fdiv>\n <div style=\"padding-left:12px;\">▸ claude/<\u002Fdiv>\n <div style=\"padding-left:12px;\">▾ editor/<\u002Fdiv>\n <div style=\"padding-left:18px;\">□ editor_view.dart<\u002Fdiv>\n <div style=\"padding-left:12px;\">▸ files/<\u002Fdiv>\n <\u002Fdiv>\n <div>\n <div class=\"ws-tabs\">Welcome·Diff·Editor·<b>Claude<\u002Fb>·Terminal<\u002Fdiv>\n <div class=\"term-block\"><div><span class=\"ok\">▌<\u002Fspan> idle<\u002Fdiv><\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\">\n <div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv>\n <div style=\"color:var(--ink-3);\">(no active file)<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">click<\u002Fspan><br>editor_view.dart<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>B<\u002Fb> · ipc editor.open — waiting on hydrate<\u002Fdiv>\n <div class=\"hdr\"><b>editor<\u002Fb> — hydrating<span>editor.active-changed<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div>\n <div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv>\n <div style=\"padding-left:18px;\" class=\"selected\">□ editor_view.dart<\u002Fdiv>\n <\u002Fdiv>\n <div>\n <div class=\"ws-tabs\">Welcome·Diff·<b>Editor<\u002Fb>·Claude·Terminal<\u002Fdiv>\n <div style=\"background:#111; color:#ededed; font-family:'JetBrains Mono',monospace; font-size:8px; padding:4px; margin-top:2px;\">\n <div style=\"color:#8a8a82;\">loading buffer…<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\">\n <div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv>\n <div style=\"color:var(--ink-3);\">loading…<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>editor.open<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">event<\u002Fspan><br>editor.active-changed<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>C<\u002Fb> · buffer visible, backlinks refresh<\u002Fdiv>\n <div class=\"hdr\"><b>editor_view.dart<\u002Fb><span>saved<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div>\n <div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv>\n <div style=\"padding-left:18px;\" class=\"selected\">□ editor_view.dart<\u002Fdiv>\n <\u002Fdiv>\n <div>\n <div class=\"ws-tabs\">Welcome·Diff·<b>Editor<\u002Fb>·Claude·Terminal<\u002Fdiv>\n <div style=\"background:#111; color:#ededed; font-family:'JetBrains Mono',monospace; font-size:8px; padding:4px; margin-top:2px; line-height:1.4;\">\n <div>import 'package:flutter…<\u002Fdiv>\n <div> <\u002Fdiv>\n <div>class EditorView…<\u002Fdiv>\n <div> @override<\u002Fdiv>\n <div> Widget build(…<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\">\n <div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv>\n <div style=\"font-size:8px; color:var(--ink);\">editor_view.dart<\u002Fdiv>\n <div style=\"font-size:7px; color:var(--ink-3); margin-top:3px;\">Backlinks (2)<\u002Fdiv>\n <div style=\"font-size:8px;\">editor/extension.dart<\u002Fdiv>\n <div style=\"font-size:7px; color:var(--ink-3); margin-top:3px;\">Outlinks (3)<\u002Fdiv>\n <div style=\"font-size:8px;\">widgets/widgets.dart<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected · main<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <!-- =================================================================== -->\n <div class=\"flow\">\n <h2><span class=\"idx\">3<\u002Fspan>Command palette & theme picker (dialog)<\u002Fh2>\n <p class=\"sub\">\n Keystrokes flow through <code>_RootShell._onKey<\u002Fcode> →\n <code>KeybindingResolver<\u002Fcode> → <code>commands.execute<\u002Fcode>.\n <code>theme.pick<\u002Fcode> ships with <code>defaultBinding: 'ctrl+k'<\u002Fcode>;\n its <code>run()<\u002Fcode> pushes a dialog via <code>DialogRouter.show<\u002Fcode>,\n which <code>DialogHost<\u002Fcode> renders over a dimmed backdrop. One-at-a-time:\n a second <code>show<\u002Fcode> queues behind the first.\n <\u002Fp>\n\n <div class=\"frames\">\n <div class=\"frame\">\n <div class=\"cap\"><b>A<\u002Fb> · idle, any workspace tab<\u002Fdiv>\n <div class=\"hdr\"><b>editor_view.dart<\u002Fb><span>saved<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv>\n <div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><div class=\"ln sh\"><\u002Fdiv><\u002Fdiv>\n <div><div class=\"ws-tabs\">Welcome·Diff·<b>Editor<\u002Fb>·Claude·Terminal<\u002Fdiv>\n <div class=\"ln lg\"><\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">Ctrl+K<\u002Fspan><br>theme.pick<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>B<\u002Fb> · DialogHost backdrop + ThemePickerView<\u002Fdiv>\n <div class=\"hdr\"><b>dialog<\u002Fb> · theme.pick<span>router.show<String><\u002Fspan><\u002Fdiv>\n <div class=\"mini mini-wrap\">\n <div style=\"opacity:0.45\"><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><\u002Fdiv>\n <div style=\"opacity:0.45\"><div class=\"ws-tabs\">…·<b>Editor<\u002Fb>·…<\u002Fdiv><\u002Fdiv>\n <div class=\"cx\" style=\"opacity:0.45\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <div class=\"modal-backdrop\">\n <div class=\"modal\">\n <div class=\"t\">Select theme<\u002Fdiv>\n <div class=\"mrow sel\">✓ Summer Night <span class=\"k\">summer-night<\u002Fspan><\u002Fdiv>\n <div class=\"mrow\">Paper <span class=\"k\">paper<\u002Fspan><\u002Fdiv>\n <div class=\"mrow\">High contrast <span class=\"k\">high-contrast<\u002Fspan><\u002Fdiv>\n <div class=\"mrow\" style=\"justify-content:flex-end; border-top:1px dashed var(--ink-3); padding-top:4px;\">\n <span style=\"border:1px solid var(--ink); padding:0 5px;\">Cancel<\u002Fspan>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">select<\u002Fspan><br>or Esc<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>C<\u002Fb> · theme applied, dialog dismissed<\u002Fdiv>\n <div class=\"hdr\"><b>editor_view.dart<\u002Fb><span>theme → paper<\u002Fspan><\u002Fdiv>\n <div class=\"mini\" style=\"background:#fdfbf3;\">\n <div style=\"background:#f7f2e2;\"><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv>\n <div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div><div class=\"ws-tabs\">Welcome·Diff·<b>Editor<\u002Fb>·Claude·Terminal<\u002Fdiv>\n <div class=\"ln lg\"><\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div class=\"cx\" style=\"background:#f7f2e2;\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <p class=\"sub\" style=\"margin-top:14px;\">\n <b>Sibling flow:<\u002Fb> <code>PaletteController.toggle()<\u002Fcode> — same\n dialog-style overlay used for any registered command (not\n currently bound to a keystroke; scaffolded via\n <code>commands/palette.dart<\u002Fcode>).\n <\u002Fp>\n <\u002Fdiv>\n\n <!-- =================================================================== -->\n <div class=\"flow\">\n <h2><span class=\"idx\">4<\u002Fspan>Git flow — stage, commit, push<\u002Fh2>\n <p class=\"sub\">\n <code>GitController.load<\u002Fcode> hydrates <code>staged /\n unstaged / untracked / conflicted<\u002Fcode>. Row hover reveals <b>+ − x<\u002Fb>\n actions → <code>stage / unstage / discard<\u002Fcode>. Commit message input\n + <b>Commit<\u002Fb> button calls <code>commit(msg)<\u002Fcode>; returns a hash\n and clears the field. Clicking the <b>Diff<\u002Fb> tab of a modified file\n opens the workspace Diff view with <i>Unstaged ↔ Staged<\u002Fi> toggle.\n <\u002Fp>\n\n <div class=\"frames\">\n <div class=\"frame\">\n <div class=\"cap\"><b>A<\u002Fb> · Git tab — changes present<\u002Fdiv>\n <div class=\"hdr\"><b>Git<\u002Fb><span>main ↑2<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div style=\"font-size:8px; width:100%; grid-column: 1 / 3;\">\n <div class=\"sb-tabs\">Files·<b>Git<\u002Fb>·pql·Problems<\u002Fdiv>\n <div style=\"display:flex; justify-content:space-between;\">\n <span>main ↑2 ↓0<\u002Fspan>\n <span style=\"color:var(--ink-3);\">Pull · Push<\u002Fspan>\n <\u002Fdiv>\n <div style=\"color:var(--ink-3); margin-top:3px;\">Changes (3) · <u>Stage all<\u002Fu><\u002Fdiv>\n <div><span style=\"color:#2a6fc1; font-weight:700;\">M<\u002Fspan> editor_view.dart<\u002Fdiv>\n <div><span style=\"color:#2a6fc1; font-weight:700;\">M<\u002Fspan> claude_pane.dart<\u002Fdiv>\n <div><span style=\"color:#b03a2a; font-weight:700;\">D<\u002Fspan> stale_helper.dart<\u002Fdiv>\n <div style=\"color:var(--ink-3); margin-top:3px;\">Untracked (1) · <u>Stage all<\u002Fu><\u002Fdiv>\n <div><span style=\"color:#2d8a52; font-weight:700;\">?<\u002Fspan> notes/flows.md<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">click +<\u002Fspan><br>stage all<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>B<\u002Fb> · staged group + commit input<\u002Fdiv>\n <div class=\"hdr\"><b>Git<\u002Fb><span>staged: 4<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div style=\"font-size:8px; width:100%; grid-column: 1 / 3;\">\n <div class=\"sb-tabs\">Files·<b>Git<\u002Fb>·pql·Problems<\u002Fdiv>\n <div>main ↑2 ↓0<\u002Fdiv>\n <div style=\"color:var(--ink-3); margin-top:3px;\">Staged (4) · <u>Unstage all<\u002Fu><\u002Fdiv>\n <div><span style=\"color:#2a6fc1; font-weight:700;\">M<\u002Fspan> editor_view.dart<\u002Fdiv>\n <div><span style=\"color:#2a6fc1; font-weight:700;\">M<\u002Fspan> claude_pane.dart<\u002Fdiv>\n <div><span style=\"color:#b03a2a; font-weight:700;\">D<\u002Fspan> stale_helper.dart<\u002Fdiv>\n <div><span style=\"color:#2d8a52; font-weight:700;\">A<\u002Fspan> notes/flows.md<\u002Fdiv>\n <div style=\"border:1px solid var(--ink); padding: 3px; margin-top: 4px; min-height: 18px;\">\n <span style=\"color:var(--ink);\">flows: first pass on editor + claude<\u002Fspan><span style=\"background:var(--ink); display:inline-block; width:1px; height:10px; margin-left:1px;\"><\u002Fspan>\n <\u002Fdiv>\n <div style=\"margin-top:3px; text-align:right;\"><span style=\"border:1px solid var(--ink); padding: 1px 6px;\">Commit<\u002Fspan><\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">⏎<\u002Fspan><br>commit()<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>C<\u002Fb> · clean tree, Diff tab can be opened<\u002Fdiv>\n <div class=\"hdr\"><b>Diff<\u002Fb> · Unstaged<span>0 files<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div>\n <div class=\"sb-tabs\">Files·<b>Git<\u002Fb>·pql·Problems<\u002Fdiv>\n <div style=\"color:var(--ink-3);\">Nothing to commit,<\u002Fdiv>\n <div style=\"color:var(--ink-3);\">working tree clean.<\u002Fdiv>\n <div>main ↑3 ↓0<\u002Fdiv>\n <\u002Fdiv>\n <div>\n <div class=\"ws-tabs\">Welcome·<b>Diff<\u002Fb>·Editor·Claude·Terminal<\u002Fdiv>\n <div style=\"font-size:8px; color:var(--ink);\"><u>Unstaged<\u002Fu> · <span style=\"color:var(--ink-3);\">Staged<\u002Fspan><\u002Fdiv>\n <div style=\"color:var(--ink-3); margin-top: 10px;\">No unstaged changes.<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected · main ↑3<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <!-- =================================================================== -->\n <div class=\"flow\">\n <h2><span class=\"idx\">5<\u002Fspan>Claude — primary vs secondary pane (D-041)<\u002Fh2>\n <p class=\"sub\">\n <b>Primary<\u002Fb> (<code>isPrimary: true<\u002Fcode>): session name stable per\n repo (<code>clide-claude-<hash><\u002Fcode>), <b>no close button<\u002Fb>, \"close\"\n just minimizes. Re-opening re-attaches via <code>tmux new -A<\u002Fcode>.\n <b>Secondary<\u002Fb>: spawned by <code>claude.new-secondary<\u002Fcode>, session\n name has <code>-N<\u002Fcode> suffix, tab <code>×<\u002Fcode> kills the tmux session.\n Fallback when tmux is missing: bare <code>claude<\u002Fcode> spawn,\n subtitle reads <code>no-tmux · fresh every launch<\u002Fcode>.\n <\u002Fp>\n\n <div class=\"frames\">\n <div class=\"frame\">\n <div class=\"cap\"><b>A<\u002Fb> · primary only, no ×<\u002Fdiv>\n <div class=\"hdr\"><b>claude — primary<\u002Fb><span>tmux · clide-claude-a1b7<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><\u002Fdiv>\n <div>\n <div class=\"ws-tabs\">Welcome·Diff·Editor·<b>Claude<\u002Fb>·Terminal<\u002Fdiv>\n <div class=\"term-block\">\n <div><span class=\"ok\">▌<\u002Fspan> primary<\u002Fdiv>\n <div class=\"dim\">no-close button · close ⇒ hide<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>pid 48021<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">cmd<\u002Fspan><br>claude.new-secondary<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>B<\u002Fb> · new tab opens with ×<\u002Fdiv>\n <div class=\"hdr\"><b>claude — secondary 1<\u002Fb><span>tmux · …a1b7-1 · pid 48203<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><\u002Fdiv>\n <div>\n <div class=\"ws-tabs\" style=\"font-size:7px;\">…·Claude·<b>Claude-2 ×<\u002Fb>·Terminal<\u002Fdiv>\n <div class=\"term-block\">\n <div><span class=\"ok\">▌<\u002Fspan> secondary<\u002Fdiv>\n <div class=\"dim\">× kills tmux session<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>pid 48203<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">× click<\u002Fspan><br>pane.close<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>C<\u002Fb> · back to primary, session killed<\u002Fdiv>\n <div class=\"hdr\"><b>claude — primary<\u002Fb><span>tmux · clide-claude-a1b7<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><\u002Fdiv>\n <div>\n <div class=\"ws-tabs\">…·<b>Claude<\u002Fb>·Terminal<\u002Fdiv>\n <div class=\"term-block\">\n <div><span class=\"ok\">▌<\u002Fspan> primary<\u002Fdiv>\n <div class=\"dim\">(secondary gone)<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>pid 48021<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <!-- =================================================================== -->\n <div class=\"flow\">\n <h2><span class=\"idx\">6<\u002Fspan>Daemon disconnect & reconnect<\u002Fh2>\n <p class=\"sub\">\n <code>IpcStatusItem<\u002Fcode> subscribes to <code>DaemonClient<\u002Fcode> and\n repaints on every <code>isConnected<\u002Fcode> flip. Panes that depend on IPC\n (<code>ClaudePane._spawn<\u002Fcode>, <code>TerminalPane._spawn<\u002Fcode>,\n controllers) display an inline error state and degrade to read-only.\n <\u002Fp>\n\n <div class=\"frames\">\n <div class=\"frame\">\n <div class=\"cap\"><b>A<\u002Fb> · running normally<\u002Fdiv>\n <div class=\"hdr\"><b>claude — primary<\u002Fb><span>tmux · pid 48021<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div><div class=\"ws-tabs\">…·<b>Claude<\u002Fb>·…<\u002Fdiv><div class=\"term-block\"><div><span class=\"ok\">▌<\u002Fspan> ok<\u002Fdiv><\u002Fdiv><\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">socket<\u002Fspan><br>EOF<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>B<\u002Fb> · controllers surface error<\u002Fdiv>\n <div class=\"hdr\" style=\"color:var(--err);\"><b>claude — primary<\u002Fb><span>daemon offline<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><div style=\"color:var(--ink-3);\">(stale)<\u002Fdiv><\u002Fdiv>\n <div><div class=\"ws-tabs\">…·<b>Claude<\u002Fb>·…<\u002Fdiv>\n <div style=\"background:#fff2e6; border:1px dashed var(--err); color:var(--err); padding:3px; font-size:8px;\">\n Daemon not connected. Start <code>clide --daemon<\u002Fcode>.\n <\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><div style=\"color:var(--ink-3);\">stale<\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug bad\"><\u002Fspan>disconnected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">daemon.up<\u002Fspan><br>reattach<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>C<\u002Fb> · primary tmux still alive → resumed<\u002Fdiv>\n <div class=\"hdr\"><b>claude — primary<\u002Fb><span>tmux · pid 48021<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div><div class=\"ws-tabs\">…·<b>Claude<\u002Fb>·…<\u002Fdiv><div class=\"term-block\"><div class=\"dim\">(replayed scrollback)<\u002Fdiv><div><span class=\"ok\">▌<\u002Fspan> resumed<\u002Fdiv><\u002Fdiv><\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <!-- =================================================================== -->\n <div class=\"flow\">\n <h2><span class=\"idx\">7<\u002Fspan>pql sidebar — switching sub-views<\u002Fh2>\n <p class=\"sub\">\n <code>PqlPanelView<\u002Fcode> hosts an in-panel view-tab strip:\n <code>Files · Query · Decisions · Tickets<\u002Fcode>. Switching calls\n <code>controller.switchView()<\u002Fcode>; <b>Query<\u002Fb> adds a DSL input\n (submit runs <code>pql<\u002Fcode> via IPC); <b>Decisions<\u002Fb> colors the id by\n <code>type<\u002Fcode> (confirmed/question/rejected); <b>Tickets<\u002Fb> groups\n rows by status into kanban columns.\n <\u002Fp>\n\n <div class=\"frames\">\n <div class=\"frame\">\n <div class=\"cap\"><b>A<\u002Fb> · Files view (default)<\u002Fdiv>\n <div class=\"hdr\"><b>pql<\u002Fb><span>view: files<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div style=\"width:100%; grid-column: 1 / 3;\">\n <div class=\"sb-tabs\">Files·Git·<b>pql<\u002Fb>·Problems<\u002Fdiv>\n <div style=\"font-size:8px; border-bottom:1px dashed var(--ink-3); padding-bottom:2px;\"><b>Files<\u002Fb>·Query·Decisions·Tickets<\u002Fdiv>\n <div>app.dart<\u002Fdiv>\n <div>main.dart<\u002Fdiv>\n <div>lib/app.dart<\u002Fdiv>\n <div>README.md<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">click<\u002Fspan><br>Decisions<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>B<\u002Fb> · Decisions — id colored by type<\u002Fdiv>\n <div class=\"hdr\"><b>pql<\u002Fb><span>view: decisions<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div style=\"width:100%; grid-column: 1 / 3;\">\n <div class=\"sb-tabs\">Files·Git·<b>pql<\u002Fb>·Problems<\u002Fdiv>\n <div style=\"font-size:8px; border-bottom:1px dashed var(--ink-3); padding-bottom:2px;\">Files·Query·<b>Decisions<\u002Fb>·Tickets<\u002Fdiv>\n <div style=\"display:flex; gap:4px;\"><span style=\"color:#2d8a52; width:28px;\">D-041<\u002Fspan><span>tmux-persist primary<\u002Fspan><span style=\"color:var(--ink-3);\">claude<\u002Fspan><\u002Fdiv>\n <div style=\"display:flex; gap:4px;\"><span style=\"color:#2d8a52; width:28px;\">D-007<\u002Fspan><span>no Material<\u002Fspan><span style=\"color:var(--ink-3);\">ui<\u002Fspan><\u002Fdiv>\n <div style=\"display:flex; gap:4px;\"><span style=\"color:#b0821f; width:28px;\">Q-022<\u002Fspan><span>ticket persistence<\u002Fspan><span style=\"color:var(--ink-3);\">tickets<\u002Fspan><\u002Fdiv>\n <div style=\"display:flex; gap:4px;\"><span style=\"color:#b03a2a; width:28px;\">D-014<\u002Fspan><span>Riverpod (rejected)<\u002Fspan><span style=\"color:var(--ink-3);\">deps<\u002Fspan><\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">click<\u002Fspan><br>Tickets<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>C<\u002Fb> · Tickets — grouped by status<\u002Fdiv>\n <div class=\"hdr\"><b>pql<\u002Fb><span>view: tickets<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div style=\"width:100%; grid-column: 1 / 3;\">\n <div class=\"sb-tabs\">Files·Git·<b>pql<\u002Fb>·Problems<\u002Fdiv>\n <div style=\"font-size:8px; border-bottom:1px dashed var(--ink-3); padding-bottom:2px;\">Files·Query·Decisions·<b>Tickets<\u002Fb><\u002Fdiv>\n <div style=\"color:var(--ink-3); margin-top:3px;\">in-progress (2)<\u002Fdiv>\n <div><span style=\"color:#2a6fc1;\">T-113<\u002Fspan> flows wireframe pass<\u002Fdiv>\n <div><span style=\"color:#2a6fc1;\">T-119<\u002Fspan> diff hunk stage<\u002Fdiv>\n <div style=\"color:var(--ink-3); margin-top:3px;\">todo (3)<\u002Fdiv>\n <div><span style=\"color:#2a6fc1;\">T-120<\u002Fspan> keybindings ui<\u002Fdiv>\n <\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <!-- =================================================================== -->\n <div class=\"flow\">\n <h2><span class=\"idx\">8<\u002Fspan>Drag-resize & toggle slots<\u002Fh2>\n <p class=\"sub\">\n <code>DragResizeHandle<\u002Fcode> writes the new size into\n <code>arrangement.setSize(slot, size)<\u002Fcode> (clamped to the preset's\n min/max). Toggling visibility via <code>arrangement.setVisibility<\u002Fcode>\n collapses/expands a whole column while the others flex. No code path\n opens a secondary-row split today; the grid is strictly\n <i>sidebar | workspace | context<\u002Fi>.\n <\u002Fp>\n\n <div class=\"frames\">\n <div class=\"frame\">\n <div class=\"cap\"><b>A<\u002Fb> · default 240 / flex / 280<\u002Fdiv>\n <div class=\"hdr\"><b>layout<\u002Fb><span>classicPreset<\u002Fspan><\u002Fdiv>\n <div class=\"mini\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div><div class=\"ws-tabs\">…·<b>Editor<\u002Fb>·…<\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">drag<\u002Fspan><br>sidebar → 340<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>B<\u002Fb> · sidebar wider, workspace yields<\u002Fdiv>\n <div class=\"hdr\"><b>layout<\u002Fb><span>sidebar: 340<\u002Fspan><\u002Fdiv>\n <div class=\"mini\" style=\"grid-template-columns: 90px 1fr 58px;\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div><div class=\"ws-tabs\">…·<b>Editor<\u002Fb>·…<\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div class=\"cx\"><div class=\"cx-tabs\"><b>Links<\u002Fb><\u002Fdiv><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <div class=\"arrow-row\">\n <div class=\"lbl\"><span class=\"tag\">cmd<\u002Fspan><br>hide context<\u002Fdiv>\n <svg width=\"50\" height=\"20\"><path d=\"M0 10 L46 10 M40 5 L50 10 L40 15\" stroke=\"#c14b2a\" stroke-width=\"1.5\" fill=\"none\"><\u002Fpath><\u002Fsvg>\n <\u002Fdiv>\n\n <div class=\"frame\">\n <div class=\"cap\"><b>C<\u002Fb> · context collapsed, workspace fills<\u002Fdiv>\n <div class=\"hdr\"><b>layout<\u002Fb><span>context: hidden<\u002Fspan><\u002Fdiv>\n <div class=\"mini\" style=\"grid-template-columns: 90px 1fr 0px;\">\n <div><div class=\"sb-tabs\"><b>Files<\u002Fb>·Git·pql·Problems<\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div><div class=\"ws-tabs\">…·<b>Editor<\u002Fb>·…<\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln lg\"><\u002Fdiv><div class=\"ln md\"><\u002Fdiv><\u002Fdiv>\n <div class=\"cx\" style=\"border-left:0; padding:0;\"><\u002Fdiv>\n <div class=\"status\"><span class=\"plug\"><\u002Fspan>connected<\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n <\u002Fdiv>\n\n <!-- =================================================================== -->\n <div class=\"section-title\">Event model · legend<\u002Fdiv>\n <div class=\"states\">\n <div>\n <h3>User events (app.dart)<\u002Fh3>\n <ul>\n <li><span class=\"legend-tag code\">KeyEvent<\u002Fspan> → <code>KeybindingResolver<\u002Fcode> → <code>commands.execute<\u002Fcode><\u002Fli>\n <li><span class=\"legend-tag code\">Tap<\u002Fspan> → <code>panels.activateTab<\u002Fcode> / <code>ipc.request<\u002Fcode><\u002Fli>\n <li><span class=\"legend-tag code\">Drag<\u002Fspan> → <code>arrangement.setSize<\u002Fcode><\u002Fli>\n <\u002Ful>\n <\u002Fdiv>\n <div>\n <h3>Daemon events (pane.*)<\u002Fh3>\n <ul>\n <li><code>pane.output<\u002Fcode> → xterm.write()<\u002Fli>\n <li><code>pane.exit<\u002Fcode> → status line updates<\u002Fli>\n <li><code>pane.closed<\u002Fcode> → pane id cleared<\u002Fli>\n <li><code>files.changed<\u002Fcode> → file tree refresh<\u002Fli>\n <li><code>editor.active-changed<\u002Fcode> → editor + backlinks rehydrate<\u002Fli>\n <\u002Ful>\n <\u002Fdiv>\n <div>\n <h3>Dialog (dialog.dart)<\u002Fh3>\n <ul>\n <li><code>DialogRouter.show<T><\u002Fcode> — returns <code>Future<T?><\u002Fcode><\u002Fli>\n <li>one-at-a-time; subsequent <code>show<\u002Fcode> queues<\u002Fli>\n <li>dismiss with result → completer completes → caller resumes<\u002Fli>\n <li>rendered by <code>DialogHost<\u002Fcode> over dimmed backdrop<\u002Fli>\n <\u002Ful>\n <\u002Fdiv>\n <div>\n <h3>Flows not yet in code<\u002Fh3>\n <ul>\n <li>Project picker — <code>workspace.open-project<\u002Fcode> stub<\u002Fli>\n <li>Multi-buffer editor tabs (single-buffer today)<\u002Fli>\n <li>Toolbar slot UI — slot reserved, no renderer<\u002Fli>\n <li>Command palette keybinding — controller exists, not bound<\u002Fli>\n <li>Keybindings / Settings / Extensions panels — stubs<\u002Fli>\n <\u002Ful>\n <\u002Fdiv>\n <\u002Fdiv>\n\n<\u002Fdiv>\n\n\n<\u002Fbody><\u002Fhtml>"
|
||
</script>
|
||
</body>
|
||
</html> |