[object Object]

← back to Model Arena

model-arena: multi-select checkboxes for challenge-level iTerm2 build launcher

3be6fd20ab116a629a28c3f5b3d2072822ecc1ca · 2026-09-23 16:10:24 -0700 · Steve Abrams

Convert #d-build-pick from single-select <select> to checkboxes so multiple
models' artifacts can each launch their own independent iTerm2 Claude window
+ landing page in one click. Verified the existing per-model retry (data-retry,
guarded server-side against adding models outside the battle) is unchanged
and already correct.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01166faVcwiztzWqhHwD9yer

Files touched

Diff

commit 3be6fd20ab116a629a28c3f5b3d2072822ecc1ca
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 23 16:10:24 2026 -0700

    model-arena: multi-select checkboxes for challenge-level iTerm2 build launcher
    
    Convert #d-build-pick from single-select <select> to checkboxes so multiple
    models' artifacts can each launch their own independent iTerm2 Claude window
    + landing page in one click. Verified the existing per-model retry (data-retry,
    guarded server-side against adding models outside the battle) is unchanged
    and already correct.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01166faVcwiztzWqhHwD9yer
---
 public/index.html | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/public/index.html b/public/index.html
index 8992d9c..a5ef6ca 100644
--- a/public/index.html
+++ b/public/index.html
@@ -96,6 +96,10 @@ input[type=range]{accent-color:var(--neon);width:130px}
 .model-tools .count{margin-left:auto;color:var(--dim);font-size:11px}
 .mrow{display:flex;align-items:center;gap:8px;border:1px solid var(--line);padding:8px 10px;font-size:12px}
 .mrow.dtd{border-color:#6b4da1;background:rgba(160,107,255,.05)}
+.build-picks{display:inline-flex;flex-wrap:wrap;gap:6px;align-items:center}
+.build-picks label{display:inline-flex;align-items:center;gap:4px;border:1px solid var(--line);padding:3px 9px;border-radius:3px;font-size:11px;color:var(--dim);cursor:pointer;white-space:nowrap}
+.build-picks label:has(input:checked){border-color:var(--neon2);color:var(--txt)}
+.build-picks input{accent-color:var(--neon2)}
 .dtdb{font-size:9px;padding:1px 5px;border:1px solid #a06bff;color:#c8a6ff;border-radius:3px;letter-spacing:1px}
 .mrow.off{opacity:.45}
 .mrow .cost{margin-left:auto;font-size:11px}
@@ -241,10 +245,11 @@ input[type=range]{accent-color:var(--neon)}
 .form textarea{height:150px}.presets{margin:4px 0 18px}.pcat{margin-top:12px;color:#8a94a3;font-weight:750;text-transform:uppercase}.preset{border-color:#d5dce6;border-radius:8px;background:#f7f9fb;color:#48576b;padding:6px 10px}.preset:hover{border-color:#9cb1d2;background:#f0f5fd}
 .model-tools{margin:22px 0 12px;padding-top:20px;border-top:1px solid var(--line)}.model-tools .count{font-weight:650}
 .models{grid-template-columns:repeat(auto-fill,minmax(245px,1fr));gap:10px}.mrow{min-height:50px;border-color:#e0e4e9;border-radius:10px;background:#fafbfc;padding:10px 12px}.mrow.dtd{border-color:#cdd9ed;background:#f4f7fc}.mrow.off{filter:saturate(.2);opacity:.55}.mrow input{accent-color:#245dbf}.dtdb{border-color:#9db5de;border-radius:4px;color:#315f9f}.hfb{border-color:#c7a76a;color:#8c681f}.note{color:#7a8492;font-size:12px}.blindtog{color:#667286}.blindtog input{accent-color:#245dbf}
+.build-picks label{border-color:#e0e4e9;border-radius:7px;background:#fafbfc}.build-picks label:has(input:checked){border-color:#194fae;background:#edf3ff;color:#194fae}.build-picks input{accent-color:#194fae}
 #f-go{min-width:150px;background:var(--navy);border-color:var(--navy);color:#fff;padding:12px 22px}
 .back{color:#315f9f;font-family:"Avenir Next",sans-serif;font-weight:650}.arena{gap:20px}.pane{border:1px solid var(--line);border-radius:15px;background:#fff;box-shadow:0 2px 8px rgba(15,23,42,.05);overflow:hidden}.pane .bar{min-height:52px;padding:10px 14px;border-color:var(--line);background:#fbfcfd}.pane .bar .name{color:var(--ink)}.pane.winner{border-color:#d8b76f;box-shadow:0 0 0 3px rgba(214,174,90,.13),0 18px 42px rgba(15,23,42,.1)}.pane.winner .bar{background:#fff9ed}.pane iframe,.poster,.pane .msg{height:500px}.aibar{padding:12px 15px;border:1px solid #d7e0ee;border-left:3px solid #3d72c7;border-radius:10px;background:#f2f6fc;color:#526177}.aibar b,.aiscore{color:#244f91}.aireason{border-color:var(--line);background:#fbfcfd;color:#6e7887}
 .detail-actions{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:10px;padding:11px;border:1px solid var(--line);border-radius:13px;background:#fff;box-shadow:0 1px 3px rgba(15,23,42,.04)}
-.detail-actions .back{margin:0!important;padding:7px 8px}.detail-actions .btn{margin:0!important}.detail-actions #d-buildbar{display:flex;gap:7px;margin:0!important}.detail-actions #d-buildbar[hidden]{display:none}
+.detail-actions .back{margin:0!important;padding:7px 8px}.detail-actions .btn{margin:0!important}.detail-actions #d-buildbar{display:flex;flex-wrap:wrap;align-items:center;gap:7px;margin:0!important}.detail-actions #d-buildbar[hidden]{display:none}
 table{border-collapse:separate;border-spacing:0;border:1px solid var(--line);border-radius:14px;background:#fff;overflow:hidden;box-shadow:0 2px 8px rgba(15,23,42,.035)}th{background:#f6f8fa;color:#6d7785;font-weight:800}th,td{padding:13px 14px;border-color:#e8ebef}tr.clk:hover td{background:#f3f7fd}tr.first td{color:#76501c;background:#fffbf2}
 .gcard{border-color:var(--line);border-radius:14px;background:#fff;overflow:hidden;box-shadow:0 2px 8px rgba(15,23,42,.04)}.gcard:hover{border-color:#aab7c8}.gcard .gm .gt{color:var(--ink)}
 .seed{border-color:var(--line);border-radius:9px;background:#fff}.champ{border-color:#d8b76f;border-radius:14px;background:#fff9ed;box-shadow:none}.srcview{background:#101827;color:#bcd0ed}
@@ -333,8 +338,8 @@ table{border-collapse:separate;border-spacing:0;border:1px solid var(--line);bor
     <a class="back" id="export" style="margin-left:16px" download>⬇ export battle as standalone HTML</a>
     <button class="btn pink" id="rerun-all" style="margin-left:16px" title="Re-run EVERY model in this battle from scratch (re-spends any metered models)">↻ Re-run entire challenge</button>
     <span id="d-buildbar" hidden>
-      <select id="d-build-pick" class="btn" title="Pick which model's artifact to build inside an iTerm2 Claude session"></select>
-      <button class="btn pink" id="d-build-go" title="Open an iTerm2 Claude session and build the selected model's artifact into a real project">⚒ Build in iTerm2</button>
+      <span id="d-build-picks" class="build-picks" title="Check every model whose artifact you want built — EACH checked model gets its OWN independent iTerm2 Claude window + its own landing page"></span>
+      <button class="btn pink" id="d-build-go" title="Launch one independent iTerm2 Claude session + landing page for EACH checked model">⚒ Build in iTerm2</button>
     </span>
     <button class="btn" id="d-continue" style="margin-left:16px" title="Start another battle — jump to the New Battle form">⚔ Continue with battles</button>
     </div>
@@ -587,13 +592,29 @@ async function renderDetail(id, statusOnly){
   }
   // Challenge-level iTerm2 build — pick which model's artifact to build INSIDE a Claude session
   const doneRuns = c.runs.filter(r=>r.status==='done');
-  const bbar=$('#d-buildbar'), bpick=$('#d-build-pick'), bgo=$('#d-build-go');
+  const bbar=$('#d-buildbar'), bpicks=$('#d-build-picks'), bgo=$('#d-build-go');
   if (bbar){
     if (doneRuns.length){
       bbar.hidden=false;
       const def = c.winner || c.aiPick || doneRuns[0].model;
-      bpick.innerHTML = doneRuns.map(r=>`<option value="${r.model}"${r.model===def?' selected':''}>${mLabel(r.model)}${r.model===c.winner?' 👑':(r.model===c.aiPick?' 🤖':'')}</option>`).join('');
-      bgo.onclick = ()=> buildInIterm(current.id, bgo, bpick.value);
+      // checkboxes, not a single-select — check ANY number of models and each
+      // gets its own independent iTerm2 Claude window + its own landing page
+      bpicks.innerHTML = doneRuns.map(r=>`<label title="${mLabel(r.model)} — its own iTerm2 window + landing page"><input type="checkbox" value="${r.model}"${r.model===def?' checked':''}> ${mLabel(r.model)}${r.model===c.winner?' 👑':(r.model===c.aiPick?' 🤖':'')}</label>`).join('');
+      const updateBuildGo = ()=>{
+        const n = bpicks.querySelectorAll('input:checked').length;
+        bgo.textContent = n>1 ? `⚒ Build ${n} in iTerm2 (${n} windows)` : '⚒ Build in iTerm2';
+        bgo.disabled = n===0;
+      };
+      bpicks.onchange = updateBuildGo;
+      updateBuildGo();
+      bgo.onclick = async ()=>{
+        const ids = [...bpicks.querySelectorAll('input:checked')].map(i=>i.value);
+        if (!ids.length) return;
+        bgo.disabled = true;
+        // each model launches its OWN iTerm2 window + landing page, independently
+        for (const id of ids) await buildInIterm(current.id, bgo, id);
+        bgo.disabled = false;
+      };
     } else { bbar.hidden=true; }
   }
   // Continue with battles — jump to the New Battle form (mirrors the + New Battle nav)

← 6e3695c auto-data-snapshot: 2026-09-23T15:52:37 (1 data files) — dat  ·  back to Model Arena  ·  Build 'The Form to Request a Form' satire strip from minicpm 6a61a4b →