---
description: the chat loop page (Door B on a hero Home, Help:ChatLoop): paste start loop into your AI's chat, then watch the loop connect live and open the pad. A signed base d2 Page, so it reads the person's agents (razie, chat 6acbe2fd, 2026-10-11: "so make this page the way it sould be")
tags: page, onboarding, chat
---
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="light dark">
<title>Upgrade to a chat loop</title>
<style>
:root{--paper:#fbfaf7;--card:#ffffff;--ink:#1d1d1b;--soft:#6b6a66;--line:#e4e1da;--blue:#185FA5;--blue2:#378ADD;--ok:#3B6D11;--ok2:#639922}
@media (prefers-color-scheme:dark){:root{--paper:#141413;--card:#1d1d1b;--ink:#ecebe6;--soft:#9c9a93;--line:#33322f;--blue2:#5aa2ea;--ok:#5f9e36;--ok2:#7fbf4a}}
*{box-sizing:border-box}
body{margin:0;background:var(--paper);color:var(--ink);font:calc(16px*var(--fz,1))/1.5 system-ui,-apple-system,'Segoe UI',sans-serif}
main{max-width:720px;margin:0 auto;padding:18px 16px 40px}
h1{font-size:calc(28px*var(--fz,1));line-height:1.15;margin:6px 0 6px}
h2{font-size:calc(18px*var(--fz,1));margin:22px 0 8px}
p{margin:6px 0}
.soft{color:var(--soft)}.small{font-size:calc(13px*var(--fz,1))}
ul.pts{margin:8px 0 0;padding-left:20px}ul.pts li{margin:3px 0}
.steps{display:flex;flex-direction:column;gap:10px}
.step{border:1px solid var(--line);border-radius:12px;padding:12px 14px;background:var(--card)}
.step.now{border:2px solid var(--blue2)}
.step.done{border:2px solid var(--ok2)}
.step h3{font-size:calc(15px*var(--fz,1));font-weight:600;margin:0;display:flex;align-items:center;gap:10px;min-height:28px}
.n{flex:none;width:28px;height:28px;border-radius:50%;background:var(--blue);color:#fff;display:inline-flex;align-items:center;justify-content:center;font-size:15px}
.step:not(.now):not(.done) .n{background:color-mix(in srgb,var(--ink) 35%,transparent)}
.step.done .n{background:var(--ok)}
.code{display:flex;gap:8px;align-items:center;margin-top:8px}
.code pre{flex:1;margin:0;padding:8px 10px;border-radius:8px;background:color-mix(in srgb,var(--ink) 7%,transparent);font:calc(15px*var(--fz,1))/1.45 ui-monospace,Menlo,Consolas,monospace}
button,.btn{font:inherit;font-size:calc(14px*var(--fz,1));padding:7px 14px;border-radius:9px;border:1px solid currentColor;background:transparent;color:inherit;cursor:pointer;text-decoration:none;display:inline-block}
.btn.go{background:var(--blue);border-color:var(--blue);color:#fff}
.btn.go[aria-disabled="true"]{background:color-mix(in srgb,var(--ink) 18%,transparent);border-color:transparent;color:var(--soft);cursor:not-allowed}
.w{display:flex;gap:10px;align-items:center;margin:10px 0}
.dot{width:10px;height:10px;border-radius:50%;background:#9aa0a6;flex:none}
.dot.on{background:var(--ok2);box-shadow:0 0 0 3px color-mix(in srgb,var(--ok2) 25%,transparent)}
a{color:var(--blue2)}
</style></head><body><main>
<h1>Upgrade to a chat loop</h1>
<p class="soft">Today you talk to your AI in its own app. In a chat loop it <i>stays on d2</i> and answers you in the chat panel, beside the page you're looking at.</p>
<ul class="pts">
<li><b>Where you talk:</b> the chat panel on every d2 page.</li>
<li><b>How it asks you things:</b> TurboChat. Its options come as a pad: tap to pick, one <b>CONTINUE</b> sends your answer.</li>
<li><b>While it runs:</b> your AI's app stays open (computer or phone); it uses your AI as usual, only while you chat.</li>
<li><b>Stop any time:</b> type <i>stop loop</i> in that chat, or close it.</li>
</ul>
<h2>Set it up: two steps</h2>
<div class="steps">
<div class="step now" id="s1"><h3><span class="n">1</span>Paste this into the chat with your AI</h3>
<p>The same AI chat you already use for this project (Claude on your desktop, web or phone).</p>
<div class="code"><pre id="prompt">start loop</pre><button id="copy">Copy</button></div>
<p class="small soft">Your AI answers <i>Loop on: I'm listening on d2</i> and keeps that chat open. Leave it running. Not connected yet? Do <b>Onboard your AI</b> on <a href="/" data-go="/">your home page</a> first.</p></div>
<div class="step" id="s2"><h3><span class="n">2</span>Say hello here</h3>
<div class="w"><span class="dot" id="dot"></span><span id="st">Waiting for your AI's loop… this lights up when it's listening.</span></div>
<p class="small soft">Then say hello in the chat panel, bottom right, or open the pad: your AI answers in a few seconds.</p>
<a class="btn go" id="pad" href="/pad" aria-disabled="true" title="Lights up when your AI's loop is listening">Open the pad →</a></div>
</div>
<h2>If it doesn't connect</h2>
<ul class="pts">
<li>No light after a minute: check your AI's chat says <i>Loop on</i>. If it doesn't, paste <i>start loop</i> again.</li>
<li>Your AI says it can't: it isn't connected to this project yet. Do <b>Onboard your AI</b> on your home page first.</li>
<li>Rather type in your AI's own app? <a href="/topics/Help:WorkWithYourPrompt" data-go="/topics/Help:WorkWithYourPrompt">Keep using your prompt</a>. More: <a href="/topics/Help:ChatLoop" data-go="/topics/Help:ChatLoop">Help: chat loop</a>.</li>
</ul>
</main>
<script>
(()=>{const D2=window.d2||{},$=id=>document.getElementById(id);
const api=(m,u,b)=>D2.api?Promise.resolve(D2.api(m,u,b)):Promise.reject(new Error("open this page in d2"));
const go=u=>D2.go?D2.go(u):(location.href=u);
document.addEventListener("click",e=>{const a=e.target.closest&&e.target.closest("a[data-go]");if(!a)return;e.preventDefault();go(a.dataset.go)});
$("copy").onclick=async()=>{const b=$("copy");try{await navigator.clipboard.writeText($("prompt").innerText);b.textContent="Copied"}catch(_){const r=document.createRange();r.selectNodeContents($("prompt"));const s=getSelection();s.removeAllRanges();s.addRange(r);b.textContent="Selected: copy it"}};
$("pad").addEventListener("click",e=>{e.preventDefault();if($("pad").getAttribute("aria-disabled")!=="true")go("/pad")});
// the loop is live when one of the person's agents says "Loop on" in its status text (Skill:d3-r-maker / d3-r-designer #wf-loop) and isn't gone or done; every 5 s, in place
let lit=false;
const poll=async()=>{try{const a=await api("GET","/api/v2/agents");const rows=(a&&(a.data||a.agents))||[];
const l=rows.find(s=>/^loop on/i.test(String(s.text||""))&&!["gone","done","stopped"].includes(s.state));
if(l&&!lit){lit=true;$("dot").classList.add("on");$("st").textContent=(l.agent||"Your AI")+" is listening: say hello.";$("pad").setAttribute("aria-disabled","false");$("pad").title="";$("s1").classList.replace("now","done");$("s2").classList.add("now")}
else if(!l&&lit){lit=false;$("dot").classList.remove("on");$("st").textContent="Your AI's loop stopped. Paste start loop again to restart it.";$("pad").setAttribute("aria-disabled","true");$("s1").classList.replace("done","now");$("s2").classList.remove("now")}
}catch(_){}};
poll();setInterval(poll,5000);
})();
</script>
</body></html>