From 4a622b741293b85ebba1cc61f66fdbf46f0a81b8 Mon Sep 17 00:00:00 2001 From: Steven Vo Date: Mon, 15 Dec 2025 11:11:13 +0700 Subject: [PATCH] New tabs inherit working directory from active tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When creating a new tab (Cmd+T), it now starts in the same directory as the currently active tab, instead of always defaulting to home. ## Changes - Extract cmd:cwd from active tab's first block - Pass inherited cwd to new tab's terminal block via metadata - Only applies to user-created tabs (not initial launch) - Falls back to home directory if no cwd found ## Benefits - More intuitive workflow - stay in your project directory - Reduces need to cd after creating new tabs - Maintains context across tabs 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- pkg/wcore/workspace.go | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/pkg/wcore/workspace.go b/pkg/wcore/workspace.go index 9037b2e5f..b9eddb151 100644 --- a/pkg/wcore/workspace.go +++ b/pkg/wcore/workspace.go @@ -199,16 +199,36 @@ func getTabPresetMeta() (waveobj.MetaMapType, error) { // returns tabid func CreateTab(ctx context.Context, workspaceId string, tabName string, activateTab bool, pinned bool, isInitialLaunch bool) (string, error) { + ws, err := GetWorkspace(ctx, workspaceId) + if err != nil { + return "", fmt.Errorf("workspace %s not found: %w", workspaceId, err) + } + if tabName == "" { - ws, err := GetWorkspace(ctx, workspaceId) - if err != nil { - return "", fmt.Errorf("workspace %s not found: %w", workspaceId, err) - } tabName = "T" + fmt.Sprint(len(ws.TabIds)+len(ws.PinnedTabIds)+1) } + // Try to inherit cwd from the active tab + var inheritedMeta waveobj.MetaMapType + if ws.ActiveTabId != "" && !isInitialLaunch { + activeTab, _ := wstore.DBGet[*waveobj.Tab](ctx, ws.ActiveTabId) + if activeTab != nil && len(activeTab.BlockIds) > 0 { + // Get the first block from the active tab + firstBlock, _ := wstore.DBGet[*waveobj.Block](ctx, activeTab.BlockIds[0]) + if firstBlock != nil { + meta := waveobj.GetMeta(firstBlock) + if cwd, ok := meta[waveobj.MetaKey_CmdCwd].(string); ok && cwd != "" { + // Inherit the cwd for the new tab + inheritedMeta = waveobj.MetaMapType{ + waveobj.MetaKey_CmdCwd: cwd, + } + } + } + } + } + // The initial tab for the initial launch should be pinned - tab, err := createTabObj(ctx, workspaceId, tabName, pinned || isInitialLaunch, nil) + tab, err := createTabObj(ctx, workspaceId, tabName, pinned || isInitialLaunch, inheritedMeta) if err != nil { return "", fmt.Errorf("error creating tab: %w", err) } @@ -221,7 +241,17 @@ func CreateTab(ctx context.Context, workspaceId string, tabName string, activate // No need to apply an initial layout for the initial launch, since the starter layout will get applied after onboarding modal dismissal if !isInitialLaunch { - err = ApplyPortableLayout(ctx, tab.OID, GetNewTabLayout(), true) + newTabLayout := GetNewTabLayout() + // Merge inherited cwd into the terminal block's meta + if len(inheritedMeta) > 0 && len(newTabLayout) > 0 { + if newTabLayout[0].BlockDef.Meta == nil { + newTabLayout[0].BlockDef.Meta = make(waveobj.MetaMapType) + } + for k, v := range inheritedMeta { + newTabLayout[0].BlockDef.Meta[k] = v + } + } + err = ApplyPortableLayout(ctx, tab.OID, newTabLayout, true) if err != nil { return tab.OID, fmt.Errorf("error applying new tab layout: %w", err) }