deckspace.dev / DeckSpace / docs / troubleshooting

Troubleshooting

Symptom, cause, fix. Several entries end in “that does nothing on this machine” — where that is the answer, it is written as the answer.

Every failure on this page is one whose cause is visible in the app’s own code. Where a mechanism is silent by construction — a check that fails without a message, a toggle that reads On while doing nothing — that is said plainly, because the missing message is the reason you are here.

Start with the log

DeckSpace appends one line per event to a plain text file. It is the only place several of these failures leave a trace.

PlatformLog file
macOS~/Library/Logs/DeckSpace/jarvis.log
Linux$XDG_STATE_HOME/deckspace/jarvis.log, defaulting to ~/.local/state/deckspace/jarvis.log
WindowsNo dedicated location. The path is derived from HOME, which Windows normally does not set, so the file lands in the system temp directory under DeckSpace-logs.

Embedded newlines are collapsed to , so every event stays on one line and grep works.

An agent CLI is not detected

Symptom. claude --version works in your terminal, but the CLI shows up grey in Detect installed AI CLIs and DeckSpace will not launch it.

Why. A GUI app launched from Finder or the Dock inherits launchd’s environment, not your shell’s. The minimal PATH it gets has no nvm, asdf, mise, Homebrew or cargo shims in it.

DeckSpace already works around this. Once per app launch it runs $SHELL -lic 'printf %s "$PATH"', merges the result with the directories below, caches the whole thing, and uses it for every pane and every probe.

Always searched, whatever your shell says
~/.local/bin · ~/.grok/bin · ~/.opencode/bin · ~/.cargo/bin · ~/.bun/bin · ~/.npm-global/bin · ~/.deno/bin · ~/.volta/bin · ~/.local/share/mise/shims · ~/bin · /opt/homebrew/bin · /usr/local/bin · /usr/bin · /bin

Three things break that workaround:

CauseWhat you seeFix
Your login shell takes longer than 1.5 seconds to print its PATH. The query is killed at that cap so a slow .zshrc can never block the first pane.Only the fixed list above is searched. Anything installed elsewhere is invisible.Register the CLI by absolute path, or move it onto the fixed list.
The CLI installed itself somewhere neither your shell nor the fixed list mentions.Same.Same.
You installed the CLI while DeckSpace was already running.Still not found. The merged PATH is computed once and cached for the life of the process.Quit and relaunch DeckSpace, then scan again.

Register it by absolute path. Settings → Custom agent CLIs takes a name, a key, and a binary — the binary field accepts either a bare command or a full path such as /usr/local/bin/goose. An absolute path is checked directly and skips PATH resolution entirely.

Detected, but no version next to it

The scan resolves the binary and then runs <path> --version with a hard 3-second cap, because some CLIs hang waiting for a TTY. A CLI that hangs still counts as installed — it just shows no version string. That is cosmetic and does not affect launching.

The same trap hits your API keys

An export ANTHROPIC_API_KEY=… in ~/.zshenv is invisible to a GUI app for the same reason. DeckSpace copies missing variables out of your login shell with env -0, under the same 1.5-second cap, and only for keys the app does not already have — PATH, PWD, OLDPWD, SHLVL and _ are always skipped. If your shell is slow to start, nothing is copied and the agent will fail to authenticate with no explanation on screen.

A pane opens on walk-away and sits there

Symptom. Walk-away is on, the pane launches, the agent starts — and then stops at its own permission prompt and waits for a human who has left.

Why. DeckSpace does not implement autonomy. It passes the flag your CLI publishes for it, and five of the built-in eleven publish none.

Agent CLIWalk-away flag
Aidernone — the toggle does nothing
Cursor Agentnone — the toggle does nothing
Droidnone — the toggle does nothing
Copilot CLInone — the toggle does nothing
Ampnone — the toggle does nothing

Fix. Use one of the six that do have a flag — see What walk-away does for the full table — or register the CLI again under Settings → Custom agent CLIs and fill in the Walk-away flag field yourself. A custom agent with that field empty behaves exactly like the five above.

An agent’s command was refused

Symptom. The agent runs something ordinary and gets back a red line beginning ⚠ DeckSpace, or a plain Operation not permitted.

These are two different mechanisms with two different fixes. Read which message you got.

“DeckSpace guard” / “DeckSpace blocked a destructive git”

Agent-driven panes get OPX_GUARD=1 and a shim directory at the front of PATH holding three files: rm, git and sudo. The shims are inert without that variable, so a pane you typed into yourself is unaffected. They parse arguments rather than matching text, so flag spellings do not slip past.

What the agent ranWhat happened
rm -r, rm -rf, rm -rfv, rm --recursiveTargets moved to ~/.opxspace-trash, not deleted. Yellow warning, exit 0 — the agent believes it succeeded.
A recursive rm where some target could not be movedNothing is deleted. Red warning, exit 1.
git reset --hardRefused, exit 1
git clean -f / --forceRefused
git push -f, --force, --force-with-lease, or a +ref refspecRefused
git checkout ., git checkout -fRefused
git restorewith any arguments at allRefused
git switch --discard-changes / -fRefused
git branch -D / --deleteRefused
git stash drop, git stash clearRefused
git worktree removeRefused
git update-ref -dRefused
git reflog expire / deleteRefused
git filter-branch, git filter-repoRefused
git gc --prune=nowRefused
sudo — anythingRefused

