Run ClosedLoop from the command line
Install the headless closedloop CLI with Homebrew, sign in, and pause or resume session capture without the Desktop app.
The closedloop CLI runs session capture as a background daemon, with no Desktop window. Use it on a machine where you work in a terminal, or where you would rather not run the Desktop app.
Install
Install with Homebrew on macOS or Linux:
brew tap closedloop-ai/tap
brew trust --tap closedloop-ai/tap
brew install closedloopThe formula comes from the public closedloop-ai/homebrew-tap repository and installs Node.js as a dependency. Check the install with:
closedloop --versionSet up
Run setup once:
closedloop setupSetup signs you in, records your consent, and starts the background service. Each stage skips what is already done, so running setup again finishes an interrupted run. When you are already signed in, setup still hands your session to a running daemon, which also resumes it if it is paused.
On Linux, sign-in stores credentials in the Secret Service through secret-tool, from libsecret. Install secret-tool and make sure a Secret Service, such as GNOME Keyring, is reachable on your session bus. Without them, sign-in stops before it prints a verification code.
Sign-in uses a verification code. The CLI prints Verification code: and Verification URL: lines and opens your browser. Approve only if the page shows the same code. Pass --no-browser to print the URL and code without opening a browser, for example over SSH:
closedloop setup --no-browserConsent asks the same questions as the Desktop app's onboarding, in the same order: the session-analysis agreement, then your sync level. The daemon analyzes no sessions until you agree. Consent needs an interactive terminal; without one, nothing is recorded. To review or change your sync level later, run closedloop consent.
Commands
closedloop --help lists every command:
Usage: closedloop <command> [--no-browser]
Commands:
login Sign in and start the background service
logout Sign out, clear local credentials, and stop the service
setup Sign in, record consent, and start the service
status Show sign-in, service, consent, and sync status
daemon Run the daemon in the foreground
consent Review and record consent and sync level
pause Pause capture and cloud sync
resume Resume capture and cloud sync
logs Print the latest daemon log lines
Options:
--no-browser Don't open a browser; print the sign-in URL and code (login, setup)
--version Print the version
--help Print this helpSign in and sign out
closedloop loginlogin signs you in and starts the background service. If you are already signed in, it says so and makes sure the service is running.
closedloop logoutlogout stops the service first, then revokes the session on the server and clears the credentials stored on this machine. Local credentials are cleared even when the server revoke fails. If it prints Some local credentials were not cleared. Run closedloop logout again., do that.
Pause and resume
closedloop pausepause stops capture and cloud sync and prints Capture and sync paused. closedloop status then shows paused on its Capture: line.
closedloop resumeresume turns both back on and prints Capture and sync resumed.
A pause lasts only until the daemon restarts: a restarted daemon starts capturing and syncing again. Signing in with closedloop login also resumes a paused daemon. Both commands need the daemon running; otherwise they print The daemon is not running.
Start and stop the daemon
closedloop login and closedloop setup start the daemon as a Homebrew service, and closedloop logout stops it. You can also manage the service with Homebrew directly:
brew services start closedloop
brew services stop closedloopThe service runs closedloop daemon. If the daemon fails, the service restarts it; a clean stop leaves it stopped.
To run the daemon in the foreground instead, for example to watch it while debugging, run:
closedloop daemonPress Ctrl-C to stop it.
The Desktop app and the CLI
The daemon and the Desktop app cannot run at the same time on one machine. Whichever starts first holds the lock:
- If the Desktop app is running, starting the daemon fails, and the CLI prints
ClosedLoop desktop is already running (pid <pid>).Quit the Desktop app first. - If the daemon is running, opening the Desktop app shows a dialog that says
ClosedLoop daemon is already running (pid <pid>)., and the app quits. Stop the daemon first.
The daemon keeps its own data, separate from the Desktop app's. Signing in on one does not sign you in on the other.
Check status and logs
closedloop statusstatus shows the version, the service and daemon state, whether you are signed in, your consent and sync level, capture progress, and sync progress. When the daemon is not running and the Desktop app holds the lock, it also prints the ClosedLoop desktop is already running (pid <pid>). line. It ends with the path of the daemon log.
closedloop logslogs prints the last 200 lines of the daemon log.
Where the daemon keeps its data
| Platform | Data directory |
|---|---|
| macOS | ~/Library/Application Support/ClosedLoop Daemon |
| Linux | $XDG_DATA_HOME/closedloop-daemon, or ~/.local/share/closedloop-daemon when XDG_DATA_HOME is unset |
The daemon log is logs/daemon.log inside that directory. To use a different directory, set CLOSEDLOOP_DAEMON_HOME to an absolute path. It cannot be, contain, or sit inside the Desktop app's data directory.
With CLOSEDLOOP_DAEMON_HOME set, the CLI runs the daemon as its own launchd agent on macOS or systemd --user unit on Linux, even when Homebrew installed it, so brew services stop closedloop does not stop it. Run closedloop logout with the same CLOSEDLOOP_DAEMON_HOME, or stop the service directly:
# macOS
launchctl bootout gui/$(id -u)/ai.closedloop.daemon
# Linux
systemctl --user disable --now closedloop.service