Skip to content

desktop: /export saves to the client machine on SSH servers — write into the workspace and show the path #61335

Open

Description

@magiccodelab

Description

On the Windows Desktop app connected to a server over SSH, /export opens the Windows save dialog and writes the file to the local machine. The session workspace is on the SSH host, so there is no way to export the session next to the project. The success toast also shows only the filename, not the chosen path, and offers no Copy action.

The JSON payload itself is already complete: fetchSessionExport pages through every message. This request is about the destination and the path, not the format.

Steps to reproduce

  1. Connect the Desktop app to a remote server over SSH.
  2. Open a session and run /export.
  3. Save the file.
  4. The file appears on the Windows machine; the remote workspace is unchanged.
  5. The success toast shows only the generated filename.

Expected

  • A destination choice: save into the session workspace on the server, or save to this computer.
  • A workspace export writes under the session's location.directory (default suggestion: .opencode/exports/<filename>) and returns the absolute server path.
  • The success UI shows the full path with a Copy action. For local saves, also offer "Show in folder".
  • The default should be the workspace, matching the old cwd behavior and keeping the export next to the project.
  • Filenames should keep Unicode titles instead of falling back to ses_..., and collisions should get a suffix rather than silently overwriting.

Actual

  • The renderer fetches the export and calls platform.saveFile.
  • On Desktop, that opens an Electron save dialog and writes with the local fs.writeFile.
  • The remote SSH workspace is never touched.
  • saveFile returns only a boolean, so the app cannot display or copy the chosen path; the toast uses filename only.

Root cause

  • packages/app/src/session/commands/use-session-commands.tsx:152-181: /export runs entirely in the renderer and calls saveSessionExport.
  • packages/app/src/session/commands/export.ts:64-76: falls back to a browser download, or calls platform.saveFile.
  • packages/desktop/src/main/files/index.ts:73-85: dialog.showSaveDialog plus local fs.writeFile. It has no access to the SSH server's filesystem.
  • packages/app/src/runtime/platform/platform.tsx:79 and packages/desktop/src/renderer/api-types.ts:44: saveFile resolves to boolean, so the absolute path is discarded.
  • packages/app/src/session/commands/export.ts:36-49: the filename slug only keeps [a-z0-9_-], so non-ASCII titles lose their text.

Feasibility

The server already exposes a location-scoped write: packages/protocol/src/groups/fs.ts:78-100 (fs.write), which creates parent directories and returns the absolute path. The app already uses it to upload attachments (packages/app/src/composer/attachments/destination.ts:31). No new protocol is required for a workspace export.

Proposed fix

  • Add a small export dialog with Workspace (server) and This computer, plus the existing JSON format (Markdown is tracked in desktop: /export offers only JSON — expose the Markdown format the TUI already has #55542).
  • For the workspace, POST the serialized content to fs.write with location[directory] = session.location.directory and path = .opencode/exports/<filename>, then use the returned data.path.
  • Show the full path in a toast or result dialog with a Copy action; use showToast({ actions }) or the existing result-dialog pattern.
  • For local saves, extend the desktop save IPC to return the chosen path instead of a boolean, or add a path-returning variant.
  • Default to the workspace, especially when server.isLocal is false.
  • Treat the export as sensitive: it contains the full transcript, so use a git-ignored directory and/or restrictive permissions, and mention that in the UI.

Additional context

Activity

  1. opencodejr commented on Nov 3, 2026

    @opencodejr

    Thanks for the detailed write-up and the code pointers!

    To restate the request: on Desktop, /export should let you choose between saving into the session's workspace on the server (the default, especially for remote/SSH servers, e.g. under .opencode/exports/) and saving to this computer. It should then show the full saved path with a Copy action (plus "Show in folder" for local saves). Filenames should keep Unicode titles, and existing files should get a suffix instead of being overwritten.

    Right now /export runs in the app on your computer and always saves through the local save dialog, so this is a change in behaviour rather than a bug. Maintainers will consider it.

    Related issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions