cloud storage client
git clone https://git.lucas.co/cce-cloud.git
fix: write the spawn log to the per-user runtime dir, not /tmp
spawn_detached logged every launched app to a fixed /tmp/cce-spawn.log and pointed the child's stdout/stderr at the same file. On a shared machine that is both a collision — the first user to log in owns the path, and /tmp's sticky bit denies the rest — and a readable trace of one user's activity, since the file carries every command the launcher ran plus whatever those processes printed. It now lives at $XDG_RUNTIME_DIR/cce/spawn.log via cce_ui::config::cce_runtime_dir() (cce-ui@0f08c0d), which is per-user and mode 0700.
Routed through the shared helper rather than an inline env::var read: hardcoding the resolution here is the same thing the DE-wide path cleanup existed to remove, one indirection later. The daemon carries XDG_RUNTIME_DIR (systemd sets it for user units — verified on the running service), and the compositor's own logs moved to the same directory in cce@522ce13, so the session's runtime files now sit together.
Takes effect on a daemon restart, not an install: ccebuild restart is what swaps it. The file name loses its cce- prefix (spawn.log) now that the directory carries it, matching launch.sh alongside it.
Co-Authored-By: Claude <[email protected]>
CLAUDE.md | 4 +++-
src/main.rs | 6 +++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index 1443189..b384843 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -68,7 +68,9 @@ needs-stdin decision, in `run_client()`).
- `Path` — executables scanned from `$PATH`.
- `Apps` — `.desktop` files from the standard application dirs, sorted by launch
frecency persisted in `~/.cache/cce-cloud-apps.json`; selecting spawns the app's
- `Exec` (spawn output logged to `/tmp/cce-spawn.log`). Each entry's `Icon=` is
+ `Exec` (spawn output logged to `$XDG_RUNTIME_DIR/cce/spawn.log`, via
+ `cce_ui::config::cce_runtime_dir()` — it was `/tmp/cce-spawn.log` before
+ 2026-08-22). Each entry's `Icon=` is
resolved through `cce_ui::icon` and drawn in a gutter left of the label — the
gutter is applied to every row, so one unresolvable icon doesn't rag the text
edge. This is the *only* mode with icons: Dmenu/Path items are arbitrary
diff --git a/src/main.rs b/src/main.rs
index cb643f2..f300468 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -522,10 +522,14 @@ fn spawn_detached(program: &str, args: &[&str]) {
use std::os::unix::process::CommandExt;
let mut cmd = std::process::Command::new(program);
cmd.args(args).process_group(0);
+ // Per-user runtime dir, not /tmp: this records every app the launcher
+ // starts and captures their stdout/stderr, so a fixed /tmp path is both a
+ // collision between users and a readable trace of one user's activity.
+ let log_path = cce_ui::config::cce_runtime_dir().join("spawn.log");
if let Ok(file) = std::fs::OpenOptions::new()
.create(true)
.append(true)
- .open("/tmp/cce-spawn.log")
+ .open(&log_path)
{
let mut f = file;
use std::io::Write;