Skip to content

About

A self-hosted, HUD-inspired project dashboard with no third-party runtime dependencies and an authenticated REST API for automation agents.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

Repository files navigation

HSS Projects

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.

Start in 30 seconds

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.sh

Open:

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.sh

The server uses only the Python standard library. pip, Homebrew, and GNU coreutils are not required.

Interface and features

  • 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.

Monthly archive

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.

MarkDash synchronization

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.json

Then 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.

Multi-device access

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.

Configuration

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"

Data, backup, and recovery

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:

  1. Stop HSS Projects.
  2. Copy projects.json and any .bak file you need to retain.
  3. 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.

Agent API

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-api

The 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.

Security boundaries

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.

Validation and compatibility

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.py

The complete browser regression suite additionally requires Node.js 22+ and Chromium or Google Chrome:

node tests/smoke.mjs

On 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.mjs

The 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.

Project layout

.
├── 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

Preventing data leaks when publishing

.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-only

The 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.json

Do 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 HEAD

If 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.

License

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.

About

A self-hosted, HUD-inspired project dashboard with no third-party runtime dependencies and an authenticated REST API for automation agents.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages