Redesign Loops & Skills: library model, semantic run history, inline script editing#354
Closed
brsbl wants to merge 40 commits into
Closed
Redesign Loops & Skills: library model, semantic run history, inline script editing#354brsbl wants to merge 40 commits into
brsbl wants to merge 40 commits into
Conversation
Stage 1 of plans/loops-skills-redesign-build.md: - Two-line loop rows: human cadence + last-run health (status + time) + next-run; drop Script/API badges (mode lives in detail), keep project pill. - Body description; relabel chrome title, breadcrumb, and the sidebar entry (text + Repeat icon) to "Loops". Internal Automation types/routes unchanged. - Update AutomationsView tests + story fixtures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Group the overview by project (folder icon + name header) instead of a project pill; enabled loops sort above paused within each project. - One status signal: leading icon reflects the last run (success/failed/ skipped/running/never); drop the enabled/paused dot. Paused is conveyed by the next-run label. - Row layout: last-run date under the name (left); next-run + schedule stacked on the right. Add icons to the row context menu (Pause/Resume/Run/Delete). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The leading slot shows the last-run icon once a loop has run; before its first run it falls back to the enabled-state dot (green when enabled/scheduled, muted when paused) so a brand-new enabled loop doesn't look dead. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Health rollup stat cards: success rate, last run, next run, avg duration (computed from runs + schedule). - Restyle header: back link to Loops, name + Active/Paused status; drop the Script/API pills (mode lives in the config card). Config shown as a titled card; run history kept. - Relabel detail strings automation→loop. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add updateAutomation API client + useUpdateAutomation hook over the existing PATCH route. - Edit button flips the config card to inline fields (name, cron, timezone, prompt for agent loops, auto-archive) using real Input/Switch; Save persists via PATCH, Cancel reverts. Script bodies aren't editable inline (response carries only scriptFile) — noted in the form. - Update detail tests/stories for the new onSave/savePending props. Stages 2–3 of plans/loops-skills-redesign-build.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Session S1 of the Loops and Skills Pages spec: the genuinely-new backend the later Skills-page UI binds to. No automations API/DB/CLI or typeahead change. Daemon: - host.list_skills: skill-only discovery that emits each record's absolute filePath + originating rootKind, reusing the existing scan-root resolution and leaf helpers (typeahead scan path untouched). - host.delete_skill: new confined FS write primitive (bb scopes only). Path is built host-side from (scope, name, cwd); name must be one safe segment; the realpath target must be the exact named direct child of the allowed bb root, refusing any symlink redirect. Non-retryable. Server: - GET /projects/:id/skills: queries both command-surface providers, maps (provider, rootKind) -> product scope/manageable, de-dupes provider-agnostic bb skills by filePath. - DELETE /projects/:id/skills: re-validates the bb scope, resolves the workspace (never forwards a client filePath), calls the non-retryable daemon primitive. Contract: skillSummarySchema + skill scope/provider enums + daemon command and result schemas, registry, and online-rpc response wiring. Tests: daemon discovery rootKind-per-root + delete confinement (traversal, symlink escape, sibling-symlink redirect, non-skill, missing); server scope-map + de-dup + delete validation/409; contract round-trip. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- /skills route + lazy SkillsView; chrome title "Skills"; useRouteState.isSkillsView. - API client listProjectSkills/deleteProjectSkill over the cherry-picked GET/DELETE /projects/:id/skills; useProjectSkills/useDeleteSkill hooks. - SkillsView: provider-grouped (real provider logos, bb-agnostic last), searchable, calm typeahead-style rows; scoped to the personal project. - Sidebar: Skills entry (Zap) above Loops via ProjectListActionButtons. - Tests for grouping + states. Verified live: GET /skills returns builtins. Stages 4–5 of plans/loops-skills-redesign-build.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
--primary light oklch(0.4891)->0.27 (near-black), dark 0.7058->0.82 (more decisive, still light-on-dark). Decision #3 from the redesign note. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Drop the redundant in-body back link (the chrome breadcrumb already returns to Loops). - Header actions: surface a persistent "View thread" (latest run's thread, when one exists) and fold Edit + Delete into a "..." overflow menu, leaving Run now + Pause/Resume as the primary actions. - Run-history rows keep their per-run View thread link. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New skill action opens the composer seeded with "Create a new bb skill that " (creation always targets a bb skill — the only manageable scope); the spawned thread authors the SKILL.md. Mirrors the Loops create flow. True inline-embedded prompt box is deferred: NewThreadPromptBox needs RootComposeView's full modeConfig, so it's a separate refactor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- View (all scopes): GET /projects/:id/skills/content resolves the skill by (scope,name) to its authoritative filePath and reads via the existing host.read_file daemon command (never a client path). - Edit (bb skills only): new secure host.write_skill daemon command (bb-user/ bb-project, path resolved host-side from (scope,name,cwd), realpath/symlink guards, edits existing SKILL.md only) + PATCH /skills/content route. - Skill rows open a detail dialog showing the SKILL.md; bb skills get inline edit (Save) + Delete; other scopes are read-only. - Contract/session registration + result fixture for host.write_skill. Stage 7 of plans/loops-skills-redesign-build.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Order bb-agnostic skills above the provider groups. - Each provider group is its own card with a collapsible header (chevron, aria-expanded) and a max-h-64 scroll area, so a large group (e.g. plugins) scrolls in place instead of running the page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each project group header is now a toggle (chevron + folder + name + count), mirroring the Skills page; collapsing hides that project's loops. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Personal == projectless in bb (isProjectlessProjectId), and the sidebar renders personal threads without a project header. Mirror that: render personal/ projectless loops as a flat list, and only group real projects under collapsible folder headers. With no real projects it's just a clean flat list (no redundant 'Personal' header). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The prompt-composer wiring — useThreadCreationOptions + usePromptDraftStorage + usePromptMentions + useCommandSuggestions + useUploadPromptAttachment + buildProviderPromptActionProps, assembled into the execution / permission / typeahead / attachments / composer configs — was hand-rolled in three places. Extract it into one shared hook, apps/app/src/components/promptbox/ useComposerArea.ts, and migrate the three call sites onto it. Parity-first migration (no behavior change to any surface), in order of coupling: 1. SideChatTabContent (FollowUpPromptBox, read-only footer, submit creates the child thread) — lifted first as the most self-contained. 2. ThreadDetailPromptArea (FollowUpPromptBox, editable footer, submit steers / follows up). 3. RootComposeView (NewThreadPromptBox, submit creates a new thread) — most coupled; its project picker, branch/worktree selection, queued-message stack, and the box itself stay per-site. Command discovery follows the resolved environment selection, which the hook itself produces, so it is supplied as a resolver over the live selection value. The hook owns only the shared assembly. Each site keeps its box choice, submit handler, and chrome. Sites differ on a few explicit, typed parameters: execution interactivity (read-only / provider-switchable), permission shaping (editable / editable-gated / read-only), the attachment upload-error strategy (collect failed names / first error), and the mention/command scoping. The Loops/Skills inline composer that motivated this is a follow-up that will consume the hook; it is intentionally not built here. Validation: typecheck and the full @bb/app test suite pass (871 tests, including the SideChatTabContent render test that exercises the real component through the new hook); lint clean on the changed files. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add an "Open in editor" button to the skill detail dialog's view state for every skill (next to Edit for bb skills, beside the Read-only label otherwise), wired to the existing useLocalOpenTargets → openPathInPreferredFileTarget path. Hidden in edit mode and when no local file-open target is available. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When an agent creates a loop from within a thread, append an informational
system/operation row ("automation-created") to that thread's timeline whose name
links to the loop's detail page. Mirrors the parent-change row: a non-turn
notice carrying a typed { automationId, projectId, automationName } payload, with
a new "automation" TimelineTitleLink kind resolved to the automation route.
- domain: automationCreatedOperationMetadataSchema (system/operation metadata)
- server: appendAutomationCreatedEvent, emitted from the create route only when
createdByThreadId is set (best-effort; never fails the create)
- thread-view: parse + project the event into the new row variant + linked title
- server-contract: timelineAutomationCreatedSystemRow variant
- app: resolve the automation link + Repeat glyph
- tests at every layer; story in System.stories
Skills get no notice yet (no creation hook / deep-link route) — follow-up.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Skills are on-disk files mutated out-of-band (agents write SKILL.md; users edit via "Open in editor"). Set staleTime: 0 + refetchOnMount: "always" on the list and content queries so the page/detail re-read from disk on mount and focus instead of serving the 2s-stale global cache. Daemon + server already read fresh. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Align both pages to app conventions from a design consistency review: - Collapse caret = single ChevronRight rotating 90° on expand (matches ProjectList), not a ChevronRight/ChevronDown swap. - Skills search input matches the standard page-search pattern (icon left-2.5, base Input focus); skill-row focus ring + edit textarea use ring-ring / border-input instead of file-accent (reserve the accent for links/active). - Width: both overviews use a shared max-w-5xl; detail pages stay max-w-3xl. - Loops rows use sanctioned text tiers (muted/subtle-foreground) instead of opacity tints (text-muted-foreground/50–/80) that fell below the AA floor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the sidebar thread-search treatment instead of the generic page-search: a filled pill (bg-muted, no border) with a leading search glyph, a bare transparent input, and a focus-within ring — rather than a bordered Input with an absolutely-positioned icon. Uses page-neutral tokens + the sanctioned focus-within:ring in place of the sidebar's scoped tokens/arbitrary shadow. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the persistent header "View thread" button; the run history already links each agent run to the thread it created, which is the right place for it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lish
- Empty state teaches create-via-prompt: a marketing one-liner + clickable
example cards (cross-provider skills; cheap-script-escalates-to-threads loops).
Skills teach when there are no user-created bb skills.
- Fork-style context chip ("New bb skill" / "New loop") above the composer when
creating via prompt, mirroring the thread-fork treatment.
- Design-review polish: single explainer per page (drop the redundant intro),
no container/lightning-icon on the example cards, search reverted to the
bordered look with the sidebar's subtle focus ring (no black ring), provider
section max-height grows with the window, "New bb skill" label.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework the detail header and config so the loop name is the focal point: - Header is the name + a single row: next-run timestamp and inline Edit / Pause·Resume / Delete (quiet ghost buttons; Delete keeps its confirm modal). Drop the four-stat health card (inferable from run history), the "Active" label, the Run now button, and the overflow menu; clean up the dead onRun / runAutomation plumbing. - Configuration shows Execution like the prompt box (provider logo + model + a readable permission chip — "Read-only", not "readonly") and Environment with an icon, instead of a raw "Agent · codex/gpt-5 · readonly" string. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Loops gets a search bar matching Skills (filters by name across groups, with a no-match state); drop the count beside the project folder icon. - Both overviews use a loading skeleton instead of "Loading…" text. - Skills: an "all your local skills, view/manage" explainer above the search (the bb-skills intro stays in the teaching below); section max-height grows with the window. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add SkillsView stories (overview, builtins-only, empty=the two default bb skills, loading, error) and round out the Loops overview (running/skipped statuses) so the real presentational components can be iterated across states in Ladle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make SCRIPT-mode loops editable end-to-end from the loop detail page, replacing the "delete and recreate the loop to change its script" message. The PATCH route + contract already accepted an `execution` update for the script variant (inline `script`, interpreter, timeout) and wrote it via `resolveStoredExecution`. What was missing to make this usable: - Server: enrich only the single-automation GET with the stored inline script content so the edit form can pre-fill it (responses otherwise carry only `scriptFile`). List/overview stay lean — no per-row disk read. - Storage: write inline scripts via a temp file + atomic `rename`, so an update that rewrites an existing script is atomic w.r.t. a concurrent run (a reader sees the full old or full new content, never a truncated file). - Frontend: in edit mode, for script loops render an editable font-mono script textarea + interpreter select + timeout (seconds), wired into the existing PATCH flow alongside name/cron/timezone. Existing `env` is carried through untouched so it isn't silently dropped; Save is disabled on an empty script. Tests: server PATCH round-trips the new script through disk and surfaces it via GET; PATCH to a script execution is rejected (403) when script runs are policy-disabled. Frontend test drives the edit form and asserts the saved patch. Live-smoked against the dev server (create → edit → disk → GET). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…poser-hook-usecomposerarea-thr_xuvnw67au8 # Conflicts: # apps/app/src/views/RootComposeView.tsx
- Skills is one browse/manage library; create is a split button (blank + example templates), teaching only in genuine empty states (grounded in VS Code/Raycast + NN/G empty-state research) - Loops overview rows signal only on/paused + failing; the run taxonomy moved to the detail run history - Loop detail run history uses semantic status icons; a script run that spawned a thread shows exit code + View spawned thread; loading skeleton + status-aware empty state - Share create-example data via getCreateExamples + CreateWithTemplatesButton; add the Script-escalates-to-agent detail story Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Brings the shared composer hook into this branch so the loop-edit form can render the real prompt box. Resolved one import conflict in apps/server/src/routes/projects.ts (kept both the skill-listing and daemon-file-response imports). RootComposeView auto-merged (create-draft chip + useComposerArea migration); typecheck + composer and redesign test suites pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Brings end-to-end script-loop editing from the detail page: the edit form gains script/interpreter/timeout fields, the single-automation GET enriches with stored script content, and the script write is atomic. Clean auto-merge with the run-history rework (both touched AutomationDetailView). Typecheck (app + server) clean; app suites (incl. script-edit) and the server automations route tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reconcile main's new provider-CLI-install feature + folder/PromptStackCard work with the useComposerArea refactor across the composer surfaces: - RootComposeView: keep the hook-based destructure; re-apply main's codex CLI install runner/banner; keep both the create-draft chip and folder-id reset. - SideChat/ThreadDetailPromptArea: drop main's inline attachment/creation-options wiring (now owned by useComposerArea); gate the composer on thread.archivedAt. - ProjectList: keep the Loops tooltip. Typecheck (app + server) clean; 83 composer + redesign tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
main's cache-owner-registry guard flags raw queryClient.invalidateQueries outside hooks/cache-owners/. The skills mutation hooks did raw invalidations, so: - moved the skills query keys to query-keys.ts (projectSkillsQueryKey, skillContentQueryKey) - added skills-cache-effects.ts owning the invalidations - skills-queries.ts now delegates to it, like automation-queries does - registered the owner's query-key imports in the guard Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…thr_xnwqkhbpc4 # Conflicts: # apps/host-daemon/src/command-dispatch.ts
…jigsc' into bb/redesign-thread-p-thr_xnwqkhbpc4
This was referenced Jun 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Redesigns the Loops and Skills pages and the Loop detail page, and folds in two enabling pieces that were spun out as their own spikes.
Skills — a browse/manage library
New bb skill ▾): the left half makes a blank skill, the chevron opens example templates.Grounded in design research: VS Code Extensions / Raycast (one managed list + a single template-based create action) and NN/G (teaching belongs to genuinely-empty states; don't over-signal).
Loops overview — two states, not five
CircleX+ "Failed"). The full run taxonomy (ran/skipped/running) moved to the detail run history.New loop ▾); teaching cards stay in the genuine empty state.Loop detail — calmer hierarchy, semantic run history
Composer hook (was #283)
useComposerAreaextracts the shared prompt-composer assembly so the loop-edit form can render the real prompt box; migrated the 3 existing composer surfaces onto it, parity-first.Folded-in PRs
Testing
turbo typecheckclean (app + server).apps/app/src/views/*.stories.tsx.🤖 Generated with Claude Code