Node-based terminal manager for AI coding agents — tmux-backed terminals and parallel agent sessions as draggable nodes on an infinite pan/zoom canvas. macOS, Linux, and a browser Server Edition.
1,765
stars
3,286
commits
TypeScript
primary language
Sep 4, 2026
updated
A node-based terminal manager — your terminals and agents on an infinite canvas.
Multiple real terminals live as draggable nodes on a single pan/zoom canvas, and every project doubles as a Trello-style board of live Claude Code sessions. Built for people with ADHD and scattered workflows: a spatial layout instead of a stack of hidden tabs.
Download · Docs · Features · Build from source · Architecture · License
Stacked terminal tabs hide context — you lose track of what's running where. nodeterm turns that into a map: every shell is a node you can place, group, label, and zoom into. Sessions are spatial and persistent, so your mental model stays intact across restarts. And because the app is built around a clean service seam, the same canvas runs three ways — as the desktop app for macOS, Linux and Windows (beta), as a self-hosted browser app you reach from anywhere (Server Edition), and an iOS companion that attaches to the same live sessions.
📚 Full documentation lives at nodeterm.dev/docs — get started, concepts, agents, remote access, troubleshooting.
Everything is a nodeRight-click the canvas to open a terminal — or an AI agent. Each runs in its own persistent tmux session, next to sticky notes (link one to feed an agent context), Monaco editors, diff views, and web/video nodes — arranged spatially, like a map. Quit the app, even restart the machine — every session comes back. | ![]() |
Know when an agent needs youHook-driven status — no output scraping: pulsing RUNNING / NEEDS YOU badges, subagent cards with live transcripts, a per-node context meter, and OS notifications. Click the ping, answer the permission prompt right in the node, and get told the moment the turn is done. On a MacBook, agents live in the notch too. | ![]() |
One project, two viewsEvery project is a canvas — and also a kanban board. Cards are your live
sessions: drag them across columns while the agent keeps running, open a card into a
live card modal (the real session + members, due date, priority, comments), and
assign teammates. Toggle with | ![]() |
Your sessions, anywherePair your phone with one QR — scan with the nodeterm iOS app — and the same live session continues in your pocket, E2E encrypted over the relay, not just your LAN. The same canvas also runs self-hosted in any browser (Server Edition). | ![]() |
Talk to your terminalHold | ![]() |
🖥 Terminal (xterm + tmux, AI naming) · 🤖 Agent (Claude Code / Codex / Gemini / GitHub Copilot / opencode / Grok / custom) · 📝 Sticky note (link to an agent as context) · 🗂 Group (bind to a git worktree for agent-per-branch) · ✏️ Editor (Monaco, ⌘S) · 🔀 Diff · 🌐 Web / Video
claude --resume). The macOS app ships its own tmux, so this works
with nothing installed; a tmux already on your system is always used in preference to it,
and terminals opened before an upgrade stay as they were until you refresh the node.gh sign-in — backed by system git.The same canvas runs headless on a Linux (or macOS) host and is used from any browser — so your terminals, editors, source control, board, and agents live on a server you reach from anywhere. Single-user auth (password + secure cookie), a WebSocket bridge, and the exact same renderer as the desktop app.
npm run server:dev # build + serve; open http://127.0.0.1:8443 and set a password
Terminals, files/editor/diff, the full git panel, the kanban board, and agent-status
badges all work in the browser today. See docs/SERVER.md for the
quickstart, security model, and current limitations.
The same server also runs headless as a background notification host: install it on any Linux box you SSH into, and your phone gets RUNNING / NEEDS YOU push + Live-Activity coverage for the agents running there — with zero open ports (the hook server stays loopback-only and push goes out over HTTPS under a grant your phone drops over SSH).
curl -fsSL https://raw.githubusercontent.com/eneskirca/nodeterm/main/scripts/install-server.sh | bash
One line installs, builds, and runs it as a systemd service (NODETERM_HEADLESS=1); re-run it
to update. See the headless notification host
section for details.
Grab the latest build from nodeterm.dev — the download button detects your platform. Everything is also listed at nodeterm.dev/releases:
macOS — .dmg for Apple Silicon and Intel (auto-updates), or Homebrew:
brew tap nodeterm/tap
brew trust nodeterm/tap # Homebrew ≥6 refuses to load an untrusted tap
brew install --cask nodeterm
Both first lines are required. On its own, brew install --cask nodeterm only searches
homebrew/cask and reports the cask as not found; without the trust grant, Homebrew ≥6
fails rather than prompting. The cask tracks each promoted release, and the app updates
itself (electron-updater), so brew upgrade is rarely needed for it.
Linux (x64) — self-updating AppImage, or a .deb for Debian/Ubuntu
(sudo apt install ./nodeterm-*.deb; updates are manual for .deb).
Windows (x64) — beta — nodeterm-Setup-<version>.exe (per-user installer) or a
portable -win.zip. Early support, so know what you are getting: the installer is
unsigned (SmartScreen will ask — More info → Run anyway), updates are manual
for now (grab the next build from the same page), and session continuity across
restarts is still landing — Windows has no tmux, so the standalone session host that
replaces it is being packaged in #579.
Everything else — canvas, agents, kanban, hooks — is the same app. Please
report what breaks.
iOS — nodeterm mobile on the App Store.
Trying it out? Removal is one script — it stops every process nodeterm started, reverts
the status-hook/skill entries it merged into your agent CLIs' config (your own hooks and
credentials are never touched), and deletes all of nodeterm's own state. Run it with
--dry-run first to see the full list of what it found:
curl -fsSL https://raw.githubusercontent.com/eneskirca/nodeterm/main/scripts/uninstall.sh | bash -s -- --dry-run
curl -fsSL https://raw.githubusercontent.com/eneskirca/nodeterm/main/scripts/uninstall.sh | bash -s -- --yes
The full inventory of what nodeterm writes where (and what the script keeps, like the
.nodeterm/ canvas folders inside your own repos) is documented in
docs/uninstall.md.
Requires Node.js 20+ on macOS or Linux (tmux recommended — it's what makes sessions
survive restarts). A source checkout does not carry the bundled tmux: run
node scripts/build-tmux.mjs once on macOS to build it into resources/bin/tmux (the
release job does this automatically), or just install tmux yourself. On Windows, run
bootstrap-windows.bat from a fresh checkout first — it checks for Node, the Visual Studio
C++ build tools and Python 3 (needed to compile node-pty) and points you at the exact
winget commands for anything missing, then runs npm ci.
npm install # deps + rebuilds node-pty against Electron's ABI (postinstall)
npm run dev # dev mode with renderer HMR
npm run build # production build into out/
npm start # preview the production build
npm run typecheck # fastest correctness gate
npm test # vitest unit + integration suite
npm run dist # local UNSIGNED .dmg into dist/ (smoke test)
npm run dist:linux # AppImage + .deb into dist/ (on a Linux host)
npm run dist:win # unsigned NSIS installer + zip into dist/ (on a Windows host)
npm run server:dev # build + run the browser Server Edition (needs Node 22 + tmux)
These are the defaults — every one of them is remappable in Settings → Keyboard Shortcuts.
| Shortcut | Action |
|---|---|
⌘K | Command palette |
⌘T / ⌘⇧C | New terminal / New Claude Code |
⌘⇧B | Toggle the kanban board |
⌘W | Close the selected node |
⌘← ⌘→ ⌘↑ ⌘↓ | Focus the node left / right / above / below (Ctrl+Shift+arrow off macOS) |
⌘Z / ⌘⇧Z | Undo / Redo |
⌘M | Toggle markdown view (terminal / editor) |
Hold ⌘⌥ (Ctrl+Alt) | Dictate into the focused terminal |
⌘⇧E | File explorer |
⌘, | Settings · ⌘/ Shortcuts |
Right-click | Actions menu (empty space or node) |
src/main (the Electron shell), src/preload (the only
bridge, window.nodeTerminal), src/renderer (React UI). src/shared holds the types
and IPC channel names used by all three.CorePlatform seam — every service (PTY, workspace/settings, git, agents, hooks) lives
in src/core behind a small platform interface and never imports electron. Electron is
one implementation of that seam; the browser Server Edition (src/server) is another,
booting the exact same services over a WebSocket-RPC bridge (src/renderer/bridge fills
window.nodeTerminal in the browser). One codebase, one renderer, multiple shells.TerminalTransport abstraction — the renderer depends only on this interface, never on
IPC or node-pty directly. LocalTransport talks to the local host; RemoteTransport talks
to a remote agent over SSH — so remote projects drop in without touching the canvas UI.See docs/SERVER.md for the Server Edition, and the design docs
under docs/ for deeper notes.
Issues and pull requests are welcome. Start with CONTRIBUTING.md — setup, the process-boundary rules, and the house rules that come up in review. CLAUDE.md is the deep reference behind them (and is loaded automatically if you work with an AI coding agent). Questions or bug reports are also happy at nodeterm.dev/support / support@nodeterm.dev. nodeterm is licensed under the Business Source License 1.1 — you can use, modify, and redistribute it freely, including in production, except offering it as a competing product or service (see License).
By submitting a contribution (pull request, patch, or code snippet), you agree that it is licensed under the same BUSL-1.1 terms as the rest of the project, and that the project may continue to relicense future versions (including your contribution) as part of its normal licensing model.
BUSL-1.1 (Business Source License): you may
copy, modify, redistribute, and — under the Additional Use Grant — make production
use of nodeterm; the one thing you may not do is offer it (hosted, embedded, or as a
standalone product/service) in a way that competes with nodeterm or with the
Licensor's products built on it. Each release automatically becomes plain MIT four
years after it is published. See LICENSE for the full terms and
THIRD-PARTY-NOTICES.md for the bundled open-source
components. For a commercial license beyond the grant, contact eneskirca@gmail.com.
"Claude" and "Claude Code" are trademarks of Anthropic, and "Trello" is a trademark of Atlassian; nodeterm is not affiliated with or endorsed by either.
TypeScript
97.0%
CSS
2.1%
Node-based terminal manager for AI coding agents — tmux-backed terminals and parallel agent sessions as draggable nodes on an infinite pan/zoom canvas. macOS, Linux, and a browser Server Edition.
1,765
stars
3,286
commits
TypeScript
primary language
Sep 4, 2026
updated
A node-based terminal manager — your terminals and agents on an infinite canvas.
Multiple real terminals live as draggable nodes on a single pan/zoom canvas, and every project doubles as a Trello-style board of live Claude Code sessions. Built for people with ADHD and scattered workflows: a spatial layout instead of a stack of hidden tabs.
Download · Docs · Features · Build from source · Architecture · License
Stacked terminal tabs hide context — you lose track of what's running where. nodeterm turns that into a map: every shell is a node you can place, group, label, and zoom into. Sessions are spatial and persistent, so your mental model stays intact across restarts. And because the app is built around a clean service seam, the same canvas runs three ways — as the desktop app for macOS, Linux and Windows (beta), as a self-hosted browser app you reach from anywhere (Server Edition), and an iOS companion that attaches to the same live sessions.
📚 Full documentation lives at nodeterm.dev/docs — get started, concepts, agents, remote access, troubleshooting.
Everything is a nodeRight-click the canvas to open a terminal — or an AI agent. Each runs in its own persistent tmux session, next to sticky notes (link one to feed an agent context), Monaco editors, diff views, and web/video nodes — arranged spatially, like a map. Quit the app, even restart the machine — every session comes back. | ![]() |
Know when an agent needs youHook-driven status — no output scraping: pulsing RUNNING / NEEDS YOU badges, subagent cards with live transcripts, a per-node context meter, and OS notifications. Click the ping, answer the permission prompt right in the node, and get told the moment the turn is done. On a MacBook, agents live in the notch too. | ![]() |
One project, two viewsEvery project is a canvas — and also a kanban board. Cards are your live
sessions: drag them across columns while the agent keeps running, open a card into a
live card modal (the real session + members, due date, priority, comments), and
assign teammates. Toggle with | ![]() |
Your sessions, anywherePair your phone with one QR — scan with the nodeterm iOS app — and the same live session continues in your pocket, E2E encrypted over the relay, not just your LAN. The same canvas also runs self-hosted in any browser (Server Edition). | ![]() |
Talk to your terminalHold | ![]() |
🖥 Terminal (xterm + tmux, AI naming) · 🤖 Agent (Claude Code / Codex / Gemini / GitHub Copilot / opencode / Grok / custom) · 📝 Sticky note (link to an agent as context) · 🗂 Group (bind to a git worktree for agent-per-branch) · ✏️ Editor (Monaco, ⌘S) · 🔀 Diff · 🌐 Web / Video
claude --resume). The macOS app ships its own tmux, so this works
with nothing installed; a tmux already on your system is always used in preference to it,
and terminals opened before an upgrade stay as they were until you refresh the node.gh sign-in — backed by system git.The same canvas runs headless on a Linux (or macOS) host and is used from any browser — so your terminals, editors, source control, board, and agents live on a server you reach from anywhere. Single-user auth (password + secure cookie), a WebSocket bridge, and the exact same renderer as the desktop app.
npm run server:dev # build + serve; open http://127.0.0.1:8443 and set a password
Terminals, files/editor/diff, the full git panel, the kanban board, and agent-status
badges all work in the browser today. See docs/SERVER.md for the
quickstart, security model, and current limitations.
The same server also runs headless as a background notification host: install it on any Linux box you SSH into, and your phone gets RUNNING / NEEDS YOU push + Live-Activity coverage for the agents running there — with zero open ports (the hook server stays loopback-only and push goes out over HTTPS under a grant your phone drops over SSH).
curl -fsSL https://raw.githubusercontent.com/eneskirca/nodeterm/main/scripts/install-server.sh | bash
One line installs, builds, and runs it as a systemd service (NODETERM_HEADLESS=1); re-run it
to update. See the headless notification host
section for details.
Grab the latest build from nodeterm.dev — the download button detects your platform. Everything is also listed at nodeterm.dev/releases:
macOS — .dmg for Apple Silicon and Intel (auto-updates), or Homebrew:
brew tap nodeterm/tap
brew trust nodeterm/tap # Homebrew ≥6 refuses to load an untrusted tap
brew install --cask nodeterm
Both first lines are required. On its own, brew install --cask nodeterm only searches
homebrew/cask and reports the cask as not found; without the trust grant, Homebrew ≥6
fails rather than prompting. The cask tracks each promoted release, and the app updates
itself (electron-updater), so brew upgrade is rarely needed for it.
Linux (x64) — self-updating AppImage, or a .deb for Debian/Ubuntu
(sudo apt install ./nodeterm-*.deb; updates are manual for .deb).
Windows (x64) — beta — nodeterm-Setup-<version>.exe (per-user installer) or a
portable -win.zip. Early support, so know what you are getting: the installer is
unsigned (SmartScreen will ask — More info → Run anyway), updates are manual
for now (grab the next build from the same page), and session continuity across
restarts is still landing — Windows has no tmux, so the standalone session host that
replaces it is being packaged in #579.
Everything else — canvas, agents, kanban, hooks — is the same app. Please
report what breaks.
iOS — nodeterm mobile on the App Store.
Trying it out? Removal is one script — it stops every process nodeterm started, reverts
the status-hook/skill entries it merged into your agent CLIs' config (your own hooks and
credentials are never touched), and deletes all of nodeterm's own state. Run it with
--dry-run first to see the full list of what it found:
curl -fsSL https://raw.githubusercontent.com/eneskirca/nodeterm/main/scripts/uninstall.sh | bash -s -- --dry-run
curl -fsSL https://raw.githubusercontent.com/eneskirca/nodeterm/main/scripts/uninstall.sh | bash -s -- --yes
The full inventory of what nodeterm writes where (and what the script keeps, like the
.nodeterm/ canvas folders inside your own repos) is documented in
docs/uninstall.md.
Requires Node.js 20+ on macOS or Linux (tmux recommended — it's what makes sessions
survive restarts). A source checkout does not carry the bundled tmux: run
node scripts/build-tmux.mjs once on macOS to build it into resources/bin/tmux (the
release job does this automatically), or just install tmux yourself. On Windows, run
bootstrap-windows.bat from a fresh checkout first — it checks for Node, the Visual Studio
C++ build tools and Python 3 (needed to compile node-pty) and points you at the exact
winget commands for anything missing, then runs npm ci.
npm install # deps + rebuilds node-pty against Electron's ABI (postinstall)
npm run dev # dev mode with renderer HMR
npm run build # production build into out/
npm start # preview the production build
npm run typecheck # fastest correctness gate
npm test # vitest unit + integration suite
npm run dist # local UNSIGNED .dmg into dist/ (smoke test)
npm run dist:linux # AppImage + .deb into dist/ (on a Linux host)
npm run dist:win # unsigned NSIS installer + zip into dist/ (on a Windows host)
npm run server:dev # build + run the browser Server Edition (needs Node 22 + tmux)
These are the defaults — every one of them is remappable in Settings → Keyboard Shortcuts.
| Shortcut | Action |
|---|---|
⌘K | Command palette |
⌘T / ⌘⇧C | New terminal / New Claude Code |
⌘⇧B | Toggle the kanban board |
⌘W | Close the selected node |
⌘← ⌘→ ⌘↑ ⌘↓ | Focus the node left / right / above / below (Ctrl+Shift+arrow off macOS) |
⌘Z / ⌘⇧Z | Undo / Redo |
⌘M | Toggle markdown view (terminal / editor) |
Hold ⌘⌥ (Ctrl+Alt) | Dictate into the focused terminal |
⌘⇧E | File explorer |
⌘, | Settings · ⌘/ Shortcuts |
Right-click | Actions menu (empty space or node) |
src/main (the Electron shell), src/preload (the only
bridge, window.nodeTerminal), src/renderer (React UI). src/shared holds the types
and IPC channel names used by all three.CorePlatform seam — every service (PTY, workspace/settings, git, agents, hooks) lives
in src/core behind a small platform interface and never imports electron. Electron is
one implementation of that seam; the browser Server Edition (src/server) is another,
booting the exact same services over a WebSocket-RPC bridge (src/renderer/bridge fills
window.nodeTerminal in the browser). One codebase, one renderer, multiple shells.TerminalTransport abstraction — the renderer depends only on this interface, never on
IPC or node-pty directly. LocalTransport talks to the local host; RemoteTransport talks
to a remote agent over SSH — so remote projects drop in without touching the canvas UI.See docs/SERVER.md for the Server Edition, and the design docs
under docs/ for deeper notes.
Issues and pull requests are welcome. Start with CONTRIBUTING.md — setup, the process-boundary rules, and the house rules that come up in review. CLAUDE.md is the deep reference behind them (and is loaded automatically if you work with an AI coding agent). Questions or bug reports are also happy at nodeterm.dev/support / support@nodeterm.dev. nodeterm is licensed under the Business Source License 1.1 — you can use, modify, and redistribute it freely, including in production, except offering it as a competing product or service (see License).
By submitting a contribution (pull request, patch, or code snippet), you agree that it is licensed under the same BUSL-1.1 terms as the rest of the project, and that the project may continue to relicense future versions (including your contribution) as part of its normal licensing model.
BUSL-1.1 (Business Source License): you may
copy, modify, redistribute, and — under the Additional Use Grant — make production
use of nodeterm; the one thing you may not do is offer it (hosted, embedded, or as a
standalone product/service) in a way that competes with nodeterm or with the
Licensor's products built on it. Each release automatically becomes plain MIT four
years after it is published. See LICENSE for the full terms and
THIRD-PARTY-NOTICES.md for the bundled open-source
components. For a commercial license beyond the grant, contact eneskirca@gmail.com.
"Claude" and "Claude Code" are trademarks of Anthropic, and "Trello" is a trademark of Atlassian; nodeterm is not affiliated with or endorsed by either.
TypeScript
97.0%
CSS
2.1%