Skip to content

SSH terminal for Mac developers

A Mac SSH client and terminal that makes remote dev boxes feel local.

lpm is a native SSH terminal for Mac that reads your ~/.ssh/config, forwards remote ports to localhost, and streams remote services into panes, one sidebar click from your local projects. No separate SSH client, no hand-typed ssh -L, no orphan tunnels.

~/.ssh/config host pickerremote port forwardingProxyJump ready
See it in action

Start a project, then hand it to Claude Code or Codex — one click each

A one-minute tour: start a project and hand it to Claude Code.

lpm is a macOS app with a multi-pane terminal workspace. Open this page on your computer to try the interactive demo.

Get lpm for MacOr check your Macs from your iPhone
The remote-dev context tax

Your remote dev box lives in a different window from your local stack

Every modern Mac developer works partly remote — a staging server, a Linux build box, a cloud workstation, a bastion-fronted EC2. That split between “local terminal” and “ssh session” shows up as friction every hour.

You context-switch between local panes and SSH sessions all day

Your local API streams logs in one window. A second window holds ssh user@build-server for the remote service. A third tab is running an ssh -L tunnel so the browser can reach it. Three windows to debug one feature, and every time you tab between them you lose your place.

Port forwarding gymnastics break every time the remote restarts

You hand-type ssh -L 3000:localhost:3000 user@build-server, the connection drops, the tunnel dies with it, and you re-type the command from shell history. Sometimes you forget which tab the tunnel was in and lsof the orphan ssh process out by hand. The work was supposed to be the feature, not the tunnel.

Re-typing the host, user, port, and key your ~/.ssh/config already knows

Your ~/.ssh/config already has Host build, ProxyJump bastion, the right port, and the right identity file. Too many workflows still make you re-enter or copy that data into a separate vault, a saved profile, or a different connection string. The config is already there; the terminal should use it.

What a remote-aware terminal looks like

An SSH terminal that knows your config and forwards your ports

What changes when the terminal understands SSH instead of just hosting it.

Pick any host from ~/.ssh/config

Open the SSH project picker and a dropdown appears, populated from your ~/.ssh/config. Selecting a host pre-fills the host alias, user, port, and identity file in one click. Include directives are followed up to four levels deep, so split configs at ~/.ssh/config.d/work show up too. Wildcard and Match blocks are skipped because they aren't pickable hosts.

Remote port forwarding with a readiness check

Type a remote port, leave the local port blank, hit Enter. lpm opens the forward and waits until the local address actually answers before the success toast appears, so the link in the toast works the first time. No more guessing whether ssh -L actually came up.

Remote services in panes, like local ones

Services declared in an SSH project run on the remote host and stream into lpm panes the same way local services do. The remote project sits in the same sidebar as your local ones, one click away, with its running state kept while you work elsewhere.

Actions run on the remote by default

On an SSH project, deploys, migrations, and remote builds run on the host with one click. One setting in the project config lets an action run on your Mac instead, against a synced copy of the remote folder that pushes changes back when it finishes.

One connection, shared and kept alive

Services, actions, and terminals share one SSH connection per host, so a jump host's 2FA prompt comes once. Keepalives catch a dropped link, and SSH terminals reconnect on their own with a fresh shell.

Claude Code and Codex report home

Open a terminal on the remote box and lpm sets up its agent status and skills there. Claude Code and Codex running on the server light up your Mac sidebar and send the same alerts as local agents.

Browse the remote project

The Files tab lists the remote project's tree and opens files for reading, and git status, branches, commits, and pull requests run on the host over the same connection. Open with sends the folder to VS Code or Cursor over Remote-SSH.

Per-project remote profile, isolated lifecycle

Each project remembers its own remote: host, user, port, key, and working directory, alongside its services and actions. Stop the project and every forward closes; quit the app and nothing leaks. Prod, staging, and your local copy are three peer projects, one click apart.

The remote-dev difference

What changes when your terminal speaks SSH the way you do

