RELEASE HISTORY

Changelog

What's shipped in LastPing, most-recent first. This page is where future releases are appended. The project lives at github.com/tp322d/lastping-app.


2026

Improvement

Keys made by agents now expire, and no key outlives its creator

The 31 August entry below said keys created through the REST API, MCP or Terraform still default to no expiry. That is no longer true of MCP. A key created by an agent through create_api_key, and a key created from the connect page, now default to 90 days — or to the creating key's own expiry, if that comes sooner.

The bigger change is a ceiling rather than a default: a key created by a key may not be given a later expiry than the key that creates it. Ask for a longer one and the request is refused, and the refusal tells you the latest date you may ask for. A leaked credential can no longer be spent on minting a longer-lived replacement for itself before anyone notices and revokes it.

Omitting expires_at is unchanged everywhere it already worked: in the console, and through the REST API or Terraform, an omitted value still means no expiry. Only the ceiling is new. A future release will let an omitted value take the creating key's expiry instead of no expiry at all, once the Terraform provider can represent that.

Feature

API keys: regenerate in one click, and a default expiry

A new API key is shown once and stored only as a hash, so a key you did not copy cannot be recovered. That is still true — but losing one no longer means leaving a live key behind and creating a second. Every key now has a Regenerate action that issues a replacement under the same name and stops the old one immediately.

Keys created in the console now carry an expiry, 90 days by default, with 30 days, a year, and “never” also available. The expiry date is shown in the key list. Keys created through the REST API, MCP or Terraform are unchanged: those surfaces take an explicit expires_at and still default to no expiry.

Feature

Find the jobs nobody is watching

An agent can now scan a repository or a host, work out what ought to be monitored, and hand LastPing the list. Cron tables, GitHub Actions schedules, Kubernetes CronJobs and systemd timers. Nobody fills in a form.

All the scanning happens on the agent's side — LastPing never reads your repository. It supplies three things: what to look for, a diff of a scan against what already exists, and a bulk create.

The important property is that it is safe to re-run. Sources already monitored come back untouched — not the name, not the schedule, not a threshold you tuned by hand. Monitors whose source has disappeared are reported, never deleted. So you can run it nightly, and the second run tells you what has appeared and what has gone: a scan that runs once is a setup wizard, a scan that is safe on a schedule is drift detection.

Discovered monitors say where they came from, on the monitor's own page. And because a crontab job fires in its host's local time rather than UTC, a scan that finds one must state the zone it read — guessing puts the deadline about twenty hours off and pages you every day. The reconcile step ships as one MCP tool, discover_monitors_reconcile, which takes the server to 36 tools.

Improvement

Exit codes are kept, not thrown away

A job that reports its exit code was having the number discarded at the front door: 137, 124 and 1 all became simply "failed". They are not the same failure. 137 is the OOM killer, 124 is a timeout, and 1 is whatever the program decided.

The code is now recorded and shown on the incident, translated where the meaning is unambiguous — "killed by SIGKILL" rather than a bare 137 — and left plain where it is application-defined, because a confident wrong explanation is worse than a number. Runs that reported no code say nothing rather than claiming a clean exit.

Feature

Is this new, and was it slow?

An incident now says how many times that exact failure has happened and when it was first seen. Failures are matched by normalising the body first — timestamps, request IDs, IP addresses, file paths and numbers are replaced before comparison — so two runs that failed the same way an hour apart, with different retry counts and different request IDs, are recognised as the same failure rather than two unrelated ones.

That answer outlives its evidence. The comparison is kept separately from the pings it came from, so it still works after those pings age out of retention. "First time" and "the fortieth time" need different responses, and until now nothing told you which one you were looking at.

A monitor's runs are also compared against its typical duration — each day's own median run, then the median of those. A run materially slower than usual is marked, showing both durations and how many days it was measured over, so the comparison is checkable rather than something to take on trust. A monitor too young to have a baseline says so instead of implying the run was normal.

Feature

