Feature
Support the ChatGPT/Codex desktop app as a UI for Codex running inside a coop VM over Remote SSH. Users should be able to keep the desktop interface, including features such as speech input, while builds, shell commands, and project files stay in the guest. Speech input is a motivation for this workflow, not a capability independently verified in this investigation.
coop already generates an SSH alias with coop ssh-config. The desktop app can connect through that alias. The integration needs reliable guest authentication and a convenient way to discover or register the VM in the app.
Reproduced limitation
On a fresh macOS/Lima VM built from a rebuilt default image, with guest Codex CLI 0.154.0 installed through the native installer:
- Configure coop with
[codex] auth = "chatgpt".
- Start a VM and generate its SSH configuration.
- Add the generated SSH host in the desktop app and select a guest project directory.
- Initiate the remote connection's Codex login flow and complete browser sign-in.
The Remote SSH connection succeeds, but browser sign-in reports:
Sign-in completed but credentials could not be saved locally.
Error code: persist_failed
failed to write OAuth tokens to keyring: Couldn't access platform secure storage: SS error: result not returned from SS API
The guest selects cli_auth_credentials_store = "keyring". The failure is saving the OAuth credentials in the guest, after SSH authentication and browser account sign-in succeed.
Evidence and diagnosis
In ChatGPT authentication mode, coop codex uses the codex-account wrapper to establish a D-Bus session, prompt for a guest keyring password, unlock GNOME Keyring, and launch Codex in that session.
The desktop app starts codex app-server directly through the remote login shell. That path bypasses the wrapper and does not inherit its unlocked keyring session.
On a VM with an existing encrypted keyring, remote server startup also stalled before its control socket became available. A bounded comparison probe showed that the server became ready with an existing unlocked keyring session, while the ordinary SSH environment did not become ready within the probe interval. On the fresh VM, server startup succeeded, but credential persistence failed. These are distinct failure states and should remain distinguishable in diagnostics.
Older coop images also use a Codex installation layout rejected by the native daemon-management command. Rebuilding the image resolved that separate prerequisite; merely creating another instance from an older image did not.
Research and implementation scope
Guest authentication and server lifecycle
- Design a managed D-Bus/keyring session and app-server lifecycle that supports non-interactive desktop launches without borrowing another process's environment.
- Define an explicit unlock flow when needed. Missing, locked, and unavailable keyrings should produce bounded, actionable failures.
- Support reconnects without requiring an unrelated terminal session to remain open.
- Cover VM restart, server crash, token refresh, logout, simultaneous CLI/desktop use, and cleanup after failed startup or destroy.
- Prevent repeated connection attempts from leaving duplicate servers or conflicting socket owners.
- Document native-install prerequisites and migration for existing images.
- Assess compatibility with OpenAI credential-proxy mode separately from ChatGPT account authentication.
Preserve existing credential-storage guarantees. Do not silently fall back to plaintext credentials, copy host account credentials, or persist the keyring password to bypass unlocking. Any intentional authentication-policy change needs an explicit design decision.
Desktop host discovery and registration
Investigate whether coop can make a VM available in the desktop app automatically, analogous to coop ssh-config:
- Verify the app's documented discovery of concrete SSH aliases and whether writing the alias is sufficient for it to appear without manual hostname entry.
- Distinguish host discovery from enabling a connection, selecting a project, and authenticating. Do not assume discovery completes those steps.
- Look for a supported CLI, deep link, or API for registering/opening an SSH host and guest project. If available, evaluate a coop command or extension to the editor integration that uses it.
- Prefer supported interfaces; do not depend on editing undocumented application databases or private settings formats.
- Define idempotent behavior for repeated setup, app-not-installed cases, VM restarts and changed SSH ports, VM recreation, and cleanup without deleting unrelated user connections.
- If discovery is the only supported mechanism, document the remaining app steps and make the generated SSH alias easy to find.
Acceptance criteria
- A fresh supported VM can be discovered or registered through the documented coop workflow.
- The desktop app connects, guest credentials are saved to the intended store, and a real remote task completes.
- Locked/missing keyrings, reconnects, restart, refresh/logout, and concurrent CLI/desktop use behave as documented.
- Failed starts and VM teardown leave no unmanaged server processes or stale registration owned by the integration.
- Documentation clearly separates desktop login, guest authentication, and execution location.
- Validate desktop-to-Lima end to end and backend-shared authentication/lifecycle behavior on Firecracker where applicable; state untested combinations.
References
Additional reproduction: both authentication methods fail
The same fresh-VM workflow was subsequently tried with both browser-based ChatGPT sign-in and device-code sign-in. Browser sign-in repeated the persist_failed credential-storage failure. Device-code sign-in reported:
failed to write OAuth tokens to keyring: Platform secure storage failure: zbus error: org.freedesktop.DBus.Error.UnknownMethod: Object does not exist at path "/org/freedesktop/secrets/collection/login"
This error identifies a missing Secret Service login-collection object at the time of credential persistence. It does not by itself establish why the collection is absent, whether it was never initialized, or whether the server is using a different session/service instance. Changing the OAuth sign-in method does not resolve the shared credential-storage failure.
The investigation should cover collection creation and default-collection selection in addition to session-bus reachability and unlocking. Verify which Secret Service instance the app server uses, whether that instance exposes the intended collection, and how a fresh headless guest initializes it without relying on a graphical prompt. Test both browser and device-code sign-in against fresh, locked, and already-unlocked guest keyrings.
Feature
Support the ChatGPT/Codex desktop app as a UI for Codex running inside a coop VM over Remote SSH. Users should be able to keep the desktop interface, including features such as speech input, while builds, shell commands, and project files stay in the guest. Speech input is a motivation for this workflow, not a capability independently verified in this investigation.
coop already generates an SSH alias with
coop ssh-config. The desktop app can connect through that alias. The integration needs reliable guest authentication and a convenient way to discover or register the VM in the app.Reproduced limitation
On a fresh macOS/Lima VM built from a rebuilt default image, with guest Codex CLI 0.154.0 installed through the native installer:
[codex] auth = "chatgpt".The Remote SSH connection succeeds, but browser sign-in reports:
The guest selects
cli_auth_credentials_store = "keyring". The failure is saving the OAuth credentials in the guest, after SSH authentication and browser account sign-in succeed.Evidence and diagnosis
In ChatGPT authentication mode,
coop codexuses thecodex-accountwrapper to establish a D-Bus session, prompt for a guest keyring password, unlock GNOME Keyring, and launch Codex in that session.The desktop app starts
codex app-serverdirectly through the remote login shell. That path bypasses the wrapper and does not inherit its unlocked keyring session.On a VM with an existing encrypted keyring, remote server startup also stalled before its control socket became available. A bounded comparison probe showed that the server became ready with an existing unlocked keyring session, while the ordinary SSH environment did not become ready within the probe interval. On the fresh VM, server startup succeeded, but credential persistence failed. These are distinct failure states and should remain distinguishable in diagnostics.
Older coop images also use a Codex installation layout rejected by the native daemon-management command. Rebuilding the image resolved that separate prerequisite; merely creating another instance from an older image did not.
Research and implementation scope
Guest authentication and server lifecycle
Preserve existing credential-storage guarantees. Do not silently fall back to plaintext credentials, copy host account credentials, or persist the keyring password to bypass unlocking. Any intentional authentication-policy change needs an explicit design decision.
Desktop host discovery and registration
Investigate whether coop can make a VM available in the desktop app automatically, analogous to
coop ssh-config:Acceptance criteria
References
docs/codex-integration.md,docs/editor.mdscripts/guest/codex-account.shAdditional reproduction: both authentication methods fail
The same fresh-VM workflow was subsequently tried with both browser-based ChatGPT sign-in and device-code sign-in. Browser sign-in repeated the
persist_failedcredential-storage failure. Device-code sign-in reported:This error identifies a missing Secret Service login-collection object at the time of credential persistence. It does not by itself establish why the collection is absent, whether it was never initialized, or whether the server is using a different session/service instance. Changing the OAuth sign-in method does not resolve the shared credential-storage failure.
The investigation should cover collection creation and default-collection selection in addition to session-bus reachability and unlocking. Verify which Secret Service instance the app server uses, whether that instance exposes the intended collection, and how a fresh headless guest initializes it without relying on a graphical prompt. Test both browser and device-code sign-in against fresh, locked, and already-unlocked guest keyrings.