Skip to content

feat(terminal): add per-pane workspace selection#97

Open
zeemy23 wants to merge 14 commits intostrantalis:mainfrom
zeemy23:feat/per-pane-workspace
Open

feat(terminal): add per-pane workspace selection#97
zeemy23 wants to merge 14 commits intostrantalis:mainfrom
zeemy23:feat/per-pane-workspace

Conversation

@zeemy23
Copy link
Copy Markdown
Collaborator

@zeemy23 zeemy23 commented Feb 5, 2026

Summary

  • Allow each terminal pane to be tied to a different workspace via a compact dropdown selector in the pane header
  • When splitting a pane, the new pane inherits the source pane's workspace override
  • Cross-workspace tab drags are silently prevented to avoid mixing terminal contexts
  • Workspace selector only appears when 2+ non-archived workspaces exist
  • Override is cleared when selecting the global workspace (clean storage)

Files Changed

File Changes
types.ts Added optional workspaceId / workspaceName to TerminalLayoutNode
TerminalWorkspace.svelte Updated PaneNode type, normalizeNode, buildPane, handleAddTab, handleSplitPane, handleCloseTab, handleClosePane; added handleChangePaneWorkspace; guarded cross-workspace tab drags
TerminalLayoutNode.svelte Added onChangePaneWorkspace prop, workspace store import, effective workspace computation, dropdown selector UI, CSS

Test plan

  • Open app with 2+ workspaces — verify dropdown appears in pane header
  • Open app with 1 workspace — verify no dropdown appears
  • Split a pane vertically — both panes should show the same workspace
  • Change one pane's workspace via dropdown — old terminal closes, new terminal opens in selected workspace
  • Add a tab in the overridden pane — new terminal created in overridden workspace, not global
  • Split the overridden pane — new pane inherits the override
  • Close/reopen the workspace — verify overrides are persisted in layout
  • Drag tab between panes with different workspaces — verify drag is silently prevented
  • Drag tab between panes with same workspace — verify it works normally

🤖 Generated with Claude Code

zeemy23 and others added 10 commits February 5, 2026 15:22
Add a Skills section to Settings that discovers, displays, edits, and
syncs Agent Skills (SKILL.md files) across Claude Code, Codex, Copilot,
and Agent directories. Supports global and project-scoped skills with
CRUD operations, cross-tool sync, bulk sync all, and auto-sync on create.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add an X button to the detail pane header for closing it, and show full
tool names (Claude Code, Codex, Copilot, Agents) on hover over the
single-letter badges.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace native title attributes with CSS pseudo-element tooltips that
appear instantly on hover, showing full tool names (Claude Code, Codex,
Copilot, Agents).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a floating button in the bottom-right corner of terminal panes that
appears when hovering and the terminal is scrolled up from the bottom.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add directory traversal validation for dirName in save/delete paths
- Preserve source file permissions in copyDir during sync
- Reload skills reactively when active workspace changes
- Relax dirName regex to allow leading hyphens/underscores
- Add comprehensive test suite for skills service

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add blank line between embedded and regular fields in SkillContent
- Use errors.New instead of fmt.Errorf for static error strings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow each terminal pane to be tied to a different workspace via a
compact dropdown in the pane header. When splitting, the new pane
inherits the source pane's workspace override. Cross-workspace tab
drags are silently prevented to avoid mixing terminal contexts.

- Add optional workspaceId/workspaceName fields to TerminalLayoutNode
- Use pane-level effective workspace for terminal create/close calls
- Add handleChangePaneWorkspace handler that swaps all terminals
- Show workspace selector only when 2+ non-archived workspaces exist
- Guard handleTabDrop and handleTabSplitDrop against cross-workspace moves
- Clear override when selecting the global workspace (no-op storage)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Feb 5, 2026

Greptile Overview

Greptile Summary

This PR introduces per-pane workspace overrides for the terminal layout, adding workspaceId/workspaceName to layout nodes and a compact workspace selector in each pane header. It threads the effective workspace into TerminalPane, ensures pane splits inherit the source pane override, and blocks tab drag/drop actions across panes that resolve to different workspaces to avoid mixing terminal contexts.

It also includes a larger set of changes adding a Skills manager (backend service + Wails bindings + frontend UI) and a terminal scroll-to-bottom affordance.

Blocking issue: when a tab is split-dropped into a new pane, the newly created pane does not carry over the source pane’s workspace override, so the new pane can incorrectly fall back to the global workspace for subsequent terminal creation/closure logic.

Confidence Score: 4/5

  • Mostly safe to merge, but contains one functional bug in per-pane workspace handling during tab split-drop.
  • The per-pane workspace selector and effective workspace plumbing look consistent, but handleTabSplitDrop creates a new pane without propagating the workspace override, which breaks the intended invariant and can route terminal operations to the wrong workspace.
  • wails-ui/workset/frontend/src/lib/components/TerminalWorkspace.svelte

Important Files Changed

