diff --git a/src/features/team-mode/team-layout-tmux/close-team-member-pane.test.ts b/src/features/team-mode/team-layout-tmux/close-team-member-pane.test.ts
new file mode 100644
index 000000000..7a13f960f
--- /dev/null
+++ b/src/features/team-mode/team-layout-tmux/close-team-member-pane.test.ts
@@ -0,0 +1,62 @@
+///
+
+import { afterEach, beforeEach, describe, expect, test, mock, spyOn } from "bun:test"
+
+import * as sharedModule from "../../../shared"
+import * as sharedTmuxModule from "../../../shared/tmux"
+import { closeTeamMemberPane } from "./close-team-member-pane"
+
+const closeTmuxPaneMock = mock(async (): Promise => true)
+const logMock = mock(() => undefined)
+
+describe("closeTeamMemberPane", () => {
+ afterEach(() => {
+ mock.restore()
+ })
+
+ beforeEach(() => {
+ closeTmuxPaneMock.mockClear()
+ logMock.mockClear()
+
+ closeTmuxPaneMock.mockResolvedValue(true)
+ spyOn(sharedModule, "log").mockImplementation(logMock)
+ spyOn(sharedTmuxModule, "closeTmuxPane").mockImplementation(closeTmuxPaneMock)
+ })
+
+ test("#given member has both tmuxPaneId and tmuxGridPaneId #when closeTeamMemberPane runs #then close is invoked for both ids (2 calls) and returns true when either succeeds", async () => {
+ // given
+ closeTmuxPaneMock.mockResolvedValueOnce(false)
+ closeTmuxPaneMock.mockResolvedValueOnce(true)
+
+ // when
+ const result = await closeTeamMemberPane({ tmuxPaneId: "%42", tmuxGridPaneId: "%84" })
+
+ // then
+ expect(result).toBe(true)
+ expect(closeTmuxPaneMock).toHaveBeenCalledTimes(2)
+ expect(closeTmuxPaneMock).toHaveBeenCalledWith("%42")
+ expect(closeTmuxPaneMock).toHaveBeenCalledWith("%84")
+ })
+
+ test("#given member has only tmuxPaneId #when closeTeamMemberPane runs #then close is invoked once and returns true when it succeeds", async () => {
+ // when
+ const result = await closeTeamMemberPane({ tmuxPaneId: "%42" })
+
+ // then
+ expect(result).toBe(true)
+ expect(closeTmuxPaneMock).toHaveBeenCalledTimes(1)
+ expect(closeTmuxPaneMock).toHaveBeenCalledWith("%42")
+ })
+
+ test("#given both closes fail #when closeTeamMemberPane runs #then returns false", async () => {
+ // given
+ closeTmuxPaneMock.mockResolvedValue(false)
+
+ // when
+ const result = await closeTeamMemberPane({ tmuxPaneId: "%42", tmuxGridPaneId: "%84" })
+
+ // then
+ expect(result).toBe(false)
+ expect(closeTmuxPaneMock).toHaveBeenCalledTimes(2)
+ })
+})
diff --git a/src/features/team-mode/team-layout-tmux/close-team-member-pane.ts b/src/features/team-mode/team-layout-tmux/close-team-member-pane.ts
new file mode 100644
index 000000000..83a3b8cb6
--- /dev/null
+++ b/src/features/team-mode/team-layout-tmux/close-team-member-pane.ts
@@ -0,0 +1,31 @@
+///
+
+import type { RuntimeStateMember } from "../types"
+
+type TeamMemberPaneIds = Pick
+
+export async function closeTeamMemberPane(member: TeamMemberPaneIds): Promise {
+ const paneIds = [member.tmuxPaneId, member.tmuxGridPaneId].filter((paneId): paneId is string => paneId !== undefined && paneId.length > 0)
+ if (paneIds.length === 0) {
+ return false
+ }
+
+ const [{ log }, { closeTmuxPane }] = await Promise.all([
+ import("../../../shared"),
+ import("../../../shared/tmux"),
+ ])
+
+ const results = await Promise.all(paneIds.map(async (paneId) => {
+ try {
+ return await closeTmuxPane(paneId)
+ } catch (error) {
+ log("[closeTeamMemberPane] FAILED", {
+ paneId,
+ error: error instanceof Error ? error.message : String(error),
+ })
+ return false
+ }
+ }))
+
+ return results.some(Boolean)
+}