Skip to content
DocsTerminals

Terminals

Terminals are persistent interactive shells you open from the desktop app with a single click — a live log tail, a Node or Python REPL, or an AI coding agent like Claude Code. Unlike a service, a terminal isn’t something lpm starts and stops with the project; unlike an action, it doesn’t run once and exit. It stays open and you type in it until you close it.

A terminal is just an action with type: terminal — same fields as any action, it simply opens in a pane and stays open instead of running once. A standalone terminals: section still works as a deprecated alias, but new configs should use type: terminal.

Declaring a terminal. Give the entry a cmd and set type: terminal so it opens in a pane and stays open instead of running once. Reach for a friendlier label, tuck it into the footer with display: footer, or set a cwd or env when you need them:

~/.lpm/projects/myapp.ymlvalid
name: myapp
root: ~/Projects/myapp
services:
  web: npm run dev
actions:
  codex:                      # minimal — key becomes the label
    cmd: codex
    type: terminal

  claude:                     # full form
    cmd: claude
    label: Claude Code        # nicer name than the key
    display: header           # pin to the toolbar, one click away (default)
    type: terminal
  • cmd*string

    The shell command that starts the terminal — usually something interactive you want to keep around, like claude, node, or tail -f ./logs/dev.log. lpm opens it in a real PTY so prompts, colors, and arrow keys all work.

  • type*string

    Must be terminal — this is what makes the entry open in a persistent pane and stay open, instead of running once like a plain action.

  • labelstring

    The friendly name shown on the button. If you skip it, lpm uses the terminal’s key — so claude just shows up as claude.

  • emojistring

    Same as on actions: a single emoji prefixed to the label, handy for telling a row of agent terminals apart at a glance — emoji: 🤖 with label: Claude Code renders as 🤖 Claude Code.

  • cwdstring

    Open the terminal in a different folder than the project root — useful for monorepos or when your agent should start inside a specific package. Relative paths resolve from root; absolute paths are used as-is (see Path resolution).

  • envmap

    Extra environment variables to set just for this terminal — handy for picking a model with ANTHROPIC_MODEL or pointing a REPL at a staging database. These only apply inside this shell, nothing else on your system is touched.

  • displaystring

    Same rules as actions. The default, header, pins the terminal to the project toolbar — omit display entirely to get the same result. footer tucks it into the status bar below the terminal. menu still works as a legacy value (overflow menu) but is no longer suggested by the editor.

* required

Header or footer?

Header is the default — every terminal lands in the toolbar unless you say otherwise. Move the tightest, always-one-click controls to the footer with display: footer so they sit beside the branch switcher without crowding the main button row.

AI coding agents, one click away. This is where terminals really shine. List the agents and REPLs you actually use and they’re waiting as one-click buttons in the project toolbar every time you open the project — each one starts in the project’s folder, so there’s no hunting for the right window or directory:

~/.lpm/projects/myapp.ymlvalid
name: myapp
root: ~/Projects/myapp
services:
  web: npm run dev
actions:
  claude:
    cmd: claude              # AI pair programmer
    type: terminal
  codex:
    cmd: codex               # another AI agent, swap at will
    type: terminal
  node:
    cmd: node                # quick REPL for poking at things
    type: terminal
  logs:
    cmd: tail -f ./logs/dev.log  # live-tail your dev server logs
    type: terminal