Commit log

cdacb2d imageutil: add HEIC to PNG conversion support

Click to expand commit body
Prompt: make the screenshot tool work with heic?

Add IsHEIC() to detect HEIC/HEIF images by file magic (ftyp box brands).
Add ConvertHEICToPNG() using ImageMagick's convert command.
Update read_image tool to auto-convert HEIC images before processing.

This enables the read_image tool to handle iPhone photos uploaded in
HEIC format, which Go's standard image library doesn't support.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

20e320c shelley: Track LLM HTTP requests in database; new headers

Click to expand commit body
Prompt: Add tracking of all LLM HTTP requests to a database table
(llm_requests) for debugging/auditing, plus add custom headers
(User-Agent with Shelley version, Shelley-ConversationId) to all
outgoing LLM requests. Remove existing HTTPRecorder callback and ant's
DumpLLM; we don't need them. Remove in-memory LLMRequestHistory and
/debug/llm endpoint. Make sure that the anthropic and openai and gemini
implementations all follow the same pattern/implementation here.

- Add llm_requests table for tracking/debugging LLM API calls
- Add custom HTTP headers: User-Agent with Shelley version, Shelley-ConversationId
- Create llmhttp package for HTTP transport with recording and headers
- Remove HTTPRecorder callback from ant.Service
- Remove DumpLLM from ant, oai, and gem services
- Remove in-memory LLMRequestHistory and /debug/llm endpoint
- Update models.Manager to use new database-based recording
- Pass http.Client through factory functions for consistent transport

The llm_requests table stores:
- conversation_id (optional)
- model and provider
- URL, request/response bodies
- status code, error, duration

Custom headers help with debugging and tracing:
- User-Agent: Shelley/<commit_hash>
- Shelley-ConversationId: <conversation_id>

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

f3af1ad all: unnest some errors

Josh Bleecher Snyder created

9e060f8 shelley: read AGENTS.md from context directory at conversation start

Click to expand commit body
Prompt: fix https://github.com/boldsoftware/shelley/issues/30

Fix issue where the system prompt was generated before loading the cwd
from the conversation record, causing it to use the server's working
directory instead of the user's specified context directory.

The cwd is now loaded from the conversation before generating the
system prompt, ensuring that AGENTS.md and other guidance files from
the context directory are properly included in the system prompt.

Fixes https://github.com/boldsoftware/shelley/issues/30

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

abd3b1c shelley: add output_iframe tool for sandboxed HTML visualization

Click to expand commit body
We'll see if this sticks and is found useful. You can't really
have the LLM output HTML, because it ends up dangerous in the timeline.
But you can embed an iframe. So let's give the LLM a way to do that!

Prompt: I want Shelley to be able to produce HTML output that the user
can see, but for security, I want this to be made safe by using an
iframe. For example, if I ask Shelley to produce a vegalite
visualization, I want the agent to be able to produce sandboxed HTML to
do that. Create a new tool "output_iframe" that should be used for
visual elements if the agent wants to display them, and should be
expanded by default in the HTML tool output. Advise the tool description
to only use this for visualizations like graphs and demonstrations of
HTML, and to use regular messages for chatting with the user.

Add a new tool 'output_iframe' that allows the agent to display HTML content
to the user in a secure sandboxed iframe. This is useful for:
- Vega-Lite and other chart library visualizations
- HTML/CSS demonstrations
- Interactive widgets
- SVG graphics

The tool:
- Takes HTML content and optional title as input
- Returns 'displayed' to the LLM (minimal response)
- Passes HTML to UI via Display field for rendering
- Uses sandbox="allow-scripts" for security (scripts run but can't access parent)

The UI component:
- Renders iframe with srcdoc for the HTML
- Expanded by default (like screenshot tool)
- Styled consistently with other tool components

Tool description explicitly advises using this only for visualizations,
not for regular chat messages.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

affeb09 shelley: add version/tag to build via goreleaser ldflags

Click to expand commit body
Include Version and Tag in `shelley version` output, injected at build
time by GoReleaser. Local builds show "dev" for version.

Also fix false positive "modified=true" in UI build by filtering out
dist/ directory from git status check.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Philip Zeyliger and Claude created

d4961e9 shelley/ui: show warning icon when conversation exceeds 100k tokens

Click to expand commit body
Prompt: When a conversation gets to 100k tokens, I want you to put up a ⚠️-type
icon, and some text above it: 'This conversation is getting long. For best
results, start a new conversation.'

When the context window reaches 100k tokens or more, show a ⚠️ warning icon
next to the context usage bar. Clicking the bar shows a popup with the
full warning message.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

c8602f3 shelley: ui: remove spinning animation from bash tool emoji

Click to expand commit body
Prompt: Get rid of the spinning hammer in shelley bash tool stuff. Just get rid of the animation
Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

f4f0813 shelley: add subagent tool for parallel task delegation

Click to expand commit body
Prompt: we're continuing work in this worktree (don't switch) on subagents. I think things are working. Can you tell me what the system prmopt is for subagents? Is it the same as the main one? how does that end up working?

