@harborppm/cli
v0.19.0
Published
Harbor from the terminal: a full-screen app with everything, plus commands for scripts and agents.
Maintainers
Readme
Harbor CLI
Harbor in the terminal: a full-screen app with your whole harbor, and commands for scripts and agents.
npm install -g @harborppm/cli
harbor # the full-screen app (signs you in the first time)
harbor mine # or one command at a timeNeeds Node 22 or later.
New to Harbor?
You can start from the terminal. A harbor of your own is free for 30 days, no card; after that it's $49 a month for the whole crew, not per seat.
npm install -g @harborppm/cli
harbor signup # make your account in the browser (email or Google), then come back
harbor # name your harbor and its first project, and you're inharbor signup opens Harbor's page on Create; confirm your email from the letter it sends when you get a moment. The first time you run harbor with no harbor yet, it asks for a name (Enter takes a suggestion) and, if you like, a first project, then opens on it. Joining a team's harbor instead? Open the invite they sent you, and harbor opens on their harbor.
The full-screen app
harbor on its own takes over the terminal, like htop or lazygit, and gives it back when you press q. It opens on Harbor's mark (the teal tile, the H and three boats, drawn in half blocks) while your harbor loads; after that the sidebar holds just the screens. Then:
- Today: today's focus (
fadds or takes off the task you're on, up to three) and your check-in (c); what's on you, late first; who's waiting on you; your risks and issues. - Inbox: the same pings as the website: waiting on you, sign-offs, mentions. Enter opens one; it's marked read.
- Projects: every portfolio, program and project with its health. A project opens on its board (columns side by side;
fandpshow only someone's cards or one priority), its list, or its budget and spend ledger (v);echanges its details: lead, dates, budget, health by hand with a note. - Programs: a program's projects and milestones side by side (
madds a milestone, space ticks one), its next move and health;vreads it project by project, each with its bar across the months, open tasks by status and worst risks. A portfolio opens as a board (programs, with risks, next milestones and money beside them);vreads it program by program. - Risks: the register, worst first. Enter changes one (status, owner, likelihood, impact, mitigation);
nlogs a risk, issue or decision. - People: open and late work and the next four weeks against each person's capacity; Enter changes their capacity, role, or the time they're promised to a program.
- Roadmap: a portfolio's programs and projects across the months, in their health's colour, ◆ for milestones.
- History: who changed what, for a portfolio, program or project (
spicks which).
A task changes in place too: title, status, owner, due date (2026-10-14, today, +3), priority, project, what it waits on (type a key or words), how it repeats, notes, checklist steps, comments (C changes or takes out one of yours).
Keys: ↑↓ (or j k) and ←→ (or h l) move, Enter opens, Esc goes back, : finds anything (a screen, "new project", a project or program by name), / finds a task by its key or words, n makes something new, e changes what's open, [ ] move a card a column, x marks it done, d deletes (it asks first), u undoes your last change, H switches harbor, ? lists them all.
It runs on the same engine as the website: health, task keys, limits and undo work the same way, changes save as you go (the header says when, and holds them while you're offline), and changes anyone makes on the website or elsewhere show up within a couple of seconds. It needs full access, which harbor login asks for by name; an older sign-in is asked again the first time.
It has colours for dark terminals and for light ones, and picks by asking the terminal for its background (or reading COLORFGBG); a terminal that doesn't say gets the dark ones. harbor theme light or harbor theme dark settles it, harbor theme auto goes back to asking, and HARBOR_THEME overrides it for one run.
harbor help shows the mark too, in a terminal with colour; piped, or with NO_COLOR set, it's plain text. harbor --version says which version you have.
On the website
Your harbor is the same one at harborppm.com, signed in with the same account, so the people you work with don't need a terminal. The website adds what a team shares:
- Your crew: invite people by email under People; they see the same boards, risks and roadmap, and their changes reach your terminal within seconds.
- Status for others: the weekly brief, a one-click status report, and read-only links for stakeholders.
- Intake forms: a public form that drops requests onto a project's board.
- GitHub: a pull request that names a task's key (RR-42) shows on the task and moves it along.
- Claude and other AI apps, connected over MCP from harborppm.com/ai.
harbor open RR-42 opens a task on the website (in the right harbor, even when the browser had another one open), harbor open Ridge a project, and harbor open on its own opens Today. harbor invite [email protected] sends Sam the same invite letter the People page does (--viewer to let them look but not change anything); only a harbor's owner can invite. harbor calendar prints your private calendar link, to add to Google, Apple or Outlook calendar: your due dates, milestones and sign-offs beside your meetings, kept up to date (--program NAME for everything dated in one program, --new to swap the link for a fresh one, --off to turn it off).
The website has the commands too: turn on Command line at the bottom in your menu, press /, and type mine, add "Call the mill" #ridge @sam --due fri or done RR-12.
In your shell prompt
harbor prompt prints a few characters for your prompt: ⚓ 2 today · 1 late, with late work in coral, and nothing at all when you're clear. It never waits on the network: it shows the counts it kept and fetches new ones in the background when they're more than five minutes old, or after you change a task. harbor prompt --init zsh (or bash, fish, starship) prints the lines to add to your shell's setup, so harbor prompt --init starship >> ~/.config/starship.toml does it in one go:
# ~/.zshrc
setopt prompt_subst
RPROMPT='$(harbor prompt --shell zsh)'Staying up to date
npm doesn't update a global install by itself, so once a day harbor asks npm whether a newer version is out, alongside whatever command you ran, and says so in one line when there is (npm install -g @harborppm/cli@latest --prefer-online updates it). It says nothing in scripts, pipes or CI; set HARBOR_NO_UPDATE_CHECK=1 (or NO_UPDATE_NOTIFIER=1) to turn it off.
Text from others
Task titles, names and notes can come from an intake form, a GitHub pull request or anyone in a harbor. Before the commands or the app show them, harbor takes out the control characters a terminal would act on (escape sequences, backspaces, text-direction overrides), so a title can't set your clipboard, retitle the window or hide what's around it. --json keeps the data exact, with those characters written as \u escapes.
Signing in
harbor signup is for a first visit: the same sign-in, with the page opened on making an account. harbor login registers the CLI with Harbor and opens the same page Claude and other apps use: it names "Harbor CLI" and asks what to allow. Choose Allow reading only (or run harbor login --read-only) if it shouldn't change anything. The sign-in is saved in ~/.config/harbor/credentials.json, readable only by you, and refreshes itself for 30 days.
harbor logout forgets it on this machine. To end its access everywhere, disconnect Harbor CLI under Connected apps in Harbor's menu.
Commands
harbor harbors the harbors you belong to
harbor use HARBOR|none the harbor to work in when you're in several
harbor programs programs and their projects
harbor projects [words] [--program P] projects with health and open work
harbor mine what's on you, late first
harbor tasks [words] [--project P] [--assignee me|none|NAME] [--late] [--status S,S]
harbor show TASK one task in full, with its web link
harbor open [TASK|PROJECT] open it on the website (or Today)
harbor invite EMAIL [--viewer] invite someone to your harbor by email
harbor calendar [--program P] [--new|--off] your private calendar link (.ics)
harbor program "NAME" [--portfolio P] [--lead me|NAME] [--starts DATE]
[--ends DATE]
harbor project "NAME" --program P [--lead me|NAME] [--starts DATE]
[--ends DATE] [--budget N]
harbor add "TITLE" --project P [--assignee me|NAME] [--due DATE]
[--priority low|medium|high|urgent] [--status S] [--over-limit]
harbor start TASK | review TASK | done TASK [--confirm] [--over-limit]
harbor edit TASK [--title T] [--assignee me|none|NAME] [--due DATE|none]
[--priority P] [--status S] [--notes TEXT]
[--repeat weekly|biweekly|monthly|never]
[--waits-on TASK,TASK|none] [--confirm] [--over-limit]
harbor comment TASK "TEXT"
harbor checkin "WHAT YOU'RE DOING" [--on-blocker]
harbor risk "TITLE" --project P|--program P [--impact 1-5] [--probability 1-5]
[--owner NAME] [--due DATE]
harbor issue "TITLE" --project P|--program P [--impact 1-5] [--owner NAME]
[--due DATE]
harbor decision "TITLE" --project P|--program P [--owner NAME] [--due DATE]
harbor risks [words] [--kind risk,issue,decision] [--project P] [--closed]
harbor premortem PROJECT ["WHAT WENT WRONG"] [--start]
harbor voyage PROJECT ["YOUR LINE"]harbor premortem runs a pre-mortem with your crew: --start asks everyone "it's after the end date and this project failed: what happened?", each person adds answers alone for five minutes, and then the answers show together on the project's Risks & issues tab, where each becomes a risk in one click. On its own it prints the question and the answers you can see. Once a project is Done, harbor voyage prints its voyage log (planned against actual dates, the biggest slips, the risks that came true, who closed the most, and the crew's lines) and adds yours.
Every command takes --json for the raw result (a refusal then comes out as {"error": "…"} on standard output, still with exit code 1), and harbor COMMAND --help shows just that command. Statuses are backlog, todo, doing, review and done. A DATE is YYYY-MM-DD, today, tomorrow, or +N for N days from today.
When you belong to more than one harbor, say which: --harbor NAME on the command, or harbor use NAME once (it's saved with your sign-in; harbor use none forgets it). With neither, the commands ask rather than guess, so nothing lands in the wrong harbor. The full-screen app shares the same choice: it opens the harbor harbor use set, asks which one the first time if none is set, and a harbor you switch to in the app becomes the one the commands use.
Harbor holds back what it would hold back in the app: finishing a task that still waits on another, or going past a column's limit. The CLI says so and names the flag that goes ahead (--confirm, --over-limit).
Every change shows in Harbor's History as yours, "via Harbor CLI". The commands never delete anything; the full-screen app can, as the website can, and asks first.
Another server
harbor login --server https://your-harbor.example (or HARBOR_SERVER). HARBOR_CONFIG_DIR moves the saved sign-in.
Developing
The commands are plain Node with no dependencies. The full-screen app is src/tui in the repository (React with Ink), bundled into dist/app.mjs by node cli/build.mjs; Ink and React are its only dependencies. npm test runs the CLI's tests against a stand-in Harbor; e2e/cli.test.mjs and e2e/terminal-app.test.mjs drive it against a real one.
License
MIT (see LICENSE). The rest of the Harbor repository is private.
