Redesign the Skills & Loops pages#405
Closed
brsbl wants to merge 56 commits into
Closed
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
main made additionalSkillsRootPaths a required field on CommandRootResolution; skill listing has no such command field and does not surface inherited dev-app roots (classifySkillRootKind drops them), so pass []. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Read view now reuses MarkdownPreview (the thread file viewer's renderer) on a surface-raised wash instead of raw <pre>, and strips a leading YAML frontmatter block so it doesn't render as a stray rule + setext heading (the dialog header already shows name/scope). Extract SkillContentPreview so it stories on its own; add a Detail story with a representative SKILL.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the 'every skill your agents can run' line above the search/create row so it reads as the page description. Drop the BuiltinsOnly story. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Split SkillDetailDialog into a presentational SkillDetailDialogView (content + persistence arrive via props) and a thin connected wrapper, so stories drive the actual popup with a sample SKILL.md instead of a standalone Detail story. Every Skills story now opens the detail on row-click; manageable skills show Edit/Delete, the rest are read-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
text-base read as an oversized heading (louder than the group headers). Drop it to a 13px subtle-foreground caption so it stays subordinate to the list. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tailwind v4 doesn't default buttons to a pointer; match the interactive-row convention (cf. SIDEBAR_ROW_INTERACTIVE_STATE_CLASS). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… icon Read view now uses FilePreview — the same component the app uses for .md files in threads (markdown rendering, code blocks with copy, GFM tables) — run header-less inside the dialog, instead of a hand-rolled MarkdownPreview wrapper. Drop text-file-accent (paper-blue) on the header lightning icon; it's now a neutral text-muted-foreground. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move Edit/Delete/Open-in-editor out of the split footer into a quiet icon cluster beside the title (clear of the dialog close). Editing now happens in place: the content box becomes an auto-focused editor and Save/Cancel swap into the same header cluster; delete confirms inline there too. Footer removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apply the frontend-design skill's 'failure is direction, not mood' principle: the load error now says what happened plainly (Couldn't load skills.) and offers a Retry (wired to refetch), kept calm/monochrome via EmptyStatePanel — no alarmist red. Update the story + test to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…w actions Stop stripping YAML frontmatter — pass SKILL.md to FilePreview verbatim so the viewer renders it the same way it does in threads (MarkdownPreview's muted key/value metadata list), instead of deleting it. Replace the bare icon cluster with one labeled Edit button plus a more-actions overflow menu (Open in editor, Delete) — the app's own DropdownMenu row pattern. Keeps the destructive action out of fat-finger range and the header uncluttered. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Edit/⋯ cluster sat awkwardly beside the dialog's ✕. Give the SKILL.md viewer a thin top toolbar with the actions right-aligned (Edit + overflow in read, Cancel/Save in edit), and reduce the dialog header to just the title — so the actions read as part of the document surface and the ✕ stands alone. Removes the now-unused SkillContentPreview (inlined into the shell). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per Notion/Linear: drop the viewer toolbar; read mode shows just one ⋯ overflow beside the title (Edit, Open in editor, Delete), aligned with the ✕. Edit is reached from there and happens inline; Save/Cancel surface in the header during editing. The viewer is plain content again. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop flex-1 from the title so it sizes to content and the ⋯ sits right after the scope pill, with the ✕ alone at the far right. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the w-44 override and the min-w-[8rem] floor (min-w-0) so the ⋯ menu sizes to its longest item instead of a fixed 176px. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Split the header action slot: read mode keeps the ⋯ by the title; editing and delete-confirm now render in a DialogFooter (Cancel/Save right-aligned, the delete prompt with the buttons). The ⋯ is hidden while editing/confirming. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tailwind v4 doesn't default buttons to a pointer; the shared dialog close lacked it (noticed on the skill viewer). Fixes every dialog's ✕. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Superseded by a properly-scoped Skills-only PR (one commit, off main). This one carried the whole combined redesign + folded #358, which isn't what was wanted. |
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.
Fresh PR for the Loops & Skills redesign — supersedes the closed #354 (which got unwieldy). Built on this branch; Loops gets its design pass in later commits here.
Status
Skills design pass (this round)
FilePreview) — same markdown rendering, frontmatter (mutedname/descriptionmetadata list), code blocks with copy, and GFM tables as a.mdfile in a thread. Content is passed verbatim; the viewer owns frontmatter.⋯overflow beside the title (Edit · Open in editor · Delete), aligned with the✕. Edit happens inline; Cancel/Save live in a modal footer (delete-confirm too).✕; a recoverable error state (Couldn't load skills.+ Retry) instead of a vague dead end.frontend-designskill's "failure is direction" + writing principles, kept within bb's restrained, near-monochrome house style.Base
Includes the resolved merge of
origin/mainand the folded-in agent loop edit composer (#358). Currently behindmain; I'll refresh before merge.🤖 Generated with Claude Code