Prompt: 1. Fetch and rebase on origin/main. Notably, there's a UI change to indicate which conversations are working vs. not, and that might need to be plumbed into subagent tasks in the convo list. 2. Let's write a system prompt for subagents. It should be short, but include some of the basic details. It's important to understand that only the last message gets sent to the parent agent, though it can of course reference files and so on.

Prompt: fetch, rebase on origin/main, and squash into one commit

Adds a subagent tool that allows the main agent to spawn independent
conversations for parallel task delegation. Subagents:
- Have their own conversation with full tool access (except nested subagents)
- Run with a minimal system prompt focused on task completion
- Return their final message to the parent agent
- Support both synchronous (wait) and async (fire-and-forget) modes

Key changes:
- New subagent tool in claudetool/subagent.go
- SubagentRunner in server/subagent.go handles conversation lifecycle
- Database schema adds parent_conversation_id for tracking hierarchy
- Minimal subagent system prompt (vs full 17KB main prompt)
- UI shows subagents nested under parent conversations
- Working indicator (pulsing dot) for subagent conversations

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

31f89a8 shelley: change favicon to Cool S

Click to expand commit body
I couldn't find a good shell SVG anywhere with licensing that
I could be sure of, so I drew a cool S in Excalidraw, and
the 90's are back.

