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 imports your ~/.ssh/config, forwards remote ports to localhost, and keeps remote services in panes beside your local stack. No separate SSH client, no hand-typed ssh -L, no orphan tunnels.
Projects, terminals, agents, a built-in browser — one click each
A recording of lpm booting a project and handing it to Claude Code — lpm is a macOS app, so the clickable demo runs on desktop.Click anything — it runs live in your browser.
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
Done poking around? Get lpm for Mac and point it at your own projects.
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 remote dev server restarts, the listener dies, 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.
An SSH terminal that imports your config, forwards your ports, and runs your remote services next to local ones
Six capabilities that change how remote Mac development feels 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 spawns the forward and polls localhost:<port> until something actually accepts a TCP connect — only then does the success toast appear. The toast and the working tunnel are in sync, so you click the link and it works the first time. No more guessing whether ssh -L actually came up.
Remote services in panes, beside your local ones
Services declared in the project's config run on the remote host but stream into lpm panes the same way local services do. Switch between staging-api (remote) and frontend (local) like they're the same shape — because in lpm they are. One native Mac window holds the whole stack regardless of which side of the SSH boundary each piece lives on.
Run an action remotely, or locally against a synced mirror
Each action chooses where it runs: on the remote host over ssh, or locally against a mirror of the remote source tree that pushes your changes back when the command finishes. Local formatters, refactors, and AI coding sessions get to act on remote source without you shuttling files. The choice is per action, so each step picks the right side of the wire.
Connection multiplexing, ready when the tunnel is
Every ssh invocation shares an OpenSSH ControlMaster channel — the first auth pays the cost (including any 2FA on a jump host) and every subsequent service start, action run, and terminal open reuses the channel. Forwards report success only after the local listener actually accepts a connection. Server keepalive surfaces a dropped link promptly instead of leaving you staring at a dead pane.
Per-project remote profile, isolated lifecycle
Each project remembers its own remote — host, user, port, key, and working directory — alongside its services and actions. Forwards, port checks, and synced mirrors are scoped to that project. Stop the project and every forward dies; quit the app and nothing leaks. Prod, staging, and your local copy are three peer projects, one click apart.
What changes when your terminal speaks SSH the way you do
Four concrete wins for Mac developers whose work crosses the SSH boundary.
You stop hand-typing a port-forward command for every remote dev server.
Declared service ports auto-forward at start. Ad-hoc binds — a compose port, a one-off debug server — surface as one-click suggestions in the Ports popover the moment they appear on the remote. The success toast only fires when localhost:<port> actually accepts a connection, so the link in the toast works the first time.
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. Creating a new SSH project drops to four clicks: pick host, confirm, save, start. The ~/.ssh/config file stays the source of truth.
You stop juggling a local terminal and a remote SSH window.
Local services and remote services run in adjacent panes inside one native Mac window. Switching between projects (prod, staging, your local copy) is one sidebar click; running state is preserved per project. The split between "local terminal" and "ssh session" stops existing as a UI concept.
You stop losing forwards and tunnels when something restarts.
Forwards are owned by the project. Stop the project and every forward dies cleanly. Restart and lpm re-establishes them. Quit the app and nothing leaks — no orphan ssh processes hiding in ps, no lsof archaeology to find a tunnel you started yesterday.
Three real remote-dev scenarios your Mac terminal should make trivial
Three concrete moments where the local-vs-remote split costs real time — and how lpm collapses them into one window.
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 ssh invocation prompts for your bastion 2FA once; from then on, the multiplexed channel stays open and 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.
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), run migrate as an action with mode: remote, and watch the staging API pane stream the deploy output. Forward the staging API port to localhost from the Ports popover to verify the fix in your browser. Your local panes never stopped — when you’re done, click back to the local project and pick up exactly where you were.
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.
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.
| Capability | lpm | Dedicated SSH client | Terminal running raw ssh | raw OpenSSH | Editor Remote-SSH |
|---|---|---|---|---|---|
| Reads ~/.ssh/config hosts without replacing OpenSSHlpm uses the selected Host alias when it connects, so OpenSSH remains responsible for options like HostName, ProxyJump, ProxyCommand, Port, and IdentityFile. | Yes | Not built in | Yes | Yes | Yes |
| Remote services run as project panes beside local servicesThis is the lpm project model: services, actions, terminals, and SSH settings live together instead of being separate saved sessions. | Yes | Not built in | Not built in | Not built in | Not built in |
| Declared remote service ports auto-forward after detectionlpm watches remote listening ports for SSH projects and auto-forwards ports declared in the project's services config. | Yes | Not built in | Not built in | Not built in | Not built in |
| Manual forwards wait for localhost readinessWhen you add a forward, lpm waits until the local listener accepts a TCP connection before reporting success. | Yes | Not built in | Not built in | Not built in | Not built in |
| Project stop cleans up the SSH forwards it startedForwards are owned by the lpm project lifecycle, not by whichever tab happened to run an ssh command. | Yes | Not built in | Not built in | Not built in | Not built in |
| Run local tools against a synced mirror of the remote tree that pushes changes backlpm 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. | Yes | Not built in | Not built in | Not built in | Not built in |
lpm
- YesReads ~/.ssh/config hosts without replacing OpenSSH
- YesRemote services run as project panes beside local services
- YesDeclared remote service ports auto-forward after detection
- YesManual forwards wait for localhost readiness
- YesProject stop cleans up the SSH forwards it started
- YesRun local tools against a synced mirror of the remote tree that pushes changes back
Dedicated SSH client
- Not built inReads ~/.ssh/config hosts without replacing OpenSSH
- Not built inRemote services run as project panes beside local services
- Not built inDeclared remote service ports auto-forward after detection
- Not built inManual forwards wait for localhost readiness
- Not built inProject stop cleans up the SSH forwards it started
- Not built inRun local tools against a synced mirror of the remote tree that pushes changes back
Terminal running raw ssh
- YesReads ~/.ssh/config hosts without replacing OpenSSH
- Not built inRemote services run as project panes beside local services
- Not built inDeclared remote service ports auto-forward after detection
- Not built inManual forwards wait for localhost readiness
- Not built inProject stop cleans up the SSH forwards it started
- Not built inRun local tools against a synced mirror of the remote tree that pushes changes back
raw OpenSSH
- YesReads ~/.ssh/config hosts without replacing OpenSSH
- Not built inRemote services run as project panes beside local services
- Not built inDeclared remote service ports auto-forward after detection
- Not built inManual forwards wait for localhost readiness
- Not built inProject stop cleans up the SSH forwards it started
- Not built inRun local tools against a synced mirror of the remote tree that pushes changes back
Editor Remote-SSH
- YesReads ~/.ssh/config hosts without replacing OpenSSH
- Not built inRemote services run as project panes beside local services
- Not built inDeclared remote service ports auto-forward after detection
- Not built inManual forwards wait for localhost readiness
- Not built inProject stop cleans up the SSH forwards it started
- Not built inRun local tools against a synced mirror of the remote tree that pushes changes back
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 next to your local ones, and forwards ports without leaving the window. If you specifically need a saved-snippet library or an SFTP file browser, Termius still does those things; lpm is a terminal-first SSH workspace, not a feature-parity Termius alternative on Mac. For most remote-dev workflows, the terminal-first approach replaces the dedicated client entirely.How does lpm import my SSH config?
When you add an SSH project, lpm reads~/.ssh/config(and any files pulled in byIncludedirectives, up to four levels deep), parses out the non-wildcardHostblocks, 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 asHostName,ProxyJump, andProxyCommand. 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, hit Enter; lpm spawns the forward, pollslocalhost:<port>until something actually accepts a connection, and only then surfaces the success toast. So you know the tunnel is usable, not just spawned. Declared service ports auto-forward at start, and ad-hoc binds discovered on the remote surface as one-click suggestions — remote port forwarding without thessh -Larchaeology.Does lpm work with a jump host or bastion?
Yes, when the jump host is part of the selectedHostentry in your OpenSSH config. lpm saves the host alias and invokes OpenSSH with it, so options such asProxyJump bastionorProxyCommandremain in OpenSSH's hands. The first connection prompts for whatever your bastion requires (key passphrase, 2FA); the multiplexed channel keeps it 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 — each action picks where it runs, independently of the others. Remote actions (the default for SSH projects) run their command on the remote host over ssh — useful for a deploy, a migration, a remote build. The other choice mirrors the remote source tree to your Mac, runs the command locally against the mirror, and pushes changes back — so a local tool (a code formatter, an IDE refactor, an AI coding session) can act on remote source without you shuttling files manually.Is lpm a good iTerm2 or Warp alternative for SSH work specifically?
Both iTerm2 and Warp are capable Mac terminals, and rawsshinside 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 in panes beside local ones, port forwarding with readiness checks, remote port suggestions, and per-project lifecycle for forwards. If your day is mostly local terminal work with the occasionalssh user@host, a general terminal is fine. If you cross the local/remote line every hour, lpm is built for that workflow.
Keep reading
Git terminal for Mac
Branch, rebase, and ship while your dev servers stream in the same window.
Mac terminal for developers
Run your whole stack — services, logs, and agents — in one native Mac app.
Run Claude Code on a remote server
Go a step further than SSH: install lpm on a Linux box and keep its projects and agents running when your Mac is closed.
Your local stack and your remote dev box, finally in the same window.
Free, native, and ready in two minutes.
Download a native macOS binary, drag to Applications, open the picker, and choose a host from your ~/.ssh/config. lpm auto-forwards declared remote service ports when it detects them, offers one-click forwards for other discovered ports, runs remote services in panes alongside local ones, and cleans up the ssh forwards it starts. Works on Intel and Apple Silicon Macs running macOS 12 or later.