PULSOS CLI
Cross-platform deployment monitoring CLI. Track deployments across GitHub Actions, Railway, and Vercel from a single terminal.
What is Pulsos
Pulsos is a terminal tool that gives you a unified view of deployments across GitHub Actions, Railway, and Vercel. It runs as a live TUI dashboard, as a persistent background daemon with a native system-tray icon, or as one-shot CLI output. The correlation engine matches deployment events across platforms by commit SHA and timestamp heuristics, so you can see how a single commit flows through your CI/CD pipeline.
Features
- Live TUI with 5 tabs: Unified, Platform, Health, Settings, Logs
- Cross-platform correlation — matches events by SHA and timestamp proximity
- Health scoring per project (weighted: GitHub 40%, Railway 35%, Vercel 25%)
- DORA metrics — Deployment Frequency, Lead Time, Change Failure Rate, Time to Restore
- Real-time telemetry — Railway container metrics (CPU/RAM) and blackbox endpoint pings (TTFB/uptime)
- Background daemon —
pulsos daemon startruns a persistent process with an Axum SSE server and native tray icon (macOS / Windows) - Auto-discovery of repos, projects, and services via
repos sync - Saved views with filters for project, platform, branch, and status
- ETag caching with rate-limit-aware adaptive polling
- Credential storage — OS keyring with file fallback (
~/.config/pulsos/credentials.toml) - Output formats — table, compact, JSON
- Shell completions for bash, zsh, fish, powershell, elvish
Install
From crates.io
From source
Homebrew (macOS / Linux)
Requirements
- Rust 1.75+
Quick Start
# 1. Authenticate with your platforms
# 2. Discover and track your repos/projects
# 3. Launch the live TUI dashboard
# Or get a one-shot table in your terminal
# Or run as a persistent background daemon
What happens at each step:
pulsos auth <platform>prompts for a token and stores it in your OS keyring (falls back to~/.config/pulsos/credentials.toml).pulsos repos syncqueries each authenticated platform, discovers available repos/projects/services, lets you pick which ones to track, and auto-generates correlations.pulsos statusfetches recent deployments from all tracked resources, correlates them, and displays the result. With--watchit launches the live TUI; without flags it auto-detects (TUI if interactive terminal, one-shot otherwise).pulsos daemon startdetaches the daemon to the background. The TUI automatically connects to the daemon's SSE stream when one is running, saving API quota.
Authentication
Token Resolution Order
Pulsos resolves tokens in this priority order:
- Environment variables — checked first
- OS keyring — via
keyringcrate (macOS Keychain, Windows Credential Manager, Linux Secret Service) - CLI config detection — reads tokens from
gh,railway, andvercelCLI config files
Environment Variables
| Platform | Variables |
|---|---|
| GitHub | GH_TOKEN, GITHUB_TOKEN |
| Railway | RAILWAY_TOKEN, RAILWAY_API_TOKEN |
| Vercel | VERCEL_TOKEN |
Interactive Setup
Each command prompts for a token, validates it against the platform API, and stores it.
Non-Interactive / CI
# Store tokens in one shot (CI mode)
# Check which tokens are resolved
# Re-validate stored tokens; re-prompts if invalid
# Remove stored tokens
Token Detection Toggles
You can disable automatic detection of specific sources in config.toml:
[]
= true
= true
= true
= true
Configuration
Config file location: ~/.config/pulsos/config.toml
Run pulsos config path to print the exact path, or pulsos config edit to open it in $EDITOR.
Full Example
[]
= "github.mycompany.com" # Default: "github.com"
[]
= true
= false
= true
= true
[[]]
= "myorg"
= ["api-*"]
= ["*-legacy"]
= true
[[]]
= "lambda-prod"
= ["my-saas-api"]
= "production" # Default: "production"
[[]]
= "lambda"
= ["my-saas-web"]
= true
[[]]
= "my-saas"
= "myorg/my-saas"
= "my-saas-api"
= "my-saas-web"
[]
= "production"
= "staging"
[[]]
= "production"
= "Production systems"
= ["my-saas", "api-core"]
= ["github", "railway", "vercel"]
= "main"
= ["success", "failure"]
= 5
[[]]
= "backend"
= ["api-core", "auth-service"]
[]
= "dark" # "dark" or "light"
= 10 # Render frames per second
= 5 # Seconds between API polls
= "unified" # "unified", "platform", "health", "settings", "logs"
= true
= "auto" # "auto", "always", "never"
[]
= 100
Config Sections
| Section | Purpose |
|---|---|
[auth] |
GitHub Enterprise host, token detection toggles |
[[github.organizations]] |
Org name, include/exclude repo patterns |
[[railway.workspaces]] |
Workspace name, include/exclude projects, default environment |
[[vercel.teams]] |
Team name, include projects, preview deployment toggle |
[[correlations]] |
Link a GitHub repo, Railway project, and Vercel project under one name |
[[views]] |
Named filter presets (projects, platforms, branch, status) |
[[groups]] |
Named collections of resources for UI-level grouping |
[tui] |
Theme, FPS, refresh interval, default tab, sparklines |
[cache] |
Max cache size in MB |
CLI Commands
Status
Auth
Repos
Views
Config
Daemon
Daemon architecture:
daemon runstarts an Axum SSE server on an ephemeral port, writes the port to~/.config/pulsos/daemon.port, generates a random 64-char bearer token at~/.config/pulsos/daemon.token(mode 0600 on Unix), and (on macOS/Windows) shows a native tray icon in the menu bar.daemon startre-execsdaemon runas a detached process (stdin/stdout/stderr closed).daemon stopreads~/.config/pulsos/daemon.pidand sends SIGTERM (Unix) ortaskkill /F(Windows), then removesdaemon.pid,daemon.port, anddaemon.token.daemon statuschecks the/healthendpoint of the running daemon.- When a daemon is running,
pulsos status --watchconnects to its bearer-auth-protected SSE stream (/api/stream) instead of polling platform APIs directly, conserving rate-limit budget. The/healthendpoint remains public (used bydaemon status). - The tray icon shows three states: neutral (all OK), syncing (blue), alert (red — endpoint down or deployment failure on main/master).
- Desktop notifications fire on endpoint state transitions (up→down, down→up) on macOS and Windows.
Other
Global Flags
| Flag | Description |
|---|---|
--format <table|compact|json> |
Output format (default: table) |
--no-color |
Disable color output |
--verbose |
Show debug information |
--config <path> |
Custom config file path |
TUI Keyboard Shortcuts
| Key | Action |
|---|---|
1–5 |
Switch to tab (Unified, Platform, Health, Settings, Logs) |
Tab / Shift+Tab |
Cycle tabs forward / backward |
j / k or ↑ / ↓ |
Navigate rows |
/ |
Enter search mode |
Enter |
Apply search (in search mode) |
Esc |
Exit search mode / cancel |
r |
Force refresh |
s |
Cycle sort order on Unified tab (by time / by platform) |
q / Ctrl+C |
Quit |
Platform Tab
| Key | Action |
|---|---|
← / → |
Switch provider subtab (GitHub / Railway / Vercel) |
g |
Switch to GitHub subtab |
w |
Switch to Railway subtab |
v |
Switch to Vercel subtab |
d |
Toggle GitHub job/step details panel (GitHub subtab only) |
Platform Tab — Details Panel (GitHub)
| Key | Action |
|---|---|
↑ / ↓ or j / k |
Navigate tree / scroll right panel |
→ / Enter |
Expand job or open right panel |
← |
Collapse job or focus left tree |
PageDown / PageUp |
Scroll right panel by 20 lines |
Ctrl+D / Ctrl+U |
Scroll right panel by 10 lines |
Esc |
Close details panel |
Logs Tab
| Key | Action |
|---|---|
f |
Cycle log level filter (ALL → ERR → WARN → INFO → ALL) |
c |
Copy selected log message to clipboard |
Settings Tab
| Key | Action |
|---|---|
t |
Enter token for selected platform |
T |
Enter token (force override even with env token) |
v |
Validate selected platform |
x |
Remove stored token |
o / Enter |
Start onboarding / discovery flow |
Project Architecture
pulsos-cli/
├── crates/
│ ├── pulsos-core/ # Library crate
│ │ └── src/
│ │ ├── platform/ # GitHub, Railway, Vercel API clients + retry helper
│ │ ├── correlation/ # Event matching engine (SHA + timestamp heuristic)
│ │ ├── domain/ # DeploymentEvent, CorrelatedEvent, DoraMetrics,
│ │ │ # ResourceMetrics, EndpointHealth, health scoring
│ │ ├── auth/ # Credential resolution, KeyringStore, FileCredentialStore, FallbackStore
│ │ ├── config/ # TOML config loading and saving
│ │ ├── cache/ # sled-based ETag cache
│ │ ├── health/ # Platform health checks (PlatformHealthReport) + PingEngine
│ │ ├── scheduler/ # Polling budget and adaptive scheduler
│ │ ├── analytics/ # DoraCalculator
│ │ └── sync/ # Auto-correlation builder (build_correlations, merge)
│ ├── pulsos-cli/ # Binary crate
│ │ ├── assets/ # Embedded tray icon PNGs (neutral, sync, alert — 16x16)
│ │ └── src/
│ │ ├── main.rs # CLI entry point (clap); daemon run owns main thread for tray
│ │ ├── commands/ # Command handlers: status, auth, repos, views, config, doctor, daemon
│ │ │ ├── daemon.rs # pulsos daemon [run|start|stop|status]
│ │ │ ├── wizard.rs # First-run config wizard (auth + discovery + re-check)
│ │ │ └── ui/ # Full-screen interactive prompt layer (ScreenSession)
│ │ ├── daemon/ # Background daemon subsystem
│ │ │ ├── engine.rs # Wraps run_poller; broadcasts DataSnapshot via SSE channel
│ │ │ ├── server.rs # Axum SSE server (/api/stream, /health); writes daemon.port
│ │ │ ├── tray.rs # Native tray icon (macOS/Windows only; tray-icon + tao + muda)
│ │ │ └── notify.rs # Desktop notifications on endpoint state transitions
│ │ ├── tui/ # ratatui live TUI (5 tabs: Unified, Platform, Health, Settings, Logs)
│ │ │ ├── poll.rs # Background poller; connects to SSE if daemon is running
│ │ │ ├── actions.rs # ActionRequest/ActionResult async channel for settings
│ │ │ └── widgets/ # Per-tab rendering components + log_buffer, settings_flow
│ │ └── output/ # Table, compact, JSON formatters
│ └── pulsos-test/ # Test helpers and builders (EventBuilder, mock servers)
└── Cargo.toml # Workspace root
Daemon File Locations
| File | Path | Notes |
|---|---|---|
| Port file | ~/.config/pulsos/daemon.port |
Written by SSE server on bind; mode 0600 on Unix |
| PID file | ~/.config/pulsos/daemon.pid |
Written by daemon run on startup |
| Token file | ~/.config/pulsos/daemon.token |
64-char random hex bearer token; mode 0600 on Unix; removed on stop |
| Credentials | ~/.config/pulsos/credentials.toml |
File-based fallback; mode 0600 on Unix |
| Config | ~/.config/pulsos/config.toml |
Main TOML config |
Polling Intervals (TUI / Poller)
| Platform | Interval | Notes |
|---|---|---|
| GitHub | 30s (adaptive) | Backs off to 60s/120s as rate limit is consumed |
| Railway | 15s | |
| Vercel | 15s | |
| Health checks | 30s | Per-platform token + connectivity readiness |
| Container metrics | 30s | Railway CPU/RAM via GraphQL |
| Endpoint pings | 8s | Blackbox TTFB/uptime; does not consume platform quota |
Development
Prerequisites
- Rust 1.75+
Build
Test
Lint
Run Locally
License
MIT
Last Updated: 2026-02-23