English | 简体中文
A self-hosted, HUD-inspired project dashboard with no third-party runtime dependencies and an authenticated REST API for automation agents.
HSS Projects stores project state on your own Linux or macOS machine and serves responsive Kanban, dependency, and monthly archive views in the browser. It requires no database, npm packages, pip packages, cloud account, or external CDN. A small Python standard-library server lets desktops, tablets, and phones share the same server-authoritative project state.
HSS Projects is intended for personal use or sharing between trusted devices. It is not a multi-user SaaS with accounts, authorization, and audit trails. Do not expose its raw HTTP listener directly to the untrusted public Internet.
Runtime requirements:
- Linux or macOS
- Bash 3.2+
- Python 3.10+
Download or clone the repository, enter its directory, and run:
chmod +x start.sh
./start.shOpen:
http://127.0.0.1:4173/
Press Ctrl+C to stop the service. start.sh runs in the foreground; use systemd, launchd, or another process manager if you need a long-running service.
The first start creates data/agent-token for the Agent API. The first project save creates data/projects.json. These private runtime files are excluded from Git by default.
If the system python3 is too old, the launcher also checks python3.10 through python3.14. You can select an interpreter explicitly:
HSS_PYTHON=/path/to/python3.11 ./start.shThe server uses only the Python standard library. pip, Homebrew, and GNU coreutils are not required.
- Five workflow lanes: Planned, Active, Needs Attention, Paused, and Done
- Create, edit, delete, search, filter by priority, and sort projects
- Move cards by dragging them or by using each card's status menu
- The browser UI tracks priority, area, status, next action, target date, and an optional dependency
- The Agent API additionally exposes summary, health, progress, tags, blocker details, and a next-action due date
- Kanban, dependency, and archive views; the graph draws only explicitly recorded dependencies
- Explicitly archive completed projects, group them by UTC year and month, and track current, archived, yearly, and monthly project counts
- Cold Steel Blue, ARC HUD, and green CRT terminal themes
- HUD scan sweeps and confirmation particles, plus a distinct synthesized Web Audio cue set for each theme
- No external image, font, or audio requests
- Respects
prefers-reduced-motion; UI sounds can also be disabled from the•••menu - Responsive desktop, tablet, and phone layouts; the phone board scrolls one lane per screen
- Polling-based cross-device synchronization, revision- and ETag-based optimistic concurrency protection, and a previous-version backup
- JSON import, export, and one-click demo projects
- Bearer-token Agent REST API with constrained project query and mutation operations
- Optional Linux/macOS MarkDash bridge with scoped per-device ingestion, automatic status projection, and server-hosted read-only details
Theme and sound preferences stay in each browser's localStorage; they do not change server project data.
Set a project to Done, open it, and choose Archive project. It leaves the current Kanban and dependency views and appears under Archive, grouped by the UTC year and month recorded in archivedAt. Open an archived project and choose Restore to Done to return it without changing its original completion time.
Older stage: "archived" records remain compatible. If they do not have a valid archivedAt, grouping falls back to completedAt, updatedAt, and createdAt; records without any valid timestamp appear under Unknown date. Merely opening or filtering the archive does not rewrite server data.
HSS can mirror multiple local MarkDash workspaces without exposing their local boards or databases. One MarkDash workspace becomes one HSS project card. A small bridge on each Linux or macOS device reads the official MarkDash JSON CLI output and makes outbound HTTPS requests to a device- and project-scoped HSS ingestion endpoint.
The existing board layout and themes do not change. A synchronized card is a read-only source projection: its status, health, progress, next action, blocker summary, and issue counts come from MarkDash. HSS continues to own portfolio metadata such as priority, area, dates, dependencies, notes, and archive state. Clicking the card opens an HSS-hosted detail snapshot, so it remains viewable when the MarkDash computer is offline. Completed synchronized projects can be archived or restored from that detail page; later syncs never auto-unarchive them. The detail page's Edit HSS information action opens the existing project form for the HSS-owned fields while keeping every source-owned field locked.
By default, the bridge derives lifecycle state from all issues. A configured
statusIssueId can act as the canonical project-status issue instead. Only
issue ID, title, status, priority, category, update time, limited blocker IDs,
and aggregate counts are uploaded. Descriptions, notes, comments, metadata,
labels, people, local paths, and database details stay on the MarkDash device.
Server-side setup uses a private registry with one token and an exact project allowlist per device:
{
"schemaVersion": 1,
"devices": [
{
"deviceId": "mac-mini-01",
"tokenFile": "tokens/mac-mini-01.token",
"projects": ["00000000-0000-0000-0000-000000000000"]
}
]
}Save it as data/markdash-registry.json, set it and every referenced token to
mode 0600, and restart with ./start.sh; the
launcher enables ingestion automatically when that default file exists. A
custom location can be enabled explicitly:
./start.sh --markdash-registry-file /private/path/markdash-registry.jsonThen use MarkDash's built-in hss configure, sync, or watch commands (or its
local board button). HSS no longer ships a duplicate client. See the
MarkDash integration guide.
Choose the smallest listening scope that fits the access path:
| Scenario | Command | Notes |
|---|---|---|
| This machine only | ./start.sh |
Listens only on 127.0.0.1:4173 by default |
| Reverse-tunnel client on the same machine | ./start.sh |
Prefer forwarding 127.0.0.1:4173; --public is usually unnecessary |
| Direct access from other LAN devices | ./start.sh --public --port 8080 |
Binds to 0.0.0.0; open http://<device-ip>:8080/ |
| Reverse proxy on the same machine | ./start.sh |
Proxy to the loopback listener; terminate TLS and enforce authentication at the external entry point |
A reverse tunnel is not an authentication boundary. It can publish a service that still listens only on 127.0.0.1, allowing remote visitors to read and modify project data. Prefer a private VPN or overlay network. If a public entry point is unavoidable, protect the entire application with HTTPS, access control, and reliable authentication.
Run ./start.sh --help for the complete launcher reference.
| Option | Environment variable | Default | Purpose |
|---|---|---|---|
--bind ADDRESS |
BIND_ADDRESS |
127.0.0.1 |
Set the listening address |
--public |
— | Off | Bind to 0.0.0.0 |
--port PORT |
PORT |
4173 |
Set the listening port |
--data-file FILE |
DATA_FILE |
data/projects.json |
Set the server data file |
--agent-token-file FILE |
AGENT_TOKEN_FILE |
data/agent-token |
Set the Agent token file |
--no-agent-api |
— | Not set (API enabled) | Disable the Agent API for this run |
--markdash-registry-file FILE |
MARKDASH_REGISTRY_FILE |
Beside the data file | Enable MarkDash ingestion with a private device registry |
--markdash-data-dir DIR |
MARKDASH_DATA_DIR |
markdash/ beside the data file |
Set the private detail-snapshot directory |
--no-markdash-sync |
— | Off | Disable ingestion even when the default registry exists |
| — | HSS_PYTHON |
Auto-detected | Select a Python 3.10+ interpreter |
Linux users can keep runtime state under their user data directory:
./start.sh \
--data-file "$HOME/.local/share/hss-projects/projects.json" \
--agent-token-file "$HOME/.local/share/hss-projects/agent-token"Paths containing spaces are supported on macOS:
./start.sh \
--data-file "$HOME/Library/Application Support/HSS Projects/projects.json" \
--agent-token-file "$HOME/Library/Application Support/HSS Projects/agent-token"The server is the authoritative source of project state. Default runtime files:
| File | Purpose | Commit to Git? |
|---|---|---|
data/projects.json |
Current project state | No |
data/projects.json.bak |
State from immediately before the latest successful save | No |
data/projects.json.lock |
Single-instance file lock | No |
data/agent-token |
Agent API credential, mode 0600 |
No |
data/markdash-registry.json |
Device identities, token-file references, and exact project scopes | No |
data/tokens/*.token |
Per-device MarkDash ingestion credentials, mode 0600 |
No |
data/markdash/*.json |
Privacy-minimized MarkDash detail snapshots, mode 0600 |
No |
Each save atomically replaces the primary file and increments revision. Only one HSS process may use a given data file, preventing separate processes from bypassing version checks and overwriting one another.
Export JSON regularly from the ••• menu. To back up or restore server files manually:
- Stop HSS Projects.
- Copy
projects.jsonand any.bakfile you need to retain. - After restoring, verify that only the current user can read and write the files, then restart the service.
Treat the .bak file as sensitive as the primary data file: it may contain projects that were later changed or deleted.
Use a different random value for every MarkDash device token and for the Agent API token. HSS refuses to start if an Agent token is reused as an ingestion credential, because that would silently turn a project-scoped credential into a full Agent credential.
MarkDash detail snapshots can be recreated by the bridge, but the registry and
its token files should be backed up through the same private credential process
you use for other server secrets. Stop HSS before restoring the state and
snapshot files together. The snapshot path must be a dedicated, non-symlink
directory owned by the HSS user with mode 0700 (or stricter); HSS refuses a
broad or permissive existing directory and never changes that directory's mode.
Use a local ext4 or XFS filesystem on Linux, or local APFS on macOS, when possible. Avoid placing active data on exFAT, SMB/NFS, or cloud-synchronized directories; they may not reliably preserve 0600 permissions, atomic replacement, or flock semantics.
Legacy browser data can migrate automatically. If the server is empty, HSS attempts to import hss-project-hud:v1 from the same browser origin. After a successful migration, the old value remains only as a migration backup. Corrupted, schema-mismatched, or invalid files are never replaced with an empty state.
A normal ./start.sh launch securely creates a token and enables the Agent API. Disable it when automation access is not needed:
./start.sh --no-agent-apiThe API prefix is /api/agent/v1. It provides capability discovery, state summaries, project listing, and ETag-protected create, partial update, and delete operations. The detailed reference is currently available in Chinese in AGENT_API.md, including the complete field contract, authentication rules, and Python/curl examples.
The Agent token protects only /api/agent/v1; the browser-facing /api/state endpoint is unauthenticated. The token is one shared credential that grants every operation exposed by the Agent API, with no read-only scopes, per-agent identities, granular revocation, or built-in rate limiting. Protect it like a password: never commit it to Git, paste it into prompts, or send it over plaintext HTTP.
If a reverse proxy uses Authorization for Basic/OIDC authentication, it may conflict with the Agent and MarkDash bearer tokens. Prefer a VPN, or use cookie/session authentication, mTLS, a separate hostname, or a separate proxy header for the browser-facing application. The proxy must preserve the original bearer header for /api/agent/v1 and MarkDash PUT /api/integrations/markdash/v1/projects/.../snapshot; keep browser-facing GET/PATCH routes behind the site's normal authentication.
Built-in safeguards include:
- Loopback-only listening by default
- A static-file allowlist that never serves
data/or the Agent token - Agent bearer authentication, token-file permission checks, and constant-time comparison
- Separate MarkDash device tokens with exact server-side project allowlists
- Owner-only MarkDash registry/config/token files and a dedicated owner-only snapshot directory
- No permissive CORS headers for cross-origin browser API access; CORS is not an authentication boundary
- JSON request-size limits and strict field contracts
- Atomic writes, private file modes, a single-instance lock, and ETag conflict protection
- CSP, frame blocking,
nosniff, and request logs that omit query strings
HSS Projects deliberately does not implement user accounts, TLS, access-log management, rate limiting, malicious-traffic protection, or multi-tenant authorization. For public deployment, provide those controls with a VPN, authenticated HTTPS reverse proxy, firewall, and identity system appropriate to your environment.
The Agent API and server test suite require Bash 3.2+ and Python 3.10+, with no third-party packages:
python3 -B tests/agent_api_smoke.py
python3 -B tests/markdash_integration_smoke.pyThe complete browser regression suite additionally requires Node.js 22+ and Chromium or Google Chrome:
node tests/smoke.mjsOn Linux, the test searches PATH for Chromium/Chrome. On macOS, it also checks /Applications and ~/Applications. You can override the browser path:
CHROMIUM_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
node tests/smoke.mjsThe suites cover authentication and constrained CRUD, scoped MarkDash ingestion, canonical snapshot validation, bridge retry and privacy behavior, persistence, legacy migration, concurrency conflicts, synchronized-card read-only behavior, detail rendering and archive/restore, drag-and-drop/status changes, UTC year-month grouping and counts, dependencies, themes and sound, reduced-motion behavior, JSON import, and viewports at 1440, 390, and 320 CSS pixels wide. Automated browser coverage currently targets Chromium/Chrome; Safari has not received equivalent automated regression coverage.
.
├── README.md # Primary English documentation
├── README.zh-CN.md # Simplified Chinese documentation
├── LICENSE # MIT License
├── start.sh # Linux/macOS launcher
├── server.py # Static server, state API, Agent API, and file store
├── AGENT_API.md # Detailed Agent API reference in Chinese
├── integrations/
│ └── markdash/ # Server-side integration guide and registry example
├── web/
│ ├── index.html # Workspace and project form
│ ├── styles.css # Three HUD themes and responsive layout
│ ├── app.js # Board UI, server sync, dependency/archive views, effects, and sound
│ └── markdash.* # Responsive server-hosted MarkDash detail page
├── tests/
│ ├── agent_api_smoke.py # Real server and launcher tests
│ ├── markdash_integration_smoke.py # Scoped ingest and snapshot tests
│ ├── smoke.mjs # Chromium end-to-end regression suite
│ └── fixtures/ # Synthetic test fixtures only
└── data/ # Private runtime state, ignored by Git
.gitignore excludes the default data directory, Agent tokens, default-named project exports, environment files, private-key material, logs, caches, and local editor state. Always inspect the actual Git index before the first push.
If a state, Agent token, MarkDash registry, device token, bridge config, bridge
runtime state, or snapshot directory uses a custom location inside the
repository, .gitignore cannot predict every arbitrary filename. Keep live
configuration and state outside the repository or add an exact ignore rule
before the first launch.
git status --short --ignored
git ls-files -ci --exclude-standard
git diff --cached --name-onlyThe following check should show that each default private file is covered by an ignore rule:
git check-ignore -v --no-index \
data/projects.json data/projects.json.bak \
data/projects.json.lock data/agent-token \
data/markdash-registry.json data/tokens/device.token \
data/markdash/example.jsonDo not upload the entire working directory with Finder, zip -r, or GitHub's web file uploader. Those methods do not honor .gitignore and can include the real data/ directory. After committing, create source archives from tracked files only:
git archive --format=tar.gz -o ../hss-projects-src.tar.gz HEADIf Git has ever tracked a sensitive file, adding it to .gitignore will not remove it from the index or history. Rotate any exposed token first, then clean the index and repository history.
HSS Projects is licensed under the MIT License. You may use, copy, modify, merge, publish, distribute, sublicense, and sell copies of the software as long as the copyright and license notices are preserved.