The agent reads why it failed, and writes back what it found

An agent can now start a run by asking what its previous runs left behind: GET /api/v1/agents/{id}/open-incidents returns each open incident with the cause, the failure body, the step it died on, how many times that same failure has occurred, and how the run's duration compared to normal. "Your check failed" is worth nothing to an agent that already knows; what it cannot work out for itself is whether this has happened before.

It can then write back an explanation, which appears on the incident attributed to the agent. Instead of "check failed at 03:04", the person reading the alert gets "failed because the upstream API returned 503; same failure as the last three nights; I retried twice and stopped."

Notes are append-only. A correction is a new note, never an edit — a diagnosis whose history a reader cannot trust is not evidence. Reading the inbox and writing a note are available over both REST and MCP (list_open_incidents and add_incident_note), and the agent is told about them in its ping instructions. Those two take the MCP server from 33 to 35 tools.

Feature

An agent can no longer grade its own run

An agent reports its own success by calling the success ping. That is self-grading, and it is the failure liveness monitoring cannot see: an agent that finishes confidently and produces garbage looks exactly like one that worked.

With declare_run_expectations, an agent commits at the start of a run to the criteria that run will be judged by — before it can see how things turn out. A success ping whose body does not meet them is recorded as a failed run, whatever the exit code says, and the incident names the criterion that was not met.

The declaration is immutable: a second attempt for the same run is refused and the first one stands. An agent that could revise its criteria once it saw the outcome coming would simply be grading itself again, with extra steps. Declaring nothing is still allowed — an agent that says nothing leaves the monitor's own assertions in force. It is one new MCP tool, taking the server from 32 to 33.

Improvement

Hooks report failure too, and the console stops guessing at connection state

Claude Code's hook install (hook_install) wired up Stop for success but nothing for failure — Stop fires for any turn that ends, cleanly or not, so a turn that died on an API error still reported as a success. StopFailure, the hook Claude Code fires instead of Stop when that happens, is now wired up too. Monitors also gained a notification duration floor (notify_min_run_s): a run shorter than the floor is still recorded but does not notify, so a fleet of fast jobs stops paging on every completion — a failure is never suppressed by it, regardless of duration.

The connect page and the agent detail page now show whether MCP is actually connected instead of assuming it from a key being present, which caught a real bug: an invalid API key used to return a green "connected" state with the full tool list attached. The MCP server now validates the bearer token and returns 401 for anything invalid.

Feature

Incidents say what happened

An incident used to be titled by the rule that fired it — silence, overrun, assertion. It now reads as a sentence built from what was actually recorded: Stopped reporting 42m ago, Stopped 52s into a run, last step: export, Ran, but rows processed was 3 (expected at least 10).

Where the data does not support a sentence the plain cause is shown instead. There is no confidence score: detection here is deterministic — a deadline passed or it did not — and a percentage would suggest the alert might be wrong when it cannot be.

Feature

A silence floor, so a quiet agent cannot read healthy

An on-demand monitor has no cadence, so between runs it armed nothing at all — an agent that simply stopped reporting stayed green. That is the one failure this product exists to catch, so it is now catchable: set expect_every_s and the monitor alerts if nothing at all arrives inside that window.

It is opt-in, and it stands down while a run is in flight — that window belongs to the run budget — and while the agent is blocked waiting on a person.

Feature

lastping run — reporting you cannot forget

Asking a job — or an AI agent — to remember to report works until it does not. The new CLI wraps whatever you already run and reports from the process itself.

curl -fsSL https://raw.githubusercontent.com/\
  tp322d/lastping-app/main/install.sh | sh

lastping run --monitor <id> -- python nightly_etl.py
lastping run --monitor <id> -- ./backup.sh

A start ping, then the exit code as success or failure with the tail of stderr attached. Your exit code always propagates, and a ping that cannot be sent never touches your command. No Go toolchain needed — the installer fetches a prebuilt binary for macOS and Linux and verifies its checksum.

Improvement