Prompt: Let's try to fix
https://github.com/boldsoftware/shelley/issues/18 by changing the
favicon. I want to preserve the fact that the favicons have random
colors and therefore keep it in svg. Let's do the "Cool S"
(https://en.wikipedia.org/wiki/Cool_S) as our image for now; that should
be easy to draw in svg.

Replace the scallop shell design with the iconic "Cool S" (also known
as the Stussy S or Super S), using the hand-drawn Excalidraw SVG
directly to preserve the sketchy aesthetic.

The color varies by hostname hash (hue 0-360°) while keeping
saturation and lightness constant for consistent appearance.

Fixes https://github.com/boldsoftware/shelley/issues/18

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

67bc2aa shelley: make agent working state explicit with UI indicator

Click to expand commit body
Prompt: Let's separate the concept of "agent working" from interpreting the message stream to figure out the state and let's be explicit. The server knows whether it is doing stuff (like tool calls or LLM calls). Let's say that we have a special type of message that's always sent whenever there are updates to indicate the "agent is working" state explicitly. Get rid of is working on the existing struct.

Follow-ups:
- Git working status isn't connected to end of turn; we can just focus on whether or not we're in the agent loop or not. Test the case where a conversation is loaded after a server restart; the agent isn't working in that case because the conversation isn't loaded. Make this a ConversationState object instead of an AgentStatus object because it's per conversation. These should be broadcast because a user might care about their other conversations too
- Add a little indicator dot for conversations that are in the working state. This also implies listing conversations requires exposing this state.

Instead of inferring the agent working state from the message stream
on the client side, have the server explicitly track and broadcast
the state via a new ConversationState struct.

Server changes:
- Add ConversationState struct with ConversationID and Working fields
- Add ConversationWithState for list endpoint (Conversation + working)
- Add SetAgentWorking/IsAgentWorking methods to ConversationManager
- Broadcast ConversationState changes to ALL active conversation managers
- Set working=true when AcceptUserMessage queues work
- Set working=false when agent message with end_of_turn=true is recorded
- Set working=false on conversation cancel
- Update /api/conversations to include working state
- Add test verifying Working=false after server restart (no active loop)
- Remove agentWorking() inference function and its tests

UI changes:
- Add pulsing blue dot indicator next to working conversations in drawer
- Handle conversation_state updates from stream to update working state
- Preserve working state when receiving ConversationListUpdate messages

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

2f879e2 shelley: ui: remove border lines from conversation drawer header and footer

Click to expand commit body
Prompt: Get rid of the line below conversations and the line above view archived.
Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

1de584e shelley: browser: support file downloads and large output handling

Click to expand commit body
Prompt: Handle https://github.com/boldsoftware/shelley/issues/7 - support browser downloads and write large outputs to files.

---

Add support for browser-initiated file downloads and improve handling of
large tool outputs.

**Downloads:**
- Browser now saves downloaded files to /tmp/shelley-downloads/ with
  randomized filenames (e.g., filename_abc12345.ext)
- Downloads are reported in navigate/eval tool output with filename,
  source URL, and save path
- Navigation to download URLs (like direct PDF links) now reports
  success with download info instead of ERR_ABORTED error

**Large output handling:**
- Console logs (browser_recent_console_logs) exceeding 1KB are written
  to /tmp/shelley-console-logs/ and the tool returns the file path
- JavaScript results (browser_eval) exceeding 1KB are similarly written
  to files instead of returned inline

Example output for downloads:
  Navigation triggered download(s):
    - report.pdf (from https://example.com/report.pdf) saved to: /tmp/shelley-downloads/report_a1b2c3d4.pdf

Example output for large JS results:
  JavaScript result (5000 bytes) written to: /tmp/shelley-console-logs/js_result_x1y2z3.json
  Use `cat ...` to view the full content.

Fixes https://github.com/boldsoftware/shelley/issues/7
Inspired by https://github.com/boldsoftware/shelley/pull/8

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

58baf77 shelley: add git commit info to version command

Click to expand commit body
Prompt: bin/shelley version doesn't seem to print anything. we have a variety of ways things get built, but i want to see version information

The version command now shows commit hash, timestamp, and modified status.
Build script captures git info into build-info.json, which the version
package reads as a fallback when runtime/debug doesn't have vcs info.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Philip Zeyliger and Claude created

b3cf6be shelley: ui: replace right-click menu with tap-to-show action bar

Click to expand commit body
Fixes: https://github.com/boldsoftware/shelley/issues/19

Prompt: Get rid of the right click menu for copy and paste. Instead if
you tap on a message, a copy icon should show up above the message that
can be clicked. Likewise an info icon for usage details. This should
work for tool results as well.

Replace the context menu (right-click/long-press) with a tap-to-show
action bar for copy and usage info actions. When a message is tapped,
a small action bar appears in the top-right corner of the message with:

- Copy icon: copies message text (including tool results) to clipboard
- Info icon: shows usage details modal (only for agent messages)

The action bar:
- Appears on tap/click anywhere on the message
- Closes when clicking outside the message
- Works for all message types including tool results
- Shows feedback (checkmark) after successful copy

This provides a more touch-friendly UX compared to the context menu,
and the icons are always accessible without needing to know about
right-click or long-press gestures.

Co-authored-by: Shelley <shelley@exe.dev>

shelley: ui: show action bar on hover, position above text

Prompt: Not bad. I also want it to show up on mouseover, and I want the copy button above the text, so that it doesn't obscure the text.

- Add hover (mouseenter/mouseleave) handlers to show action bar on hover
- Reposition action bar above the message (top: -28px) so it doesn't
  obscure the message text
- Action bar now shows on either hover OR tap (for mobile compatibility)

Co-authored-by: Shelley <shelley@exe.dev>

shelley: ui: remove drop shadow from action bar

Prompt: Not bad. It's got a drop shadow of some sort that looks inconsistent

Remove the boxShadow from the message action bar for a cleaner look.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

35f8566 shelley: ui: prevent screenshots from scaling beyond 100%

Click to expand commit body
Prompt: When shelley shows a screenshot, it takes up the whole width,
even if that means scaling up the image more than 100%. I think that's
wrong; we should max out at 100% scaling if possible.

Add width: fit-content to .screenshot-tool-image-container so it shrinks
to the image's natural size. The max-width: 100% ensures it still doesn't
overflow on narrow screens.

This prevents small screenshots from being stretched to fill the entire
width of the message area.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

2de1563 go.mod: upgrade to 1.25.6

Josh Bleecher Snyder created

42aaa6f shelley: ui: add dynamic favicon status indicator

Click to expand commit body
Prompt: https://github.com/boldsoftware/shelley/issues/14 . Work on this. Have the favicon change when the state changes from agent is working to ready.

Changes the browser tab favicon to show a colored dot indicating agent status:
- Green dot: ready/idle - agent is waiting for input
- Orange dot: working - agent is processing a request

The status dot is added to the existing server-injected seashell favicon SVG.
This helps users who have Shelley in a background tab know when the agent
has finished working without switching tabs.

Fixes: https://github.com/boldsoftware/shelley/issues/14
Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

2e3eff5 .clabot: add skybrian

David Crawshaw created

1335c5a fix: keyboard shortcut toast disappears after 6 seconds

Click to expand commit body
Prompt: [user showed screenshot of stuck toast] I was expecting the toast
for shelley's keyboard shortcuts to disappear after a while.

Split the keyboard hint logic into two effects:
1. One to show the hint on first open (when fileDiff is ready)
2. One to auto-hide after 6 seconds (triggered by showKeyboardHint changing)

This ensures the timer runs reliably regardless of how the dependencies
of the first effect change.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

b87937e ui: make build output quieter by default

Click to expand commit body
Prompt: That is so noisy! Can we make the UI build way quieter by default? Fine to have a verbose env variable or something. All I want is to see that it built and maybe how long it took.

Show just a single summary line with timing and gzip size.
Set VERBOSE=1 for detailed per-file breakdown.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Philip Zeyliger and Claude created

23c70aa bin: add install-to-exe.sh for remote testing

Click to expand commit body
Prompt: Add to bin/ a bin/install-to-exe.sh script that takes a hostname, appends exe.xyz to it if it's "short", builds a shelley binary for linux x86, scp'ies it to /usr/local/bin on the host, and runs systemctl restart -u shelley.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Philip Zeyliger and Claude created

3cda68e shelley/ui: auto-scroll to first changed chunk in Diffs view

Click to expand commit body
Prompt: In the "Diffs" view in shelley, we should automatically navigate to the first changed chunk rather than to the top of the file.

Instead of starting at the top of the file, the DiffViewer now
automatically navigates to the first changed chunk when a file
is opened. This uses Monaco's onDidUpdateDiff event to ensure
the scroll happens after the diff computation is complete.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

969ded4 shelley: improve cd behavior and git status messages

Click to expand commit body
Prompt: I find that the model tends to "cd" a lot despite the fact that
we have a change dir function. Remove the current directory from the
prompt an explain in the bash tool that there's a change directory tool.
Have the change directory tool report whether it's in a git repo and
where the git repo base is. Also update the message about the diff
status changing to include the git dir it's in, with tilde replacement.

- Remove <pwd> from bash tool description to reduce LLM cd usage
- Add branch info to change_dir output (root with ~, branch name)
- Update git status messages to show full path with ~ replacement
- Include commit subject in git status (truncated to 50 chars)

Example change_dir output:
  Git repository detected (root: ~/exe, branch: main)

Example git status message:
  ~/exe (main) now at abc1234 "commit subject"

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

bfdfeb3 shelley: fix agent_working status being reset by metadata updates

Click to expand commit body
phil: Don't love the impl here, but not having cancel was really
crimping my style. The whole agent_working status thing has been
really error prone.

Prompt: I'm not seeing Shelley show 'Agent is working...' any more. I
suspect the change that dealt with reconnects may have broken it? Follow
up: I think the issue is that messages from other conversations updating
the conversation name or whatever are confusing the logic.

The agent_working field in StreamResponse was being set to false (the zero
value) when sending conversation metadata updates (like slug changes). This
caused the UI to incorrectly clear the 'Agent working...' status immediately
after the agent started working.

Fix by changing AgentWorking from bool to *bool with omitempty, so metadata-
only updates don't include the field at all. The UI already checks
typeof agent_working === 'boolean' before updating state, so undefined
values are correctly ignored.

- Change StreamResponse.AgentWorking from bool to *bool with omitempty
- Update agentWorking() to return *bool
- Add boolPtr() helper function
- Update tests to handle pointer comparisons
- Regenerate TypeScript types

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

dac5480 shelley/ui: don't re-sort conversation list on updates

Click to expand commit body
Prompt: When two conversations are running at the same time, the updates to each other's status (last updated, probably) makes them resort, and it's very distracting, especially if they compete with each other. Let's just not resort them

When two conversations run simultaneously, updates cause them to
compete for position, which is visually distracting. Now we update
conversations in place and only put new conversations at the top.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

a42f6e4 shelley: fix race condition between message and metadata notifications

Click to expand commit body
Prompt: This test is flaky. [...] I think the issue is that slug updates aren't messages. I think we send conversation updates (see 3dbcb107dbbb6753c7af811d535b559c794a674b) over the same stream but without message ids. Fix it. Run the test a lot to make sure it's not flaky.

notifySubscribers (for metadata like slug changes) was using Publish with
sequence IDs, which could race with notifySubscribersNewMessage. If the
metadata update ran first, it would consume the sequence slot and the actual
message would be skipped. Changed notifySubscribers to use Broadcast instead,
which doesn't interfere with message sequence tracking.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Philip Zeyliger and Claude created

06cdc53 shelley: add server-side conversation content search to command palette

Click to expand commit body
Prompt: Does it search the text of the conversations too? This will need a backend endpoint.

Add backend support for searching conversation content:
- New SQL query SearchConversationsWithMessages that searches both
  conversation slugs and message content (user and agent messages only,
  excluding system prompts)
- New API parameter search_content=true to enable content search
- Frontend CommandPalette now calls the search API with debouncing
  (150ms) when the user types, showing a loading spinner during search

The search looks for the query string in:
- Conversation slug
- User message text (from user_data.text JSON field)
- Agent response text (from llm_data JSON field)

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

afa0735 shelley: add Command+K command palette

Click to expand commit body
Prompt: Command K should bring up, in Shelley, a modal that lets you navigate Shelley. Default is new conversation, but all other views (like diff) and conversation search should be available with fuzzy search.

Add a command palette modal (Cmd+K or Ctrl+K) that provides:
- Quick search for conversations with fuzzy matching
- Navigation to start a new conversation (default selected)
- Opening the git diff viewer
- Keyboard navigation with arrow keys, Enter, and Escape

The palette shows actions first, then conversations, and filters
results as you type with a simple fuzzy matching algorithm that
scores exact matches, prefix matches, contains matches, and
character-by-character fuzzy matches.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

e5116b2 shelley: add comprehensive test coverage

Click to expand commit body
There's more to do here, but this was kind of fun. This was
a bit inspired by https://bits.logic.inc/p/ai-is-forcing-us-to-write-good-code

Prompt: For shelley, I want the Go code to have 100% coverage. To start
with, run the tests, and evaluate what coverage we have right now.
Suggest approaches on getting us to 100. Drive this process by posting
to shelley on this host at its new conversation workflow, to break up
the work into smaller chunks, and build out tests.

Increase test coverage from ~50% to ~72% across shelley packages.

New test files:
- claudetool/keyword_test.go, shared_test.go, think_test.go, toolset_test.go
- llm/ant/ant_test.go, llm/llm_test.go
- server/git_handlers_test.go, handlers_test.go

Improved test coverage in:
- claudetool/bashkit: 96.7% -> 99.2%
- claudetool/onstart: 81.4% -> 96.5%
- claudetool/patchkit: 88.4% -> 93.9%
- claudetool/browse: 50.6% -> 56.8%
- db: 69% -> 81.6%
- llm: 2.4% -> 76.5%
- llm/ant: 14.1% -> 77.4%
- llm/conversation: 38.7% -> 88.1%
- llm/gem: 51.1% -> 61.8%
- llm/imageutil: 84% -> 96%
- llm/oai: 22.3% -> 77.9%
- loop: 70.4% -> 93.4%
- models: 54.1% -> 83%
- server: 46.4% -> 61.6%
- slug: 78.2% -> 96.4%
- subpub: 93.9% -> 100%

Packages at 100%: gitstate, subpub
Packages at 90%+: bashkit, onstart, patchkit, imageutil, loop, slug, conversation

Co-authored-by: Shelley <shelley@exe.dev>

Shelley and Shelley created

70ac05d shelley: Add real-time conversation list updates via existing SSE stream

Click to expand commit body
Prompt: the conversations list doesn't update as different conversations update. We should send messages to /stream to update the conversation list appropriately when things about conversations change. Be sure to test it with the relevant test harness.
Follow-up: fetch & rebase on origin/main. I don't want to have to open multiple connections; we already have a /stream connection. I think the invariant is that the client is subscribed to one stream at a time; let's send conversation updates over the same stream!

Instead of creating a separate SSE endpoint, send conversation list updates
through the existing per-conversation stream at /api/conversation/{id}/stream.

Changes:
- Add Broadcast() method to SubPub to send messages to all subscribers
  regardless of sequence ID (for out-of-band notifications)
- Add ConversationListUpdate field to StreamResponse
- publishConversationListUpdate broadcasts to ALL active conversation managers
- Server publishes updates when:
  - New conversation is created
  - Conversation is archived/unarchived
  - Conversation is deleted
  - Conversation is renamed
  - Conversation gets a new message (updated_at changes)
  - Conversation slug is generated asynchronously
- UI ChatInterface receives updates and passes to App via onConversationListUpdate
- App updates conversation list in real-time without separate connection

Tests verify updates flow through the existing conversation stream.

Co-authored-by: Shelley <shelley@exe.dev>

Philip Zeyliger and Shelley created

ebc18f8 all: fix formatting

GitHub Actions created

902fa07 shelley/ui/src/utils: exclude * in auto-linkify

Click to expand commit body
Fixes boldsoftware/shelley#12

Josh Bleecher Snyder created

86991be shelley .clabot: add jmandel

David Crawshaw created

eeb5cbb shelley/server: use a docs index

Click to expand commit body
Instead of a full export.

Progressive disclosure is yes.

Josh Bleecher Snyder created

6a41350 shelley/ui: add collapsible conversations drawer

Click to expand commit body
Prompt: make the conversations drawer collapsible. Currently, it works
differently on narrow and wide screens. Continue having it work
differently, but have an affordance for collapsibility. Maybe it's the
same button, but it does slightly different things on a wider screen.

Fixes https://github.com/boldsoftware/shelley/issues/4

On desktop (≥768px):
- Add collapse button (double chevron «) in drawer header
- When collapsed, drawer is hidden and expand button (») appears in main header before title
- Drawer can be expanded/collapsed by clicking the respective buttons

On mobile (<768px):
- Behavior unchanged - drawer slides in/out as overlay
- Collapse/expand buttons are hidden on mobile (uses existing hamburger menu pattern)

The collapsed state is persisted in React state and is independent of
the mobile drawer open/close state.

Philip Zeyliger created

6a3d18e shelley: show working directory in bash tool output

Click to expand commit body
Prompt: change the bash tool output (at least in the UI) to indicate the working diretory the tool was run from.

Add working directory to bash tool display in the UI:
- Backend: Add BashDisplayData struct with WorkingDir field, include it
  in ToolOut.Display for both foreground and background commands
- Frontend: Show working directory in collapsed header (truncated with
  ellipsis) and in expanded details view
- CSS: Add styling for .bash-tool-cwd class

The working directory is shown as 'in /path/to/dir' after the command
in the collapsed view, and as a separate 'Working Directory:' section
when expanded.

Philip Zeyliger created

f26efeb shelley/ui: improve reconnection logic

Click to expand commit body
Prompt: When Shelley ui gets disconnected I don't think it does a great job reconnecting. Fix that. Use signals from the browser that it's being looked at to trigger th retry loop. And retry at some frequency regardless. Instead of "agent is working" show "disconnected" with a retry in the relevant place.

- Use browser visibility, focus, and online events to trigger reconnect
  when disconnected
- Add periodic retry every 30 seconds even after initial retries fail
- Use faster backoff delays (1s, 2s, 5s) before showing disconnected state
- Clear periodic retry interval when connection succeeds or manual retry
  is triggered
- Fix guard in handleManualReconnect to prevent duplicate connections

Philip Zeyliger created

fd6c392 shelley/ci: switch GitHub Actions from npm to pnpm

Click to expand commit body
Prompt: https://github.com/boldsoftware/shelley/actions/runs/20923684872/job/60115676273 is busted. fix it.

Update test.yml and release.yml workflows to use pnpm instead of npm,
matching the recent switch to pnpm in the ui directory.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Philip Zeyliger and Claude created

955ecfe shelley/ui: switch from npm to pnpm

Click to expand commit body
Prompt: switch shelley to use pnpm instead of npm. Don't forget to change any github workflows you find.

- Update package.json to use pnpm@10.28.0 as packageManager
- Replace package-lock.json with pnpm-lock.yaml
- Update Makefile to use pnpm install --frozen-lockfile
- Update test_ci.sh to use pnpm commands
- Update GitHub workflows (shelley-tests.yml, build-exeuntu.yml)
  to use pnpm/action-setup@v4
- Update documentation (AGENT.md, AGENT_TESTING.md, e2e/README.md)
- Update embedfs.go error messages
- Update bin/run_formatters.sh to use pnpm exec

Philip Zeyliger created

e5c9eac shelley/ui: default to simple diff view, feature flag for Monaco

Click to expand commit body
Prompt: In a sort of recent commit, we switched the patch tool output to
use Monaco diffs. These seem to not be working well yet. Let's reintroduce
the old simple diff view. Keep the Monaco code behind a feature flag that
can be set with local storage so I can keep trying the new thing.

Use localStorage.setItem('shelley-use-monaco-diff', 'true') to enable
the Monaco diff view. The simple text-based diff view is now the default
as the Monaco diff had some issues.

Both views are still available:
- Simple diff: default, shows unified diff with syntax highlighting
- Monaco diff: feature-flagged, side-by-side view with commenting

Philip Zeyliger created

5a98102 typos: s/AGENT.md/AGENTS.md/

Philip Zeyliger created

e27497d shelley: AGENT.md -> AGENTS.md

Click to expand commit body
Oops.

Josh Bleecher Snyder created

5c19a2b shelley/server: read agents.md

Click to expand commit body
This was an oversight. Forgot the 's'.

Next up: move the default agent.md to agents.md.

Josh Bleecher Snyder created

4d2428c shelley: fix typo in agent.md

Josh Bleecher Snyder created

b7c2972 shelley: skip messages with zero usage when calculating context window

Click to expand commit body
Prompt: In a new worktree work on the usage bar indicator again. In a given conversation there are some messages that don't have usage. I want you to use the last message that DOES have usage.

When calculating context window size for the usage bar indicator,
skip messages that have usage_data with all zeros (e.g., user messages,
system messages, tool messages). Previously the code only checked if
usage_data was nil, but these message types often have zero-valued
usage data populated.

Now the code continues walking backward through messages until it
finds one with actual non-zero context window usage.

Philip Zeyliger created

e3bb6ad shelley/ui: fix Monaco model leak causing Firefox crash

Click to expand commit body
Prompt: fix and add a test for the following new Shelley inline diff view causes the page to break in Firefox; it goes completely blank and then I get this error:
Error: ModelService: Cannot add model because it already exists!

The inline diff view in PatchTool was crashing Firefox with 'Cannot add
model because it already exists!' when collapsing and expanding the diff.

Root cause: Monaco editor models were created but never disposed during
cleanup. When the component unmounted and remounted (or the useEffect
re-ran), new models were created with potentially conflicting URIs.

Fix:
- Track Monaco models in a ref (modelsRef)
- Dispose models in the cleanup function alongside the editor
- Defensively check for and dispose existing models before creating new
  ones (in case of timing issues)

Also added:
- 'patch success' command to predictable model (uses overwrite operation)
- E2E test that verifies collapse/expand cycles don't cause errors

Philip Zeyliger created

471497d shelley: don't submit on Enter for mobile input

Click to expand commit body
I'm not convinced this is going to work for me, but let's
try it and see.

Prompt: In a new worktree, make the mobile input for enter not send
the message since the send button is right there.

On mobile devices, pressing Enter should create a newline instead of
submitting the message. Users have the send button readily available
for submission, and newlines are common in mobile messaging.

Philip Zeyliger created

0b7e150 shelley: Add hover highlighting and comment indicator to modal diff viewer

Click to expand commit body
Prompt: The hovering looks BEAUTIFUL in the patch tool diffs. Can you also make it work for the modal diff viewer we have?

- Apply same hover highlighting pattern to DiffViewer component
- Show comment indicator glyph only in comment mode (not edit mode)
- Clear hover decorations when switching to edit mode
- Enable glyph margin on non-mobile devices
- Use separate CSS class names (diff-viewer-*) to avoid conflicts

Philip Zeyliger created

de470d9 shelley: Add hover highlighting and comment indicator to Monaco diff view

Click to expand commit body
Prompt: in a new worktree, make it so that when i mouse over a line in the monaco diff view, that line is highlighted. Maybe there's a subtle indicator that you can add a comment if you click on it.

- Use Monaco's decoration API to highlight the hovered line with a subtle blue tint
- Show a comment bubble icon in the glyph margin when hovering over a line
- Enable glyph margin on non-mobile devices for the comment indicator
- Clear decorations when mouse leaves the editor
- Works with both light and dark themes

Philip Zeyliger created