The Hub
Red Pen Hub PRO v0.6.0
One board that aggregates Red Pen notes from every project and every surface into a single screen - and lets you resolve and reopen them in place. The Hub is the PRO convenience layer; it gates nothing on any single surface.
Principles
- Local-first. The Hub is a small app you run on your own machine. There is no SaaS, no account, no telemetry, and no kill switch.
- No phone-home. It only ever reads the stores you connect and writes back only when you click a button. Nothing is sent anywhere on its own.
- It is never your only copy. The source of truth always stays at the surface - the WordPress database, the
.redpen/notes.jsonfile, the browser. The Hub aggregates; it does not own your notes. - It gates nothing on any surface. Every individual surface stays free and complete on its own. The Hub is the paid convenience layer - free for up to three projects, unlimited with a one-time PRO key.
License and the free tier v0.6.0
The Hub is the PRO product, and it unlocks with the same offline-signed license key as the WordPress plugin's branded report. Paste your key into the PRO panel on the Sources tab; it is verified locally against a public key embedded in the app - no account, no phone-home, no expiry, no kill switch. A valid key shows a "Licensed to ..." confirmation and unlocks unlimited projects, forever.
Without a key the Hub still runs and is fully usable - it just aggregates up to three projects on the board, with a banner offering to unlock the rest. That is a genuine try-before-buy, not a crippled demo: everything works, you simply see three projects until you unlock unlimited. Configure as many sources as you like; the cap is only on what the board aggregates, and lifting it never touches your notes.
Running the Hub
The Hub is a standalone local Node application. Install dependencies and start it:
npm install
npm start
# Red Pen Hub running at http://localhost:3900
It will eventually also ship as npx red-pen-hub and as a single-file executable so it can run with no Node setup at all (see Distribution below). Open http://localhost:3900 in a browser to use the board.
Configuration - sources.json
All configuration lives in a single sources.json file next to the app. It is user-specific and gitignored - it never ships. The fields you care about:
| Field | Purpose |
|---|---|
port | The port the board serves on. Defaults to 3900. |
sources | The curated list of PULL and FILE sources you have added (see below). PUSH sources are not listed here - they self-register. |
hubToken | A shared token, generated once and persisted, that connected sites use to push notes to this Hub. Never phoned home anywhere. |
licenseKey | Your PRO license key, saved when you paste it on the Sources tab. Verified locally against the embedded public key; blank on the free tier. |
repoPaths | An optional map of project name to local git repository path, used only to show the passive clean / dirty indicator in the Sources tab. |
Getting notes onto the board
There are three ways a project's notes reach the Hub. You can mix all three on one board.
| Method | Direction | Best for | Auth |
|---|---|---|---|
| Connect a Site (push) | The site posts to the Hub | WordPress sites, the static drop-in | Hub URL + one shared token |
| Add Projects (pull) | The Hub reads the source | WordPress installs, file stores discovered by a scan | Application Password for WordPress pull |
| File source | The Hub reads a file | Express, static exports, Ableton - anything with a .redpen/notes.json | None - direct file read |
1. Connect a Site (push)
The easiest path, and the one that scales. Instead of the Hub reaching out to each site, each site posts its notes to the Hub. A connecting site needs only two things: the Hub's URL and one shared token - the same token everywhere. There are no per-site passwords and no URLs to guess.
On the site side, you paste the Hub URL and token into that surface's "Connect to Hub" control - the Display settings on the WordPress plugin, or the "Connect to Hub" panel in the static drop-in's All-notes board. From then on the site pushes its notes to the Hub whenever they change. The first push self-registers the project - it appears on the board automatically, with no "Add" step, and is stored as a single JSON file under the Hub's connected/ directory.
http://localhost:3900, not localhost:3900. A schemeless URL is silently rejected by WordPress sanitization and the connection appears to save but never pushes. The plugin now defaults a missing scheme to http://, but it is worth typing in full.
2. Add Projects (pull)
The pull path is driven by a scan. Click + Add Projects in the Sources tab, point it at a development directory, and the Hub walks that directory and detects every Red Pen install regardless of platform:
- File stores - any
.redpen/notes.json(Express apps, static exports, Ableton). - WordPress installs - any folder with a
wp-config.phpand the Red Pen plugin present, with a guessed local URL.
The scan returns a checklist, pre-checked, with note counts. You uncheck what you do not want and confirm; your selection is persisted to sources.json. WordPress pull sources read the plugin's REST endpoint and need an Application Password (not the login password) entered once. Note that local WordPress sites are usually better connected by push - pull is most useful for file stores and for remote sites that cannot reach a localhost Hub.
3. File sources
A file source is the simplest kind - a direct path to a .redpen/notes.json store. The Hub reads it straight off disk. This is how Express apps, static exports, and the Ableton extension's store appear on the board. File sources are discovered by the Add Projects scan or can be added directly.
The board
The board is the whole interface. Everything is filterable and sortable, and the view follows a set of tabs.
Status tabs
Across the top, tabs split notes by where they are in the workflow, each with a live count that respects your active filters:
| Tab | Shows |
|---|---|
| Open | Notes not yet started. The default view. |
| In progress | Notes being worked. |
| Resolved | Closed notes. |
| All | Every note, any status. |
| Projects | One row per project with its open / in-progress / resolved / total breakdown - including connected projects that currently have zero notes. Click a project to drill into its notes. |
| Sources | The source management view - add, connect, re-check, set a repo path, edit credentials, or remove a source. |
Columns
Each note row reads at a glance. The old single "When" column was split into a Created and a Resolved column so you can see and sort by when a note opened and when it closed; "Where" was renamed Location. Every row also shows a compact byline - author, assignee, and reply count - and, when a note is resolved, the resolver's name under the Resolved date. Severity shows when a note has one (see Severities).
Filtering, sorting, and saved views
Above the table sit a search box and four dropdowns - project, surface, type, and priority - which combine to narrow the list. Every column header is sortable; clicking a header toggles the direction, and an arrow marks the active sort column. The board defaults to sorting by priority, highest first, so the most urgent notes are always on top. Each row has a jump-to-source link that opens the note at its origin, and a dark / light toggle lives in the header.
The board now remembers where you left it: the active tab, the sort column and direction, and all filters persist across reloads. You can also save named views - a filter set you name once ("high-priority open on project X") and jump straight back to.
Start - the third state from the board
Open notes carry a Start button that moves them to in progress, alongside the existing Resolve / Reopen controls. The full three-state workflow (Open -> In progress -> Resolved) is now reachable directly from the board, not just at the source surface.
Write-back - resolve and reopen in place
The Hub is not read-only. Every note row carries a Resolve button (and Reopen once resolved). Clicking it changes the note's status and writes that change back to the note's real source of truth - so the board and the origin stay in sync without you visiting each project. The Hub routes the change to the right place automatically based on where the note came from:
| Source kind | How write-back is applied | Durable? |
|---|---|---|
| File store | Edits the note's status directly in its .redpen/notes.json. | Yes - the file is the source of truth. |
| WordPress (pull) | POSTs to the plugin's status route using the source's Application Password. | Yes - written to the WordPress database. |
| Connected (push) | Merges the status into the Hub's copy so it survives future pushes, and hands the change back to the origin site so it updates locally too. | Yes - durable and two-way (v0.5.9 + v0.5.11). |
If a write-back fails - a site is unreachable, an Application Password lacks rights - the board surfaces an error toast rather than failing silently.
Export
The Export MD button turns the current view into an Obsidian-friendly Markdown checklist - notes grouped by project, with checkboxes, type and priority, and a link back to each source. It is a tracking digest you can paste into a vault or a ticket, not a generated prompt. You can copy it to the clipboard or download it as a .md file.
Alongside it, a CSV export dumps the current view as a spreadsheet-ready file - the same notes, in a format you can open in a spreadsheet, filter, or hand off. Both exports run locally with no external service.
Passive git status
In the Sources tab you can point each project at its local git repository using the repo action. Once a path is set, that source row shows a read-only indicator of whether the repository is clean or has uncommitted changes, along with the branch. This is purely informational - a glance at which projects have unsaved work - and the Hub takes no action on it.
Assignees and automated work
A planned direction for the Hub is to treat coding agents (Claude and similar) as assignable users alongside people, so a note reads clearly as automated versus manual work. The assignee model already exists on the WordPress surface today. Bringing it to the Hub - including the ability to set an assignee from the board via write-back - is on the Roadmap.
Security posture
The Hub is a loopback-only, single-user local tool, and it is built to stay that way. The hardening in place:
- Loopback bind only. The server binds
127.0.0.1/::1- it does not listen on your network. - DNS-rebinding guard. Requests with a non-loopback
Hostheader are rejected, so a malicious page cannot rebind a domain to your local Hub. - Constant-time token comparison. The connect token is checked without leaking timing information.
- Bounded outbound fetches. When the Hub pulls a source, requests are restricted to
http(s)and redirects are bounded and re-validated at every hop. - Protected credential file.
sources.jsonis written with0600permissions (owner-only).
It deliberately does not block internal or LAN addresses, because aggregating local development sites - which live exactly there - is the Hub's whole reason for existing. Blocking them would defeat the tool.
Accessibility
The board is keyboard- and screen-reader-operable, not mouse-only:
- Sortable column headers are keyboard-operable and announce their state with
aria-sort. - The status tabs announce which one is active.
- Modals have proper dialog roles, trap focus while open, and close on Esc.
- The light / dark toggle is a real, announced switch control rather than a bare button.
Distribution and licensing
The Hub is the PRO tier of Red Pen. It is not tied to XAMPP or any one stack - it reads stores wherever they live. Planned distribution is via npm (npx red-pen-hub) and a single-file executable, so it runs without an Electron bundle or a Node setup.
The PRO unlock is a one-time, lifetime purchase - no subscription, no renewals. Unlocking uses an offline-signed license key: the key is verified locally against an embedded public key, with no phone-home and no kill switch. Consistent with the rest of Red Pen, the unlock only adds convenience; it never disables a feature that was free on any individual surface.