Connect your agent in one step, and 32 MCP tools

The console used to hand you a server URL and an auth header and leave you to work out the rest. There is now a connect page that asks which client you use — Claude Code, Claude Desktop, Cursor, Windsurf, Codex — and gives you the exact command or config file for it, with the key already filled in.

The MCP server grew from 27 tools to 32: status pages are now manageable from an agent, destinations can be deleted, routing can be read before it is replaced, and get_ping_instructions returns the wrapper and hook setups rather than only the manual protocol.

Fix

blocked alerts now reach you by default

blocked means an agent has stopped mid-task and is waiting on a person — approval, a credential, a decision. It was not in the set of events routed to a new monitor's default destination, so by default nobody was told. It is now, and existing monitors still on their defaults were updated.

Feature

Output assertions and metric guards

A job that runs on time, exits zero and does nothing was a green check. Assertions read the ping body a job already sends and turn a success into a failure when it does not say what it should — a substring, a regular expression, or a JSON path compared against a value. The incident quotes what it got against what it expected.

Metric guards do the same for numbers. Report cost_usd or a token count in the body and alert when the sum, max or average crosses a ceiling over a trailing window. An agent that loops and burns money is no longer a monitor that says everything is fine.

Feature

The agent registry, on-demand monitors, and blocked

Register an agent and every monitor it owns rolls up into one live state, worst first: down, blocked, late, running, up, pending, idle. The one that matters most is blocked — a run that stopped to ask you something and is still waiting.

Agent work does not run on a schedule, so on_demand monitors do no absence detection between runs; they bound a run once one starts. Run history now covers agent runs too, not only CI, so an agent can ask where its own last run got to. The Terraform provider gained a lastping_agent resource to match.

Feature

Stall detection — catch a run that stops making progress

A long job that hangs has always been caught by overrun detection — but only once its whole run budget expires, and the alert could not say where it wedged. Runs can now report progress, and a run that stops reporting opens a stalled incident that names the last step it reached.

RID=$(uuidgen)
curl -fsS "$URL/start?rid=$RID"
curl -fsS "$URL/step?rid=$RID&step=dump"
curl -fsS "$URL/step?rid=$RID&step=upload"
curl -fsS "$URL?rid=$RID"

Set step_timeout_s on the monitor to the longest gap you expect between steps. Exceed it and an incident opens immediately — "hung at upload, no step in 12m" — instead of at the end of the run budget. The monitor detail page shows each recent run's timeline with the gap between steps, and the new {last_step}, {step_count} and {run_duration} template variables put the same context in your own alert copy.

This is opt-in. A monitor that sets no step_timeout_s behaves exactly as it did before — nothing changes for jobs you do not instrument. A step never extends the run budget either: a job that reports progress forever still overruns.

Available on the REST API, the dashboard, and the MCP server — create_monitor and update_monitor take step_timeout_s, get_ping_instructions hands an agent a ready-to-run curl_step snippet, and get_run_history returns each run's steps.

Milestone

Terraform provider — monitoring as code

The LastPing Terraform provider is live on the public Terraform Registry as lastping-dev/lastping v0.1.0. Monitors, destinations, alert routing, alert messages, status pages and API keys are all manageable as code — reviewed in a pull request, applied by your pipeline, and diffable like the rest of your infrastructure.

terraform {
  required_providers {
    lastping = {
      source  = "lastping-dev/lastping"
      version = "~> 0.1"
    }
  }
}

There is also an ephemeral API-key resource. It mints a short-lived key for a single run and revokes it when the run ends, so no long-lived credential is ever written into Terraform state.

Already have monitors? Export as Terraform on the monitors list emits HCL for what you have — complete with import blocks, so adopting Terraform adopts your existing monitors rather than recreating them.

Feature

Monitor tags, CI run history, and a docs hub

Monitors can now carry tags, so a fleet that grew one job at a time can be grouped by service, team, or environment — in the console, over the API, and from an agent.

