Chat-slot agents were being persisted as durable entries in openclaw.json,
causing spurious workspace directories (e.g. chat-slot-main-1) to appear.
Only explicit workspace creation via init now creates durable agent entries.
Workspace discovery and session routing ignore chat-slot internals.
Server-side WebSocket connections should not set Origin (a browser security
concept). The header caused the gateway to treat the web runtime as a browser
client, blocking silent local device pairing after device identity auth was
added.
Integrate version tracking for DenchClaw and OpenClaw into the telemetry system. The versions are now read from the package.json and environment variables, and are included in the PostHog client initialization and telemetry events. This enhancement allows for better monitoring and analytics of the versions in use.
Backend support for multi-session chat: /api/chat/runs endpoint for parent/subagent run status, subagent registry for reading run state, and cascade stop to abort child sessions when stopping a parent.
Darken --color-sidebar-bg to create more visual hierarchy between
the sidebar and main content area, inspired by animclaw's approach.
Light: #f5f5f4 → #ebebea (delta 15 from main-bg, was 5)
Dark: #141413 → #0c0c0b (delta 10 from main-bg, was 2)
- Remove framer-motion animations from hero greeting, input bar, and
suggestion buttons so they render instantly
- Fix SSR hydration mismatch by deferring hero render until client mount
- Always create a "New Chat" tab on fresh load and when closing last tab
Made-with: Cursor
- Add 'sidebar-animate' class to sidebar elements for improved transition effects.
- Change accent color scheme to a green palette for better visual consistency.
- Ensure sidebar animations are disabled during resizing for smoother user experience.
- Replace custom RowActionsMenu and Columns menu with shared DropdownMenu component
- Restyle ViewTypeSwitcher from bordered button group to subtle rounded tabs
- Simplify DataTable toolbar: remove button borders, tighten spacing
- Use rounded-2xl for compact sidebar chat input, keep rounded-3xl for main
Made-with: Cursor
- Simplify sidebar visibility logic by removing unnecessary variables.
- Enhance sidebar width handling with smooth transitions for collapsed states.
- Update chat sidebar to adjust width dynamically based on its open state.
- Refactor component structure for better readability and maintainability.
- Fix session load error by handling 404 gracefully
- Unify sidebar backgrounds to stone-100, make main-bg fully opaque
- Add divider + gap before new tab button, hide when last tab active
- Make tab hover cursor default, new tab button fully rounded
- Remove glass background from chat header
- Replace show/hide output button with clickable step labels
- Fix chat sidebar header to use solid background
- Set min-height on tab bar wrapper for loading state
Made-with: Cursor
- Tab bar uses distinct strip background with curved connectors on active tab
- "+" button creates new chat tabs (like Chrome new tab)
- Markdown links intercepted for in-app navigation and anchor scrolling
- Fix borderColor shorthand conflict in database-viewer spinner
- Align sidebar header height with tab bar
Made-with: Cursor
- Move chat history from left sidebar to floating popover on tab bar
- Add dench-ui components (Button, Card, Input, Label, Switch) with deps
- Glassmorphism styling for all dropdowns/context menus with dark mode
- Chrome-style active tab that merges with content area
- Align sidebar header with tab bar (34px)
- Condense sidebar header to single line
- Move sidebar expand button into tab bar
- Add next-themes for proper dark mode with system preference support
- Add Tailwind v4 class-based dark mode via @custom-variant
- Add dench-ui CSS tokens (light + dark)
- Restore pointer cursor for all interactive elements
- New chat button always visible in tab bar
- "Delete this chat" label in dropdown menu
Made-with: Cursor
parseSimpleYaml only matched `key: value` lines (regex required `.+`
after the colon), so `permissions:` followed by indented `- database`
list items was never parsed. This caused app bridge methods like
db.query to always fail with "Unknown method or insufficient
permissions" even when the app manifest granted the database permission.
Change the regex to `.*` to also match keys with no inline value, then
collect subsequent indented `- item` lines into an array.
Closes#87
- Refactor WebSocket connection logic to dynamically fetch the port from the server, improving flexibility.
- Introduce global variables to manage WebSocket server state and port, allowing for better control and error handling.
- Update terminal drawer component to use the new port fetching mechanism, ensuring consistent connection behavior.
The terminal drawer was flickering closed immediately after opening because
the spawned shell process exited with code 1, triggering handleExited →
closeTerminal → onClose which unmounted the entire drawer within ~500ms.
- Stop auto-closing the drawer on process exit so users can see error output
- Extract URL param building into testable buildWorkspaceSyncParams function
that correctly includes terminal state, preventing param stripping on navigation
- Add 21 tests covering terminal param preservation across navigation scenarios
Without error handling, if node-pty require or pty.spawn throws (bad
permissions, missing cwd, stale server), the client gets no response and
the terminal hangs with a blinking cursor. Now sends an exit event back.
fitAddon.fit() was called synchronously on mount before the browser laid
out the container, sending 0-dimension cols/rows to the PTY. The shell
would hang without displaying a prompt. Now defers WS connection by 50ms,
re-fits after the shell reports ready, and shows an error if WS fails.
xterm.js frontend + node-pty WebSocket server spawning the user's real shell,
with drag-to-resize drawer, multi-terminal tabs, live theme sync, and URL state.
- Convert sync filesystem and DuckDB operations to async across API routes,
workspace lib, and active-runs to prevent event loop blocking during tree
discovery, object lookups, and database queries
- Add "tags" field type for free-form string arrays with parse-tags utility,
TagsBadges/TagsInput UI components, filter operators, and CRM skill docs
- Preserve rich text formatting (bold, italic, code, @mentions) in user chat
messages by sending HTML alongside plain text through the transport layer
- Detect empty-stream errors, improve agent error emission, and add file
mutation queues for concurrent write safety in active-runs
- Add pre-publish standalone node_modules verification in deploy script
checking serverExternalPackages are present
- Extract syncManagedSkills and discoverWorkspaceDirs for multi-workspace
skill syncing, add ensureSeedAssets for runtime app dir
- Bump version 2.1.1 → 2.1.4
sessions.patch for verboseLevel=full was called before the agent RPC
created the session, so it silently failed on new chats. Tool events
were never emitted and the frontend only showed brief text responses.
Now patches both before (for existing sessions) and after the agent RPC
(for newly created sessions). Also adds SSE keepalive to the POST /api/chat
stream to prevent connection drops during long tool executions, and removes
the unused legacy CLI spawn codepath.
The root layout called getOrCreateAnonymousId() in a Server Component
without marking the route as dynamic. Next.js treated it as static,
pre-rendering the developer's UUID into the standalone build shipped
via npm — so every `npx denchclaw` user shared the same PostHog identity.
- Add `export const dynamic = "force-dynamic"` to root layout
- Replace `process.env.HOME || "~"` fallback with `homedir()` in web
telemetry and posthog-analytics plugin (Node.js path.join doesn't
expand "~", creating a relative path under cwd instead)
The URL sync effect and hydration effect run in the same React render
cycle. Since React state updates (setActivePath) are batched, the URL
sync effect still saw activePath=null and pushed "/", stripping all
query params. This caused an alternating refresh bug where odd refreshes
showed the homepage and even refreshes worked correctly.
Skip the URL sync effect for one render after hydration completes, giving
React state time to update before the effect writes the URL.
findObjectDir only searched the workspace root and one level deep, so objects
nested inside category folders (e.g. marketing/influencer/) were not discovered
by the views API. This caused saved views, active_view, and view_settings to
silently return empty for any object beyond depth 1.
Replace the single-level scan with a depth-limited recursive search (max 4
levels), skipping known heavy directories (node_modules, .git, .next, etc.).
The sidebar tree builder (buildTree in tree/route.ts) already walks recursively,
so this brings findObjectDir in line with the rest of the workspace discovery.
Parse cron/every/at schedules and project all occurrences within the
visible date range so the calendar shows upcoming runs, not just the
next one. Display scheduled times on event chips.
Remove scattered router.replace("/") calls in favor of the URL sync effect.
Add popstate listener to restore app state on browser back/forward.
Preserve object-view params across shell-level URL updates.
Fix ObjectView overwriting URL params on initial mount.
Update package versions for denchclaw and dench to 2.0.16. Refactor feedback API to convert chat lines into PostHog-compatible messages, preserving chronological order and including tool calls and results. Improve test cases to reflect changes in message handling.
Add workspace mock to agent-runner tests, skip PostHog pageviews on cron paths to reduce noise, document web-chat storage path in CRM skill, and include cursor plans and build info.
Show an animated hero screen with rotating prompt suggestion cards when the chat is empty, using framer-motion for layout transitions. Add setText method to ChatEditor for programmatic content insertion.