{"id":51358489,"url":"https://github.com/me-shaon/pulsedeck","last_synced_at":"2026-07-02T21:31:10.353Z","repository":{"id":366744662,"uuid":"1275399788","full_name":"me-shaon/pulsedeck","owner":"me-shaon","description":"PulseDeck — the reporting inbox for your AI agents.","archived":false,"fork":false,"pushed_at":"2026-06-30T16:34:56.000Z","size":2415,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-30T18:19:01.727Z","etag":null,"topics":["ai-agents","automation","dashboard"],"latest_commit_sha":null,"homepage":"https://pulsedeck.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/me-shaon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-20T16:31:33.000Z","updated_at":"2026-06-30T16:34:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/me-shaon/pulsedeck","commit_stats":null,"previous_names":["me-shaon/pulsedeck"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/me-shaon/pulsedeck","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/me-shaon%2Fpulsedeck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/me-shaon%2Fpulsedeck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/me-shaon%2Fpulsedeck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/me-shaon%2Fpulsedeck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/me-shaon","download_url":"https://codeload.github.com/me-shaon/pulsedeck/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/me-shaon%2Fpulsedeck/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35064248,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","automation","dashboard"],"created_at":"2026-07-02T21:31:05.343Z","updated_at":"2026-07-02T21:31:10.342Z","avatar_url":"https://github.com/me-shaon.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/pulsedeck-logo.svg\" /\u003e\n    \u003cimg src=\"./assets/pulsedeck-logo-light.svg\" alt=\"PulseDeck\" width=\"280\" /\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003cbr /\u003e\n\n**A self-hosted dashboard for your AI agents' output.**\n\nAgents, scripts, and automations send their reports to PulseDeck. You get one clean, searchable place to read them — instead of digging through Slack, email, and terminal logs.\n\n[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-2dd4bf.svg?style=flat-square)](./LICENSE)\n![Self-hosted](https://img.shields.io/badge/Self--hosted-one_command-2dd4bf?style=flat-square)\n![Node.js](https://img.shields.io/badge/Node.js-LTS-339933?style=flat-square\u0026logo=node.js\u0026logoColor=white)\n![PostgreSQL](https://img.shields.io/badge/PostgreSQL-16-4169e1?style=flat-square\u0026logo=postgresql\u0026logoColor=white)\n\n[Quick start](#quick-start) · [What you get](#what-you-get) · [Connect an agent](#connect-an-agent) · [Documentation](#documentation)\n\n\u003c/div\u003e\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"./assets/dashboard.png\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n    \u003cpicture\u003e\n      \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/dashboard-dark.png\" /\u003e\n      \u003cimg src=\"./assets/dashboard.png\" alt=\"PulseDeck — click to view full size\" /\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Quick start\n\nYou need [Docker](https://docs.docker.com/get-docker/) and `make` (plus\n`openssl`, preinstalled on macOS/Linux).\n\n```bash\ngit clone https://github.com/me-shaon/pulsedeck.git pulsedeck \u0026\u0026 cd pulsedeck\nmake setup        # creates .env and generates strong secrets (idempotent)\ndocker compose up # or `make up` to build + run detached\n```\n\n`make setup` is required: the stack refuses to boot without a real\n`AUTH_SECRET`/`POSTGRES_PASSWORD`, so it can never run on a known value.\n\nOpen **http://localhost:3000**, create your account and workspace, and you're running.\n\n### See it with live data\n\nWant to watch it fill up? Run the built-in demo agent — it sends realistic reports every 30 seconds:\n\n1. In the app, go to **Sources → Add source** and copy the registration token (`reg_…`).\n2. Run the demo agent:\n\n```bash\npnpm --filter @pulsedeck/demo dev --url http://localhost:3000 --token reg_xxxxx\n```\n\nCharts, streams, and the live feed start populating right away.\n\n\u003e **Heads up:** the demo agent runs with Node 22+ and pnpm on your host — it's a\n\u003e workspace package, not part of the Docker image. If you set up with Docker and\n\u003e don't have Node/pnpm, either install them or skip the demo; PulseDeck itself\n\u003e runs fine without it.\n\n\u003e **Port already taken?** Override it inline, e.g. `WEB_PORT=8080 docker compose up`.\n\u003e Defaults: web `3000`, api `3001`, postgres `5432`.\n\n### Run without Docker\n\n\u003cdetails\u003e\n\u003csummary\u003eManual setup for local development and production (no Docker required)\u003c/summary\u003e\n\nPulseDeck is a standard pnpm monorepo. The only external service it needs is\n**PostgreSQL** — Redis is optional (used solely for multi-replica realtime\nfan-out). The API applies its database migrations automatically on startup, so\nthere is no separate migration step.\n\n#### Prerequisites\n\n- **Node.js 22+**\n- **pnpm 9.15+** — `corepack enable \u0026\u0026 corepack prepare pnpm@9.15.0 --activate`\n- **PostgreSQL 16+** — running and reachable\n\n#### 1. Install dependencies\n\n```bash\ngit clone https://github.com/me-shaon/pulsedeck.git pulsedeck \u0026\u0026 cd pulsedeck\npnpm install --frozen-lockfile\n```\n\n#### 2. Create the database\n\n```bash\npsql -U postgres -c \"CREATE USER pulsedeck WITH PASSWORD 'pulsedeck';\"\npsql -U postgres -c \"CREATE DATABASE pulsedeck OWNER pulsedeck;\"\n# Postgres 15+ locks down the public schema — grant it explicitly:\npsql -U postgres -d pulsedeck -c \"GRANT ALL ON SCHEMA public TO pulsedeck;\"\n```\n\n#### 3. Configure the API\n\nThe API reads its config from `apps/api/.env` (real environment variables always\nwin). Create it with at least the two required values:\n\n```bash\ncat \u003e apps/api/.env \u003c\u003c'EOF'\nDATABASE_URL=postgres://pulsedeck:pulsedeck@localhost:5432/pulsedeck\nAUTH_SECRET=replace-with-32+-random-chars   # e.g. `openssl rand -base64 48`\nEOF\n```\n\nAll other options (retention, OAuth, signup mode, …) are documented in\n[`.env.example`](./.env.example). Note `DATABASE_URL` ships **commented out**\nthere: the Docker stack builds its own URL (DB host `postgres`) from\n`POSTGRES_PASSWORD`, and a `localhost` value in the root `.env` would break it.\nFor this non-Docker path you set `DATABASE_URL` explicitly (host `localhost`) in\n`apps/api/.env`, as above.\n\n#### 4a. Local development (hot reload)\n\n```bash\npnpm dev\n```\n\nThis starts the API on **:3001** and the web dev server on **:3000** (Vite\nproxies `/api` → the API, keeping cookies first-party). Migrations run on API\nstart. Open **http://localhost:3000**.\n\nThe demo agent works the same as above:\n`pnpm --filter @pulsedeck/demo dev --url http://localhost:3000 --token reg_xxxxx`.\n\n#### 4b. Production\n\n**Build everything:**\n\n```bash\npnpm build\n```\n\nThis emits the API bundle to `apps/api/dist` and the static web bundle to\n`apps/web/dist`.\n\n**Start the API** (it applies pending migrations, then listens):\n\n```bash\ncd apps/api\nNODE_ENV=production \\\nDATABASE_URL=postgres://pulsedeck:pulsedeck@localhost:5432/pulsedeck \\\nAUTH_SECRET=your-32+-char-secret \\\nBETTER_AUTH_URL=https://your.domain \\\nPORT=3001 \\\nnode dist/index.js\n```\n\nKeep it alive with a process manager (systemd, pm2, …). `BETTER_AUTH_URL` must be\nthe **public origin users hit** (the web origin below), not the API port.\n\n**Serve the web bundle.** `apps/web/dist` is static files. The SPA calls `/api`\non its own origin, so put a reverse proxy in front that serves the static files\n**and** forwards `/api` to the API. Example nginx (mirrors the bundled\n[`apps/web/nginx.conf`](./apps/web/nginx.conf)):\n\n```nginx\nserver {\n  listen 80;\n  server_name your.domain;\n  root /path/to/pulsedeck/apps/web/dist;\n  index index.html;\n\n  location /api/ {\n    proxy_pass http://127.0.0.1:3001;        # keeps the /api prefix\n    proxy_http_version 1.1;\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    # Server-Sent Events (live updates): flush immediately, don't time out.\n    proxy_set_header Connection '';\n    proxy_buffering off;\n    proxy_read_timeout 1h;\n  }\n\n  location / {\n    try_files $uri $uri/ /index.html;        # SPA client-side routing\n  }\n}\n```\n\nCaddy alternative (`Caddyfile`):\n\n```caddyfile\nyour.domain {\n  root * /path/to/pulsedeck/apps/web/dist\n  handle /api/* {\n    reverse_proxy 127.0.0.1:3001\n  }\n  handle {\n    try_files {path} /index.html\n    file_server\n  }\n}\n```\n\nPut TLS in front (Caddy does this automatically; for nginx use certbot) and set\n`BETTER_AUTH_URL=https://your.domain` to match.\n\n\u003c/details\u003e\n\n---\n\n## What you get\n\n- **One inbox for every agent** — reports land organized into categories and streams, newest first.\n- **Rich, structured reports** — metrics, charts, tables, timelines, alerts, and status grids, not just walls of text.\n- **Search everything** — full-text search and filters by source, severity, tags, and date.\n- **Custom dashboards** — drag-and-drop widgets to build the view you want.\n- **Teams** — multiple workspaces, roles, and invite links.\n- **Live updates** — new reports appear instantly, no refresh needed.\n- **Yours to host** — one command, only needs PostgreSQL. No SaaS lock-in.\n\n---\n\n## Connect an agent\n\nAny agent that can make an HTTP request can send reports — no SDK or special library needed. Register once to get an API key, then `POST` your reports.\n\nThe **Add source** page in the app gives you a ready-to-paste setup prompt. For the full API, see the [documentation](#documentation).\n\nWant a working example? [`packages/demo`](./packages/demo) is a complete reference agent you can read and copy.\n\n---\n\n## Email \u0026 password reset\n\nOut of the box PulseDeck sends no email — invite links surface in the app, and the\n**Forgot password?** flow shows a warning that email isn't configured. To enable\npassword-reset delivery (and emailed invites), point PulseDeck at an SMTP server:\n\n```bash\nEMAIL_PROVIDER=smtp\nEMAIL_FROM=\"PulseDeck \u003cno-reply@yourdomain.com\u003e\"\nSMTP_HOST=smtp.yourprovider.com\nSMTP_PORT=587            # 587 STARTTLS (default) or 465 with SMTP_SECURE=true\nSMTP_USER=...\nSMTP_PASS=...\n```\n\nOnce `EMAIL_PROVIDER=smtp` and `SMTP_HOST` are set, the admin banner in **Settings**\ndisappears and reset links are delivered by email. Any standard SMTP provider works\n(Mailgun, Postmark, SES SMTP, Resend SMTP, your own server, etc.). See\n[`.env.example`](./.env.example) for all options.\n\n---\n\n## Documentation\n\nDetailed guides — configuration, deployment, the full agent API, and development setup — live on the docs site:\n\n📖 **[PulseDeck Documentation](https://pulsedeck.app/docs)**\n\nQuick links for now:\n\n- **Configure** — all options live in [`.env.example`](./.env.example).\n- **Develop** — `make dev` runs the whole stack in Docker with hot reload. `make help` lists every command.\n- **Contribute** — see [`CONTRIBUTING.md`](./CONTRIBUTING.md).\n\n---\n\n## License\n\nPulseDeck is licensed under the **GNU AGPL v3** — see [`LICENSE`](./LICENSE). Contributions require agreement to the [CLA](./CONTRIBUTING.md). Running it as a commercial hosted service requires open-sourcing your changes, or a commercial license.\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"./apps/web/public/pulsedeck-mark.svg\" alt=\"PulseDeck\" width=\"40\" /\u003e\n\n**PulseDeck** — a home for your agents' reports.\n\n\u003csub\u003eSelf-hosted · Open source · AGPL v3\u003c/sub\u003e\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fme-shaon%2Fpulsedeck","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fme-shaon%2Fpulsedeck","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fme-shaon%2Fpulsedeck/lists"}