{# One project row. Rendered by the dashboard grid loop AND by
GET /api/projects/{name}/row for reactive insertion (no full-page reload). `idx` is
the row's position for the search/cap visibility gate (0 from the fragment route, so a
freshly created project is always shown).
The `:style` below reorders rows VISUALLY for a non-name sort via CSS `order` — it does
NOT change DOM/tab order (focus + screen-reader order stay A–Z), the deliberate trade for
an opt-in cosmetic sort. Don't turn this into a DOM reorder (the anti-pattern the Active
zone avoids). #}
{# DES-07: responsive name cap — clamp scales the truncation width with the viewport
(narrow phone → ~10rem, wide desktop → 28rem) instead of a fixed 16rem; min-width:0
lets text-truncate shrink inside the flex row. #}
{{ p.name }}
{% if p.is_git_repo %}Git{% endif %}
{% if p.has_claude_md %}CLAUDE.md{% endif %}
{# FE-578: surface a launch precondition INSIDE the popover; Run stays ENABLED
(disabling it would hide the spawn picker / trust confirm that resolve it).
On open we coerce a non-git+worktree default to a valid mode; the note below
the Spawn picker explains it. #}
{# Dismissing the popover (outside-click / Escape) also clears any pending
trust/bypass gate (#686) so a hidden gate never lingers — reopening starts
a fresh launch. mopen is reset too so More options collapses on reopen. #}
How do you want to drive it?
Connectable from claude.ai / Desktop — converse with it, and Stop it here when done.
{# Option text + effect tooltip both come from the canonical
permission_labels map (#685) — never a hand-maintained copy.
bypassPermissions is offered only where the per-project ceiling
allows it and only for the Desktop/bridge launch (the typed-confirm
footgun guard); the "(Desktop only)" caveat is a contextual hint
appended here, not baked into the canonical label. #}
{# Plain-language effect of the SELECTED mode, inline (not just title=) so it's
visible on touch — the riskiest per-launch choice shouldn't hide in a tooltip. #}
{# "More options" — a single disclosure (#686) holding the ADVANCED choices
for the Desktop/bridge launch: the Mode selector (Server Mode / Interactive
Session) AND Spawn. Mode is an advanced choice, tucked away by default; the
safe Desktop default works with this closed. Only the Desktop launch exposes
these (browser/background ignore spawn + resume mode). #}
{% if pty_supported %}
{# Mode (Server Mode / Interactive Session) — the advanced launch-shape choice,
tucked inside More options. Drives whether Spawn applies (standard) or the
single-session note shows (pty). #}
{% endif %}
{# Spawn only applies to the standard (multi-session) bridge — it maps to
`claude remote-control --spawn`. pty is a single interactive session run
under the keeper with no `--spawn`, so it ignores these; hide them in pty
mode rather than offer no-op choices. #}
{# #578: surface (don't disable) — a non-git dir can't worktree, so
note it here and coerceSpawnMode() falls back to same-dir on open.
x-text (auto-escaped, never x-html); no d-* class on this x-show el. #}
{% if pty_supported %}
{# Keep d-flex OFF this x-show element — `.d-flex{display:flex!important}`
overrides x-show's inline display:none and would pin this hint visible
even in standard mode (same bug as the live-tail banners). Flex goes on
the inner wrapper. #}
Runs as one session in the project directory.
{% endif %}
{# Trust-on-start + bypassPermissions gates fold INSIDE the popover (#686) —
no separate below-the-row alerts. Both are hidden until the Run button routes
a Desktop launch into start(), which opens the matching gate; resolving or
cancelling either one dismisses the popover (via the launch-pop-close event). #}
{# When a gate opens INSIDE the popover the Run button hides, so move focus
into the gate's first control (WCAG 2.4.3 / 4.1.3) — else focus is orphaned
on and a keyboard/SR user gets no signal a confirm now blocks launch.
x-effect re-runs when confirmTrust[name] flips; $nextTick waits for x-show. #}
Trust the files in {{ p.name }}? Launching a session here
lets it run tools and execute any code in CLAUDE.md /
.claude in this directory.
bypassPermissions lets sessions in {{ p.name }}
run tools without asking. Type the project name to confirm.
{# Primary Run action. Hidden while a trust/bypass gate is showing INSIDE the
popover so the gate's own confirm button is the single next step (no competing
primary). On a clean launch (no gate pending) launchRun() returns true and the
popover closes; when it opens a gate it returns false and the popover stays. #}
{# Semantic end-of-popover sentinel: a stable structural boundary for tests
(so they don't couple to template whitespace/nesting). Renders nothing. #}
Readiness checks for {{ p.name }} before launch
{# The trust-on-start + bypassPermissions confirm gates moved INSIDE the launch
popover (#686) — they no longer render as separate below-the-row alerts. The
`data-test="inline-error"` hook is load-bearing: three `.alert-danger.mb-0`
blocks now share this row (the in-popover bypass-confirm, this transient-action
error, and the spawn-failure detail below), so a bare `.alert-danger.mb-0`
selector is ambiguous — tests must target this stable hook. #}
Session failed to start
CLAUDE.mdnew file
A session is running — saved changes apply to new sessions, not the attached one.