Fix. The refusal message prints the absolute path of the real binary. Run the command yourself in a pane you opened by hand, or call that absolute path. Deleted work is not gone: look in ~/.opxspace-trash first.

git restore is the entry that surprises people. It is refused unconditionally, including harmless forms like git restore --staged <file>, because the shim keys on the subcommand and not on the flags after it.

“Operation not permitted”

That is the OS sandbox, not DeckSpace. An agent launched into its own pane runs inside a write fence: reads, execution and network are free, all file writes are denied, and writes are then re-allowed in a short list of places.

Only some panes are fenced

The fence covers agents DeckSpace starts — in their own pane, in a pane it opens for you (swarm builders, Maestro workers, Kanban runs), and work it runs with no pane at all. A terminal you opened yourself is deliberately not fenced, so if you see this error in an agent pane and not in your own shell, that is why. The full table is on the walk-away page.

Writable inside an agent pane
The workspace it is working in
/private/tmp, /private/var/tmp, /private/var/folders, /dev
~/.claude, ~/.codex, ~/.gemini, ~/.config, ~/.cache, ~/.local/state, ~/.npm, ~/.opxspace-trash

Everything else is refused by the kernel — whether the agent writes directly, shells out, uses an absolute path, or runs a script. Another repo on the same machine is outside the fence.

Fix. Move the work into the workspace, or turn Confine agent writes off under Settings → Autonomy for the run that legitimately needs to write elsewhere.

There is no sandbox on this machine

PlatformBackendCondition
macOSsandbox-execavailable when /usr/bin/sandbox-exec exists
Linuxbwrapavailable only if bwrap --version succeeds
Windowsalways none
This failure is silent by design

When no backend exists, DeckSpace still opens the pane. The argv is passed through untouched, OPX_GUARD=1 is still set, and the Confine agent writes toggle still reads On. Nothing on screen contradicts you.

The one place that tells the truth is the sentence under that toggle in Settings → Autonomy. With a sandbox it names it. Without one it says this machine has no sandbox available and agents can write anywhere you can.

On Windows this is not a configuration problem. There is no fence to switch on.

The app never offers an update

DeckSpace checks a signed manifest at https://deckspace.dev/deckspace/updates/latest.json — 15 seconds after launch, every 4 hours, and whenever the window regains focus. Automatic checks are floored at one per 30 minutes. When one lands, a green Update now banner appears at the top of the app; nothing installs on its own.

There are four reasons you might never see it, and none of them produce a message.

CauseWhy it is invisible
The endpoint is unreachable — offline, blocked, DNSAn automatic check swallows its error. There is no toast, no badge, nothing in the banner area.
There is no Check for updates buttonThe store has a manual check that reports both outcomes, including You’re on the latest version.. Nothing in the shipped UI calls it, so that path is unreachable and you cannot force a check from inside the app.
Background checks are switched offThe store reads deckspace.updates.disabled from browser storage and returns early when it is "1". There is no on-screen toggle that writes that key, so if it is ever set, nothing in Settings will show you it is set.
You are looking at a detached panel windowThe check cadence is started once, from the main window only. A detached panel never checks and never shows the banner.

Fix. Quit, relaunch, and leave the main window focused for a minute. If no banner appears, compare the version chip beside the DeckSpace wordmark in the top-left of the window against Updating and install the current build by hand if they differ. Once the banner does appear, one click downloads it, verifies the update signature, installs and relaunches.

The phone remote answers 403

Two entirely different refusals share that status code, and they send you to two different screens. The error.code in the response body is what tells them apart.

CodeWhat it meansFix
forbidden_scopeThe device was not paired with the scope this route needs. The message names it: this route needs the order scope. The five scopes are monitor, order, approve, converse and drive (shown as Type into panes).Pair the phone again. Scopes can be taken away from the device list in Settings → Remote and that takes effect immediately — but they cannot be added there. The checkbox for a scope a device does not hold is disabled on purpose.
forbidden_scope, message this device may not take screenshotsScreen captures are a per-device flag, not a scope, because a capture shows your whole screen and not only DeckSpace.Same — granted at pair time only.
forbidden_permissionThe device does hold the scope. A tool-permission category on the desktop is set to ask or deny, and a confirm arriving from a phone has no prompt anyone is standing at.Set that category to allow on the desktop. The body names it in detail.category.
pairing_closedYou typed a pairing code with no pairing window open, or with Remote switched off.Open Settings → Remote on the desktop and start pairing there first.

Only two categories can produce forbidden_permission, and which one depends on where the order was told to land:

Order targetCategory that must be allow
A board task (the default)Board write
A headless missionShell commands — the mission runs an agent that writes files and runs commands in the repo
The phone sends you to a screen with a different name