Four wins for Mac developers whose work crosses the SSH boundary.

  1. You stop hand-typing a port-forward command for every remote dev server.

    Declared service ports forward automatically as soon as the remote server starts listening. Ad-hoc binds, like a compose port or a one-off debug server, show up as one-click suggestions in the Ports popover. The success toast appears only once the local address actually answers, so the link in the toast works the first time.

  2. You stop re-entering host, user, port, and key data your SSH config already knows.

    The picker reads your existing hosts and keeps the selected Host alias intact, so OpenSSH can still apply alias-scoped options such as HostName, ProxyJump, ProxyCommand, Port, and IdentityFile. Adding an SSH project comes down to picking the host, naming the remote folder, and clicking Add project. The ~/.ssh/config file stays the source of truth.

  3. You stop juggling a local terminal and a remote SSH window.

    Remote projects sit in the same sidebar as your local ones, one click apart, and their services stream into panes exactly like local ones. Switching between prod, staging, and your local copy keeps each one's running state. Detach your local project into its own window to watch both side by side.

  4. You stop losing forwards and tunnels when something restarts.

    Forwards belong to the project. Stop the project and every forward closes cleanly; start it again and lpm forwards the declared ports as they come up. If a tunnel dies on its own, the next check forwards a declared port again. Quit the app and nothing leaks: no orphan ssh processes hiding in ps, no lsof archaeology to find a tunnel you started yesterday.

In practice

Three remote-dev scenarios your Mac terminal should make trivial

Three moments where the local-vs-remote split costs real time, and how lpm keeps them in one app.

1

Onboard to a remote dev box without typing a single connection detail

A teammate hands you their ~/.ssh/config snippet — a Host devbox entry with ProxyJump bastion and the right key path. You paste it into your config, click “Add a project” in lpm, choose “SSH Host”, and pick devbox from the dropdown. Pick any host from ~/.ssh/config and the form fills itself while preserving the devbox alias, so OpenSSH still applies the ProxyJump rule. The first connection prompts for your bastion 2FA once; from then on, every service, action, and terminal reuses it. You’re inside the dev box without typing a host, a user, a port, or a key path.

2

Push a hotfix to staging without stopping your local stack

Your local frontend and api are streaming logs in two panes. A bug needs to ship to staging fast. Open the staging project (already configured against the remote host) and click your migrate action. On an SSH project, actions run on the remote host by default, so the staging API pane streams the output. Forward the staging API port to localhost from the Ports popover to verify the fix in your browser. Your local project kept running the whole time; click back to it and pick up exactly where you were.

3

Forward a remote dev server to localhost the moment it starts

You start the remote project’s api service. It prints Listening on http://0.0.0.0:8080 into its pane. lpm sees the URL in the output, matches it against the declared service port, and auto-forwards — the toast reads Auto-forwarded :8080 → http://localhost:8080. Open the URL locally; your browser is talking to the remote process through the SSH channel without you typing a single -L flag. Stop the project and the forward dies cleanly. No orphans, no lingering tunnels.

How it compares

lpm vs dedicated SSH clients, Mac terminals, raw OpenSSH, and editor remotes

The distinction is not whether the other tools can SSH or forward ports. Many can. lpm is different because SSH is part of the project lifecycle: services, actions, panes, and forwards are managed together.

  • Reads ~/.ssh/config hosts without replacing OpenSSH

    lpm uses the selected Host alias when it connects, so OpenSSH remains responsible for options like HostName, ProxyJump, ProxyCommand, Port, and IdentityFile.

    • lpm: yes
    • Dedicated SSH client: no
    • Terminal running raw ssh: yes
    • raw OpenSSH: yes
    • Editor Remote-SSH: yes
  • Remote services stream into project panes like local ones

    This is the lpm project model: services, actions, terminals, and SSH settings live together instead of being separate saved sessions.

    • lpm: yes
    • Dedicated SSH client: no
    • Terminal running raw ssh: no
    • raw OpenSSH: no
    • Editor Remote-SSH: no
  • Declared remote service ports forward once they listen

    lpm watches remote listening ports for SSH projects and auto-forwards ports declared in the project's services config.

    • lpm: yes
    • Dedicated SSH client: no
    • Terminal running raw ssh: no
    • raw OpenSSH: no
    • Editor Remote-SSH: no
  • Manual forwards wait for localhost readiness

    When you add a forward, lpm waits until the local listener accepts a TCP connection before reporting success.

    • lpm: yes
    • Dedicated SSH client: no
    • Terminal running raw ssh: no
    • raw OpenSSH: no
    • Editor Remote-SSH: no
  • Project stop cleans up the SSH forwards it started

    Forwards are owned by the lpm project lifecycle, not by whichever tab happened to run an ssh command.

    • lpm: yes
    • Dedicated SSH client: no
    • Terminal running raw ssh: no
    • raw OpenSSH: no
    • Editor Remote-SSH: no
  • Run local tools against a synced mirror of the remote tree that pushes changes back

    lpm keeps a local mirror of the remote project directory, runs the action against that mirror on your Mac, then syncs the edits back to the remote host.

    • lpm: yes
    • Dedicated SSH client: no
    • Terminal running raw ssh: no
    • raw OpenSSH: no
    • Editor Remote-SSH: no
