A small desktop app for keeping a tidy stable stack of dev terminals — one tab per project / service, each backed by a real interactive PTY, each remembering its own working directory, environment, command, and tags. Group profiles by tag folders. Start / Stop whole tags at once.
Built with Tauri 2 (Rust) + React + TypeScript +
xterm.js, so the bundle is a small native .app rather
than an Electron-sized download. macOS is the primary target today (hidden
titlebar + traffic-light overlay tuned for the sidebar header), but the Tauri
shell and the PTY layer (portable-pty) are cross-platform; Windows / Linux
builds should work and just won't get the macOS-specific chrome polish.
A normal terminal multiplexer (tmux, iTerm tabs, VS Code's terminal) is fine for one project. As soon as a workday means "start the API, start the worker, start the web dev server, tail this log, attach to that container, keep a free shell for ad-hoc", the friction adds up:
- You retype (or up-arrow-fish) the same
cd … && npm run devfor each tab. - You can't tell at a glance which sessions are actually up.
- "Stop everything for this project" means clicking through eight tabs.
- A wedged foreground job (Docker Compose, a hung dev server) needs a manual Ctrl+C.
- When something exits with a non-zero code in the background, you don't notice until you switch back to its tab.
Lowcal Terminal Orchestrator makes each of those things a button:
- The command, cwd, env and tags live in a YAML file the app owns.
- A coloured status dot per tab — green for running, gray for stopped, red when a Start-injected command exited non-zero (with the exit code surfaced on hover).
- Tags in the sidebar let you group, and bulk-start/stop projects.
| Layer | Tech |
|---|---|
| Shell / packaging | Tauri 2 (Rust) |
| Frontend | React 18 + TypeScript + Vite |
| Terminal renderer | xterm.js + @xterm/addon-fit |
| PTY | portable-pty |
| PTY ↔ frontend bridge | axum WebSocket on 127.0.0.1:<dynamic> |
| Config | YAML via serde_yaml, watched with notify |
| Native dialogs | tauri-plugin-dialog |
- macOS (primary), or Linux / Windows for unsupported-but-likely-works builds.
- Node.js 18+ and npm.
- Rust toolchain (stable). Install via rustup.
- Tauri 2 prerequisites for your OS — see
Tauri's prerequisites guide.
On macOS that's Xcode Command Line Tools (
xcode-select --install).
git clone https://github.com/achekulaev/lowcal.git
cd lowcal
npm install
npm run tauri devThe Tauri dev command starts Vite on http://localhost:1420, builds the Rust
side, and launches the desktop window with hot reload for the frontend.
On first launch, Lowcal copies terminals.example.yaml
into the OS app config directory as terminals.yaml. Edit it from inside the
app (right-click a profile → Edit, or + for a new one) or directly on
disk — external saves are watched and prompt to reload.
npm run tauri buildThis runs the frontend build (tsc && vite build) and produces:
src-tauri/target/release/bundle/macos/LowCal.appsrc-tauri/target/release/bundle/dmg/LowCal_<version>_<arch>.dmg
Tauri usually opens the DMG window after a successful build so you can drag
the app into /Applications yourself.
LowCal is a personal-scratch project and isn't currently signed with a paid
Apple Developer ID certificate, so the build you produce locally (or
download from a release, if any) is ad-hoc signed. macOS Gatekeeper sees
that, marks the .dmg as quarantined when it lands in ~/Downloads, and on
first launch you'll get one of:
- "LowCal" can't be opened because Apple cannot check it for malicious software.
- "LowCal" is damaged and can't be opened. You should move it to the Trash. (This second message is misleading — the app isn't damaged, it's just quarantined and unsigned.)
Two ways past it, pick whichever you prefer:
Option A — right-click → Open (one-time, GUI):
- Drag
LowCal.appinto/Applicationsfrom the DMG. - In Finder, right-click (or Control-click) the app → Open.
- In the warning dialog, click Open again.
macOS remembers the exception per app, so subsequent launches are normal double-clicks.
Option B — strip the quarantine flag (one-time, terminal):
xattr -dr com.apple.quarantine "/Applications/LowCal.app"After this the app launches with a normal double-click.
If you build LowCal yourself with npm run tauri build and run it from
src-tauri/target/release/bundle/macos/LowCal.app directly, you usually
won't hit the quarantine dialog at all — the flag is only added by Safari,
Mail, AirDrop, etc. when a file arrives from "outside".
terminals.yaml lives in the OS app config directory (e.g. on macOS:
~/Library/Application Support/dev.lowcal.terminal-orchestrator/terminals.yaml).
| Shortcut | Action |
|---|---|
Cmd+T / Ctrl+T |
Open New terminal (create profile). |
Cmd+= / Ctrl+= |
Same as New terminal. |
Cmd+F / Ctrl+F |
Focus sidebar profile filter (flat-results mode). |
Esc |
In the filter: clear and close. In the editor modal: cancel. |
Cmd+Enter / Ctrl+Enter |
In the editor modal: save. |
This is a personal-scratch project that I've been finding useful enough to keep iterating on. The API and config schema may shift between minor versions; the YAML config is forward-compatible (unknown fields are preserved by the editor) but no formal migration guarantees yet.
Issues and PRs welcome, but expect slow turnaround.
No license is published in this repository yet. Until one is added, the default is all rights reserved — please open an issue if you'd like to use it for anything beyond evaluation.