CI monitors keep a run history: the recent runs behind a monitor, each with its failing step, actor, commit, and a deep link to the provider's run page. Agents can read the same history through the get_run_history tool. A log excerpt is attached too, when you've added the optional if: failure() step to your own workflow — the run tracking itself needs no YAML change.

The documentation is now a hub rather than a single page, with setup guides per signal source and a section on the MCP server.

Feature

Dashboard improvements

First-run onboarding now shows a live listening for your first heartbeat card, so you can watch a new monitor come alive instead of guessing whether the ping landed. The monitors list gained one-click pause, resume, and delete, and relative timestamps tick live rather than going stale between refreshes.

Feature

Remote MCP server at mcp.lastping.dev

The MCP server is now hosted at mcp.lastping.dev over Streamable HTTP with bearer auth. Point an agent at the URL with an API key and it connects — nothing to install, no local process to keep running.

The endpoint is advertised in the discovery document and on the agents page, so an agent can find it without being told where to look.

Release

Agent-first — the MCP server and runaway detection

LastPing now ships an MCP server, lastping-mcp, that lets an AI agent create and manage monitors directly. The flagship tool is get_ping_instructions: an agent can instrument its own dead-man's-switch mid-conversation, without a human stopping to wire up monitoring first.

API errors are written for that reader too. Each one carries a machine-readable code and a fix hint, so an agent can correct a bad request instead of retrying it verbatim. A GET /.well-known/lastping.json discovery endpoint describes the service to whoever asks.

Runaway detection landed alongside it: a per-monitor ceiling that opens an incident when a job or an agent loops far more often than expected. Silence was already covered — this covers the opposite failure. More on the agents page.

Milestone

Project published on GitHub

The LastPing project repository is now live at github.com/tp322d/lastping-app. The CLI and the MCP server live there, and issues can be filed against them.

There is no open-core split. The hosted service at app.lastping.dev is free for individuals. Follow the project on the project page.

Feature

CI/CD signal sources

GitHub Actions, GitLab CI, and Jenkins can now send signed webhook events to LastPing — no YAML polling loop needed. Each event carries the pipeline run URL, so incidents deep-link directly to the failing build.

Signatures are verified with HMAC-SHA256 on the ingest service. A new ci monitor type tracks run outcomes (success / failure / timeout) and fires incidents on first miss.

Feature

Active HTTP monitoring

A new http monitor type lets you probe any URL on a configurable schedule. LastPing checks status code, response time, and optional keyword presence — SSRF-guarded to private address ranges.

Response-time charts are available in the console. Alerting follows the same incident model as heartbeat monitors: an incident opens on first failure and closes on recovery.

Redesign

The Slate redesign — console & new screens

The app console is now a dark observability console built on the Slate design system: command palette (⌘K), expandable sidebar, and a toast notification stack. The palette is amber-free — slate backgrounds, teal accents, semantic status colours.

Two new screens shipped with the redesign: an Incidents screen for managing open and resolved incidents in one place, and an Analytics screen with monitor health over time.

Feature

Alerting configuration — routing matrix & custom templates

Alert routing is now configured via a matrix: each row pairs a destination channel (email, Slack, Discord, Telegram, webhook) with one or more event types (incident opened, resolved, late). You can attach multiple channels to a monitor and route different events to different destinations in one view.

Custom message templates let you write per-event alert copy — runbook links, ownership context, whatever your on-call team needs. Templates use a safe, defensive rendering engine and fall back to defaults on any error.

2025

Launch

Initial release

LastPing launches with heartbeat / dead-man's-switch monitoring: send a ping after a job succeeds; LastPing alerts you if the ping stops arriving within the expected window.

Also in the initial release: alert channels (email, Slack, Discord, Telegram), public status pages per project, and a hosted service at app.lastping.dev with no paid tier.

FREE FOR INDIVIDUALS · FULLY HOSTED

Try everything that shipped.

The hosted service is free for individuals. No credit card required. Sign up and start monitoring in minutes.