FAQ

What Mac developers ask before using lpm as their SSH terminal

  • Does lpm replace Termius as my SSH client on Mac?
    For developers who want their terminal to handle remote work alongside local services, yes — lpm reads the hosts already in your ~/.ssh/config (no separate host vault), runs remote services in panes, and forwards ports without leaving the window. You can browse and read the remote project's files (read-only), but for SFTP transfers or a snippet library Termius still does more; lpm is a terminal-first SSH workspace, not a feature-parity Termius alternative on Mac.
  • How does lpm import my SSH config?
    When you add an SSH project, lpm reads ~/.ssh/config (and any files pulled in by Include directives, up to four levels deep), parses out the non-wildcard Host blocks, and shows them in a dropdown. Pick a host and lpm pre-fills the host alias, user, port, and identity file in the form. lpm connects through that alias, so OpenSSH can still apply alias-scoped options such as HostName, ProxyJump, and ProxyCommand. The import is one read, and your config file stays the source of truth.
  • Can I forward a remote port to localhost without typing ssh -L?
    Yes, that's the whole point of the Ports popover. Type the remote port, leave the local port blank, and hit Enter; lpm opens the forward and shows the success toast only once the local address actually answers, so you know the tunnel is usable, not just started. Declared service ports forward automatically as soon as the remote server listens, and other ports lpm spots on the remote show up as one-click suggestions: remote port forwarding without the ssh -L archaeology.
  • Does lpm work with a jump host or bastion?
    Yes, when the jump host is part of the selected Host entry in your OpenSSH config. lpm saves the host alias and invokes OpenSSH with it, so options such as ProxyJump bastion or ProxyCommand remain in OpenSSH's hands. The first connection prompts for whatever your bastion requires (key passphrase, 2FA); lpm keeps that connection open after that, so later services, actions, and terminals can reuse it.
  • Can actions run on the remote host, or locally against remote files?
    Both. On an SSH project, actions run on the remote host by default, which suits a deploy, a migration, or a remote build. A setting in the project config lets an individual action run on your Mac instead: lpm copies the remote folder down, runs the command locally, and pushes the changes back, so a local formatter or an AI coding session can work on remote source without you shuttling files. That option needs rsync.
  • Do Claude Code and Codex on the remote box show up in lpm?
    Yes. When you open a terminal on an SSH project, lpm sets up its agent status and skills on the server, so Claude Code and Codex running there report working, needs you, and done to your Mac's sidebar and trigger the same sounds and banners as local agents. If a gateway host sends terminals to a different machine than lpm's connection, lpm warns you that alerts from that server won't arrive.
  • What happens when the SSH connection drops?
    lpm sends keepalives, so a dead link is noticed quickly, and SSH terminals reconnect on their own, backing off between attempts. A reconnect starts a fresh remote shell, so whatever that session was running is not resumed. Remote processes also live only as long as the connection; to keep projects and agents running while your Mac sleeps, install lpm on the server as a Linux host.
  • Can I duplicate an SSH project or make a worktree of it?
    Not yet. Duplicate and New Worktree aren't available for SSH projects, and services are not auto-detected for SSH projects: a new one starts with a single login-shell service that you edit in the config editor.
  • Is lpm a good iTerm2 or Warp alternative for SSH work specifically?
    Both iTerm2 and Warp are capable Mac terminals, and raw ssh inside either can use your OpenSSH config. lpm is different because it adds a project model around the SSH session itself: a host picker reading ~/.ssh/config, remote services streaming into project panes, port forwarding with readiness checks, remote port suggestions, and per-project lifecycle for forwards. If your day is mostly local terminal work with the occasional ssh user@host, a general terminal is fine. If you cross the local/remote line every hour, lpm is built for that workflow.

Your local stack and your remote dev box, finally in the same app. Free, native, and ready in minutes.

Install lpm, open the host picker and choose an entry from your ~/.ssh/config. lpm forwards declared remote service ports as soon as they listen, offers one-click forwards for other ports it spots, streams remote services into panes, and cleans up the forwards it starts. Supported on every Apple Silicon or Intel Mac with macOS 12 and up.