Filename Overview
pkg/worksetapi/skills_service.go Adds skills service for listing/reading/writing/syncing SKILL.md across tool dirs; no issues found in this PR context.
wails-ui/workset/frontend/src/lib/components/TerminalLayoutNode.svelte Adds per-pane workspace selector UI and uses effective workspace for TerminalPane; depends on pane nodes carrying workspace override correctly.
wails-ui/workset/frontend/src/lib/components/TerminalWorkspace.svelte Implements per-pane workspace overrides, inheritance on split, and blocks cross-workspace drags; bug: split-drop-created pane doesn’t inherit workspace override.
wails-ui/workset/frontend/src/lib/components/settings/sections/SkillManager.svelte Adds full SkillManager UI for creating/editing/deleting/syncing SKILL.md across tools; no issues found.

Sequence Diagram

sequenceDiagram
  participant User
  participant TLN as TerminalLayoutNode
  participant TW as TerminalWorkspace
  participant TS as TerminalService

  User->>TLN: Change workspace selector
  TLN->>TW: onChangePaneWorkspace(paneId,newWsId,newWsName)
  TW->>TS: closeTerminal(oldWsId, terminalId)
  TW->>TS: createWorkspaceTerminal(newWsId)
  TS-->>TW: terminalId
  TW-->>TLN: layout updated

  User->>TLN: Drag tab A -> B
  TLN->>TW: onTabDrop(targetPaneId,targetIndex)
  TW->>TW: compare srcWs vs tgtWs

  User->>TLN: Split-drop dragged tab
  TLN->>TW: onTabSplitDrop(targetPaneId,direction,position)
  TW->>TW: newPane created (missing workspaceId override)
  TW-->>TLN: new pane falls back to global workspace
Loading

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Feb 5, 2026

Additional Comments (1)

wails-ui/workset/frontend/src/lib/components/TerminalWorkspace.svelte
Split-drop loses workspace override

In handleTabSplitDrop, the newly created pane from a dragged tab doesn’t inherit the source pane’s workspace override. When dragging within the same overridden workspace, the new pane will fall back to the global workspace (TerminalLayoutNode computes effectiveWorkspaceId from node.workspaceId || workspaceId), so terminals in the new pane can be opened/closed against the wrong workspace.

Consider setting workspaceId/workspaceName on newPane (e.g. from srcPane?.workspaceId/workspaceName) when creating it.

Prompt To Fix With AI
This is a comment left during a code review.
Path: wails-ui/workset/frontend/src/lib/components/TerminalWorkspace.svelte
Line: 778:783

Comment:
**Split-drop loses workspace override**

In `handleTabSplitDrop`, the newly created pane from a dragged tab doesn’t inherit the source pane’s workspace override. When dragging within the same overridden workspace, the new pane will fall back to the global workspace (`TerminalLayoutNode` computes `effectiveWorkspaceId` from `node.workspaceId || workspaceId`), so terminals in the new pane can be opened/closed against the wrong workspace.

Consider setting `workspaceId/workspaceName` on `newPane` (e.g. from `srcPane?.workspaceId/workspaceName`) when creating it.

How can I resolve this? If you propose a fix, please make it concise.

zeemy23 and others added 2 commits February 5, 2026 16:05
…buttons

Reset browser default select styling with appearance: none, display: flex,
and explicit line-height to match the 28px action buttons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove display:flex, appearance:none, and line-height overrides that
fought with browser select rendering. Keep box-sizing:border-box and
explicit height to let flex parent alignment work naturally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@strantalis
Copy link
Copy Markdown
Owner

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 94b6039858

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +142 to +144
func getSkillFromPath(scope, dirName, tool, projectRoot string) (SkillContent, error) {
path, err := resolveSkillPathWithRoot(scope, dirName, tool, projectRoot)
if err != nil {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject path traversal in GetSkill requests

getSkillFromPath resolves and reads dirName without calling validateDirName, while SaveSkill/DeleteSkill do validate; this allows a crafted dirName like ../../.. to escape the intended skills directory and read arbitrary SKILL.md files reachable from the joined path. This is a security regression introduced by the new read API path and should enforce the same traversal guard before resolveSkillPathWithRoot.

Useful? React with 👍 / 👎.

Comment on lines +232 to +234
func syncSkillAtPath(scope, dirName, fromTool string, toTools []string, projectRoot string) error {
src, err := resolveSkillPathWithRoot(scope, dirName, fromTool, projectRoot)
if err != nil {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate dirName before syncing skill directories

syncSkillAtPath also skips validateDirName, so a malicious dirName can make srcDir/dstDir resolve outside the skill roots and then copyDir recursively copies unintended directories. In environments exposing this API through the UI bridge, this can copy arbitrary local content into tool skill folders and should be blocked with the same validation used by save/delete.

Useful? React with 👍 / 👎.

Merge origin/main and fix split-drop workspace override bug where newly
created panes from tab split-drops did not inherit the source pane's
workspace override, causing terminals to incorrectly use the global
workspace.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@zeemy23 zeemy23 requested a review from strantalis as a code owner February 6, 2026 21:38
Extract pure layout-tree operations and keyboard navigation helpers
from TerminalWorkspace.svelte into terminal/layoutTree.ts. This brings
the file under 1000 lines and reduces function complexity below the
max-15 threshold.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants