The desktop app

The desktop app is one of three ways to run loopkeep, alongside the lk CLI and the terminal UI — all equal, all driving the same background service (loopkeepd), which runs underneath and keeps going when you close the window. One window supervises every project. This page tours it and documents its settings; where an action also has a lk command, it's noted.

The window

  • Project switcher (top of the sidebar) — switch between registered projects; a badge shows how many approvals are pending in each. Add project sits at the bottom.
  • SidebarInbox, Runs, Workflows, Policies, and Project Settings, all scoped to the selected project. A badge on Inbox counts what's waiting on you.
  • Footer — the background-service status (Connected / Offline), a Refresh button, and your account. The account menu opens Settings and Personal Policies.
  • Banners (bottom of the window) surface things that need a decision: the service is unreachable (Start service), a new version is available (Update & restart), or the project isn't trusted (Trust on Policies).

Projects

A project is a registered folder that holds a .loopkeep/ workspace. Add one from the project switcher, from Settings → Projects, or from the empty state — pick a folder and, if it isn't a loopkeep project yet, Initialize it (see Quickstart). Remove one from Project Settings → Remove this project or Settings → Projects → Delete: the folder and its .loopkeep/ are left on disk, only the registry entry goes away. The home workspace can't be removed.

From the terminal: lk workspaces lists them, lk workspaces add <path> and lk workspaces remove <id> manage them, and lk init creates .loopkeep/.

Editing triggers

The Triggers section of the workflow editor builds the on: block with forms instead of YAML, one card per trigger type: cron expressions for a schedule, paths and events for file-watch, and — for GitHub, Slack, and webhooks — the events you subscribe to with conditions under each. Add conditions starts a set and Add an alternative adds another, which is how a trigger comes to fire on any one of several sets. About is the ownership condition, so "a pull request opened by me" is what the reference calls on: my-pr. Webhooks are picked from the URLs you've already issued rather than typed by hand.

Two things worth knowing before you save from the form: on: entries it has no form for are shown as preserved and carried through your save exactly as written, and comments inside the triggers block don't survive a form save — the editor says so and points you at the Raw tab, which edits the markdown directly. Every key and its exact meaning is in the workflow frontmatter reference.

Editing Slack safe-outputs

The workflow editor's Settings section also manages Slack destinations. Post to Slack requires a channel. Its workspace control is an always-present free-text field for a Slack workspace ID; the value remains optional when exactly one connected workspace can be resolved. The channel control is a picker fetched for the workspace ID, with direct ID entry as a fallback. The agent supplies only the message and cannot change that destination. Reply in Slack is a separate declaration that permits a Slack-origin run to answer its own conversation. Saving either card writes safe-outputs.slack-post or safe-outputs.slack-reply while preserving safe-output keys the form does not manage. Use Raw for a malformed block the form cannot represent.

Background service

The app starts loopkeepd for you and shows its status in the footer. Its settings live under Settings → Background service:

  • Max concurrent runs — the cap on runs in flight across every project (default 4). CLI: lk global-max. A single project can also set its own lower cap from the CLI with lk workspace-max [<n>|clear]; the effective limit is the lower of the two.
  • Keep running after the app is closed — off by default, so quitting the app also stops the service and its automatic firing; turn it on to keep runs and triggers going headless. Takes effect on the next service start.
  • Delete run worktrees after N days and Clean up now — how long finished runs' worktrees are kept before cleanup; checkpoint branches and the event history are always kept. CLI: lk retention <days|off> and lk cleanup.

If the service becomes unreachable or the running build differs from the app, a banner offers to start or restart it.

Command line tool

Settings → Command line tool → Install lk command symlinks /usr/local/bin/lk into the app bundle, so app updates keep the command current. macOS may ask for your administrator password. See Install.

Preferred terminal

Settings → Preferred terminal / multiplexer. When set, take-over shows an Open in terminal button that launches the interactive session for you; left empty, you copy the command and run it yourself. When loopkeep can also drive a multiplexer, take-over offers to open a pane there too. Pick a detected terminal or type a command template using {cmd} (the command to run) and {cwd} (the run's worktree).

Appearance and language

Settings → Appearance (System / Light / Dark) and Settings → Language (System / English / 日本語). Both follow your OS setting by default. These are desktop-only preferences.

Console sign-in

Settings → Console sign-in shows the paired device, the Console, and the gateway, and offers Sign out (which revokes the device). Pairing is optional and enables GitHub and Slack triggers — see Pair with the Console.

Slack notifications

Settings → Slack notifications can send approval requests and notification digests to one connected Slack channel. Set both a workspace and channel; leave both empty for desktop-only notifications. Approval requests arrive immediately, while notify-level items are posted only in the scheduled digest. The Slack message is informational — approve or deny in loopkeep.

Personal Policies

The account menu's Personal Policies opens your home policy, which applies on top of every project, and shows the read-only Built-in floor — the writes loopkeep always asks about, that no layer can relax. See Policies & trust.

Pause all automation

Settings → Danger zone → Pause all automation stops trigger-driven runs across every project until you resume; manual runs and runs already in flight keep going, and per-project settings are untouched. CLI: lk pause --all and lk resume --all. The Console's Stop automation request sets this same persisted gate on an online capable device. Resume is deliberately local-only.

Updates

When a new version is available, a banner offers Update & restart — the app downloads it and relaunches. This is desktop-only; the CLI is updated with the app bundle it's symlinked into. What's new includes every bundled release newer than the installed version, so skipping versions still shows intervening behavior changes. A release manifest carries at most five sections; if the sections cannot be parsed safely, the dialog shows the bundled notes in full.