The message the phone renders says to set the category in Settings → Permissions. The section is actually titled Tool permissions · pre-authorization. Same screen, and the category labels in it (Board write, Shell commands) match the message exactly.

The other refusals a phone can hit:

StatusCodeCause
401pairing_invalidThe code is unknown, expired, or already used.
409device_limitEight devices are already paired. Remove one first.
409already_decidedThe gate moved on between the list and your tap. Refetch.
429120 requests per minute per device. Five failed authentications lock that device out for 15 minutes.
503renderer_unavailableThe DeckSpace window is closed on the desktop.

A gate never reaches the phone

Symptom. Something is clearly waiting for a human on the desktop, and the phone’s approvals list is empty.

Three of the four gate kinds live only inside the DeckSpace window — the Maestro plan gate, the Maestro question wizard, and mission approvals. They are listed where they can be decided, so while the window is closed they are simply absent rather than shown and un-tappable. Reopen the window and the gate reappears with its original timestamp.

A mission started from a detached Loop panel is invisible to the phone

Every DeckSpace window is its own context. A mission started in a detached Loop panel keeps its approval handles in that window, and the main window never learns about it — so its gate never appears on the phone at all. Detaching the panel after the mission started in the main window is fine.

Fix. Start missions in the main window when you intend to approve them from your phone.

The desktop is also given 4 seconds to answer a phone’s request. An overrun is reported as stalled, not failed — approving a plan starts the whole run, so the decision is applied before the answer comes back. Do not tap twice.

Remote will not start

When the server refuses to come up, Settings → Remote gives a reason. Each maps to a specific fix.

ReasonFix
disabledRemote is off. Nothing is listening.
not_proRemote is part of a subscription. Activate or renew under Plan & license, then turn it on.
no_tailnet_addressPrivate mesh is selected but no address in 100.64.0.0/10 exists. Join the mesh, or switch to Local network. Private mesh never falls back to the LAN on its own.
no_lan_addressLocal network is selected but there is no 10.x, 172.16–31.x or 192.168.x address. Join a network and turn Remote on again.
bind_failedAnother program holds the port. Quit it and turn Remote on again.
listener_stoppedThe server stopped on its own. Toggle Remote off and on; the log has the detail.
no_server_idThe identity your phones use to recognise this machine could not be saved — usually an unwritable app database. Remote refuses to start rather than hand out an identity that changes next launch.

If the mode is This machine only, the server answers on 127.0.0.1 and a phone cannot connect to it directly at all. That is the mode working, not failing. See Phone remote.

Linux-only failures

SymptomWhyFix
The tray icon does not exist, and mini-mode hides the app with no way backThe tray needs a StatusNotifierWatcher on the session bus. GNOME removed its tray years ago.Install the AppIndicator and KStatusNotifierItem Support extension. DeckSpace warns once at startup when it detects no host — and stays quiet when it cannot tell, so no warning is not proof of a tray.
The global hotkey and dictation insert are greyed outWayland blocks synthetic input and global shortcuts. An X11 session is required.Use an X11 session, or use push-button voice in the Voice room — that still works, and the transcript goes to the clipboard for you to paste.
Voice replies are silentNeither paplay nor aplay is installed.Install pulseaudio-utils or alsa-utils. The app says this once, then stops repeating it.
Agents write outside the workspacebwrap is missing, so there is no sandbox backend.Install bubblewrap. See above — the toggle will read On either way.

Activation and licence

DeckSpace requires a valid licence key and a device-bound activation token for that specific Mac. Both are checked offline at every launch.

MessageCauseFix
“This license is already active on 2 Macs”The seat cap is 2.Remove the licence on one of those Macs, or use the device page on deckspace.dev, then activate again.
Renew prompt / subscription lapsedThe Stripe subscription behind the key has ended. Renewal is enforced through the activation token, not the key.Renew, then relaunch so the app re-activates.
“That license key isn’t valid.”The key was rejected outright.Check it pasted whole — the keys are long and wrap in email.
“Couldn’t reach the license server.”No network, or the store is unreachable.Reconnect and try again.
Paid features locked after a long stretch offlineThe activation token expires. The app tries to renew it silently once it is within 10 days of expiry — but that background attempt runs at most once per app launch, so a failed attempt is not retried until you relaunch.Get online and relaunch DeckSpace. One successful refresh restores it.

Smaller things

SymptomCause and fix
“Can’t verify the developer” on first launchRight-click DeckSpace → OpenOpen. Once only.
A room shows an error panel instead of loadingIts code chunk failed or took more than 10 seconds. The app already retried once automatically. Press Retry; relaunching also re-fetches it.
“tmux not found” when opening a persistent sessionPersistent sessions are tmux-backed so they survive quitting the app. Install tmux (brew install tmux). Ordinary panes do not need it.
An agent authenticates in one pane and not anotherPanes where the CLI is the direct child have no shell in between to source your dotfiles. See the API-key note under agent CLI not detected.

Still stuck

Send the last few dozen lines of the log file from the top of this page to info@deckspace.dev, with your platform and the app version from the chip beside the DeckSpace wordmark in the top-left of the window. A real person answers.