Repository navigation
skiffd
skiffd is the Skiff daemon. It owns the pseudo-terminals (PTYs) and the processes for all sessions. The desktop app connects through a local Unix socket.
You can close the window and leave agents at work. When you open Skiff again, it connects to the same daemon.
| Action | Result |
|---|---|
| Close or reload the window | Sessions keep running in skiffd. |
| Open the window again | Terminals show their current screen and available history. |
| An agent exits | Its terminal returns to an interactive shell. |
Restart skiffd
|
Running sessions stop. Saved sessions return as new shells. |
| Reboot the computer | Processes stop. Skiff restores the saved workspace when the daemon starts again. |
The daemon keeps a terminal screen and up to 2,000 lines of scrollback per session in memory. A client first receives a snapshot, then live output.
skiffd saves groups, layouts, session IDs, names, folders, terminal sizes, and themes in a workspace file. It saves after changes and on normal shutdown.
After a daemon restart, each saved session starts a shell in its folder with its previous ID. If the folder no longer exists, the shell starts in the home folder.
The workspace file does not save running processes, terminal screens, or scrollback. Agents do not resume automatically after a daemon restart.
The app first tries to connect to the socket. If it cannot connect, it starts skiffd and tries again.
The app finds the daemon binary in this order:
- The path in
SKIFF_DAEMON, if set. - A
skiffdbinary next to the app executable. -
skiffdonPATH.
Packages include the daemon. You do not need to start it separately for normal use.
skiffd has its own version, separate from the desktop app version. On connection, the app checks the daemon version and protocol number.
| Daemon state | App behavior |
|---|---|
| Same version and protocol | Uses the daemon. |
| Older version or different protocol, with no live sessions | Replaces the daemon automatically if it can identify and stop the process. |
| Older version or different protocol, with live sessions | Shows a warning and a Restart skiffd button. A different protocol can cause parts of the app to fail. |
| Newer version with the same protocol | Uses the daemon and shows a version warning. |
| Accepts connections but does not answer the handshake within two seconds | Reports that the daemon does not respond. |
Save your work before you select Restart skiffd. The restart stops running sessions. Panes return as shells in their folders.
| File | Release build | Debug build |
|---|---|---|
| Socket | <runtime dir>/skiff/skiffd.sock |
<runtime dir>/skiff/skiffd-dev.sock |
| Log, when the app starts the daemon | Beside the socket: skiffd.log
|
Beside the socket: skiffd-dev.log
|
| Workspace | <state dir>/skiff/workspace.json |
<state dir>/skiff/workspace-dev.json |
| Settings | <config dir>/skiff/projects.toml |
Same default file as the release build |
On Linux, the runtime directory is $XDG_RUNTIME_DIR. If no runtime directory is available, Skiff uses the system temporary directory.
On Linux, the default state directory is $XDG_STATE_HOME, or ~/.local/state if unset. The default config directory is $XDG_CONFIG_HOME, or ~/.config if unset.
On platforms without a state directory, Skiff uses the local data directory for the workspace. On macOS, the default workspace and settings files are under ~/Library/Application Support/skiff/.
When the app starts a new daemon, it moves the previous log to skiffd.log.1 or skiffd-dev.log.1. A daemon started directly writes logs to standard error.
Set these variables before you start the app or daemon. An existing daemon keeps the environment from its startup.
| Variable | Purpose |
|---|---|
SKIFF_DAEMON |
Selects the daemon binary that the app starts. |
SKIFF_SOCKET |
Selects the Unix socket path. The app and daemon must use the same path. |
SKIFF_STATE |
Selects the workspace file. |
SKIFF_CONFIG |
Selects the projects.toml settings file. |
SKIFF_SHELL_ENV=0 |
Disables the login-shell environment and alias probe. |
RUST_LOG |
Sets the daemon log filter, for example debug. The default is info. |
At startup, the daemon probes the shell in SHELL as an interactive login shell. The probe reads environment variables and aliases.
If the daemon starts without TERM, it imports the shell environment. This gives desktop launches access to shell settings such as PATH and EDITOR. If TERM is set, it keeps the inherited environment and reads aliases only. The probe has a three-second timeout.
From the repository root, build the daemon with:
cargo build -p skiffdpnpm tauri dev also builds it before the app starts. Debug builds use a separate socket and workspace, so they can run beside the installed app. They share the default settings file.
A rebuild does not replace a running daemon. To use a new build:
-
Save the work in the sessions that use the development daemon.
-
Find its process ID:
pgrep -ax skiffd
-
Stop that process with
kill -TERM <pid>. Select the development process if an installed daemon also runs. -
Restart or reload the development app.
To run the debug daemon directly, use:
RUST_LOG=debug target/debug/skiffdIt stays in the foreground and prints logs to standard error. If another daemon already uses its socket, it exits with skiffd is already running. It removes a stale socket if it cannot connect to it.
- Daemon: sessions, terminal screens, workspace restore, and socket server.
- Shared types: protocol, paths, settings, and session model.
- Client: requests and event subscriptions.
- Desktop connection: startup, version checks, logs, and restart behavior.