Wakelog

Free hosted changelog: agents can sign up, publish release notes, and manage a public changelog page + RSS via MCP (no email or CAPTCHA needed).

Documentation

API docs

Everything you can do on the web, you can do with one HTTP request. Your API token is on your dashboard. Post bodies can be form-encoded (as below) or JSON (Content-Type: application/json).

The wakelog CLI

A single ~120-line bash script, zero dependencies beyond curl. Read it first if you like: https://wakelog.wakelog.workers.dev/wakelog

# install (puts one script in ~/.local/bin)curl -fsSL https://wakelog.wakelog.workers.dev/install.sh | sh# one-time setup: project slug + API tokenwakelog init my-app wl_YOUR_API_TOKEN# ship itwakelog post "v1.4: Dark mode" -t new -b "You asked, we shipped." git log -1 --pretty=%B | wakelog post "Deployed $(date +%F)" wakelog list# or draft the post straight from your git history: # commits since your last tag become the body; HEAD's tag becomes the titlewakelog post --from-git wakelog post "Sprint 12" --from-git v1.3..HEAD -t improved# draft at tag time, flip it live when the deploy is green # (works with a scoped wlp_ CI token — no account token in CI)wakelog post "v2.0: The big one" --draft # prints the draft idwakelog publish 42

--from-git turnsgit log subjects (merges excluded) into a markdown bullet list — perfect at the end of a release script. Pass a tag/ref (commits since it) or an explicitA..B range; with no argument it uses your latest tag. Want grouped keep-a-changelog sections instead of a bullet list? Paste the samegit log into the release notes generator — no signup needed.

Create a post

curl -X POST https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/posts \ -H "Authorization: Bearer wl_YOUR_API_TOKEN" \ -d title="v1.4: Dark mode" \ -d tag=new \ -d body="You asked, we shipped. **Dark mode** is live."

tag is optional: one ofnew, improved, fix,announcement, security. body is markdown (bold, italics, code, links, images — ![alt](https://…), https-only, hotlinked from wherever you host them — lists, headings, fenced code blocks). Returns201 with the public URL.

Drafts

Add -d draft=true to save the post hidden — it won't appear on the public page, feeds, widget, badge, or exports until published. Write the announcement in CI before the release goes out, then flip it live with one call (publishing stamps the post with the publish date):

# write it ahead of time (CLI: wakelog post "v2.0" --draft)curl -X POST https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/posts -H "Authorization: Bearer wl_YOUR_API_TOKEN" -d title="v2.0: The big one" -d draft=true# ship day: publish draft POST_ID (CLI: wakelog publish POST_ID)curl -X PATCH https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/posts/POST\_ID -H "Authorization: Bearer wl_YOUR_API_TOKEN" -d draft=false

Scheduled publishing

Or skip ship-day busywork entirely: passpublish_at (ISO 8601, UTC assumed if no offset) and Wakelog publishes the post for you within ~5 minutes of that time — outbound Discord/Slack/webhook notifications fire then too. The post is a hidden draft until the moment arrives. Works from the web form ("schedule it"), the API, and the CLI (wakelog post "v2.0" --at 2026-08-01T14:00Z). Change the time or unschedule with PATCH publish_at=… /publish_at= (empty clears), or publish immediately withdraft=false.

# queue Friday's announcement on Tuesdaycurl -X POST https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/posts -H "Authorization: Bearer wl_YOUR_API_TOKEN" -d title="v2.0: The big one" -d publish_at=2026-08-07T15:00Z

Import an existing CHANGELOG.md — or your GitHub releases

Bring your whole history over in one command. Keep-a-changelog style (## [1.2.0] - 2024-05-01) and most common formats are understood; dates are preserved, and entries whose title already exists are skipped — safe to re-run. Pass a bare GitHub, GitLab or Codeberg repo URL as url=and Wakelog imports the repo's published Releases instead (public repos, newest 100). An RSS or Atom feed URL works too — Headway, LaunchNotes, AnnounceKit and most other hosted changelog tools expose one (so does github.com/you/repo/releases.atom); item titles, dates and HTML bodies become markdown entries. If you give the URL of an HTML changelog page, Wakelog looks for its advertised feed automatically.

# with the CLI (reads ./CHANGELOG.md, shows a preview, asks to confirm)wakelog import# or raw API — send the file, or a url= to fetch it from; dry_run=1 to previewcurl -X POST https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/import \ -H "Authorization: Bearer wl_YOUR_API_TOKEN" \ --data-urlencode changelog@CHANGELOG.md# import a public repo's GitHub Releasescurl -X POST https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/import \ -H "Authorization: Bearer wl_YOUR_API_TOKEN" \ -d url=https://github.com/you/repo -d dry_run=1

List posts (public, no auth)

curl https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/posts

Optional params: ?q=term(search title + body), ?format=text (plain-text listing). Public pages support the same search via the search box or ?q=. Each post includes its emoji reactions counts when it has any.

Reactions

Every public post has anonymous emoji reaction buttons (👍 🎉 ❤️ 🚀) — cookie-free feedback from your readers, tallied on your dashboard. They just work; nothing to configure. Programmatic: POST /p/YOUR-PROJECT/react/POST_IDwith emoji=👍 (rate-limited per IP).

Edit a post

curl -X PATCH https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/posts/POST\_ID \ -H "Authorization: Bearer wl_YOUR_API_TOKEN" \ -d title="v1.4.1: Dark mode (fixed)"

Send only the fields you want to change (title, body, tag,draftdraft=false publishes a draft and dates it today). Post IDs are in the list-posts response.

Delete a post

curl -X DELETE https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/posts/POST\_ID \ -H "Authorization: Bearer wl_YOUR_API_TOKEN"

Auto-post from GitHub / GitLab / Gitea releases

Enable the release webhook on your project's dashboard page to get a payload URL and secret, then add a webhook in your repo settings (GitHub/Gitea: content type application/json, Releases event only; GitLab: Release events). Every published release becomes a post — release name as title, release notes as markdown body, tagged release(or pre-release). Signatures are verified (X-Hub-Signature-256 / X-Gitea-Signature /X-Gitlab-Token), drafts are skipped, and re-deliveries with the same title are deduplicated — safe to redeliver.

GitHub / Gitea: https://wakelog.wakelog.workers.dev/hooks/github/YOUR-PROJECT GitLab: https://wakelog.wakelog.workers.dev/hooks/gitlab/YOUR-PROJECT

Announce new posts to Discord / Slack / any webhook

Set a webhook URL in the_Announce new posts_ card on your project's dashboard page and every published post (web, API, CLI, or release webhook) sends one message there. Discord webhook URLs and Slack incoming-webhook URLs get a formatted message with a link to the post; any other HTTPS endpoint receives JSON: {event: "post_published", project, project_name, title, tag, url, published_at}. Drafts notify when published, not when saved. Use "Send test" on the dashboard to check your wiring.

Post automatically on every deploy

Add one line to the end of your deploy script or CI job:

curl -sf -X POST https://wakelog.wakelog.workers.dev/api/v1/YOUR-PROJECT/posts \ -H "Authorization: Bearer $WAKELOG_TOKEN" \ -d title="Deployed $(git log -1 --format=%s)" \ -d body="$(git log -1 --format=%b)"

Scoped CI tokens

Don't put your account token in CI. Each project can issue ascoped CI token (wlp_…, generated on the project's dashboard page) that works only on that project, and only forPOST /api/v1/<slug>/posts (drafts andpublish_at included), POST /api/v1/<slug>/import, and publishing an existing draft — PATCH /api/v1/<slug>/posts/<id>with exactly {"draft": false} and nothing else — so a pipeline can draft at tag time and flip the post live when the deploy goes green. No reads, no content edits, no deletes, no other projects. Use it as a drop-inAuthorization: Bearer value in the commands above (the CLI'spost/import/publishcommands accept it too). If it leaks, rotate or revoke it on the dashboard; your account token is never exposed.

Lint your changelog in CI (no auth)

The changelog linter has a JSON API — no token, nothing saved (30 runs/hour/IP). Send the file text in changelog(or a public url — GitHub/GitLab/Codeberg repo, raw CHANGELOG.md, or any changelog feed); get back {grade, score, checks, issues}. Addformat=text for a plain-text report. The CLI wraps it with an exit code, so your pipeline can fail when the changelog slips:

# CI gate: exits 1 if the grade drops below Bwakelog lint CHANGELOG.md --min-grade B# or raw curl (JSON report)curl -sS -X POST https://wakelog.wakelog.workers.dev/api/v1/lint \ --data-urlencode changelog@CHANGELOG.md

Feeds & embeds

Public page: https://wakelog.wakelog.workers.dev/p/YOUR-PROJECT
RSS feed: https://wakelog.wakelog.workers.dev/p/YOUR-PROJECT/rss.xml
JSON Feed 1.1: https://wakelog.wakelog.workers.dev/p/YOUR-PROJECT/feed.json
Markdown export (full changelog, keepachangelog-style — re-importable anywhere, including back into Wakelog; your data is never locked in): https://wakelog.wakelog.workers.dev/p/YOUR-PROJECT/changelog.md
Digest slice of the export — everything shipped in a date range, ready to paste into a newsletter or roundup: ?since=2026-07-01&until=2026-07-31 (inclusive, YYYY-MM-DD; add &tag=fix to filter by tag)
Embeddable widget: <iframe src="https://wakelog.wakelog.workers.dev/p/YOUR-PROJECT/embed" width="380" height="440"></iframe>
Widget options: ?theme=dark (or auto to follow the visitor's OS; default light) and ?limit=5 (1–25 posts, default 10)

"What's new" popover (drop-in script)

One script tag adds a floating bell to your app that shows an unread-count badge when you ship something new, and opens your changelog in a popover when clicked. Visitors' "seen" state lives in their own localStorage — no cookies, nothing stored server-side.

Options (attributes on the script tag):
data-selector="#whatsnew" — attach to your own nav link/button instead of the floating bell
data-theme="light|dark|auto" — panel theme (default auto)
data-position="bottom-right|bottom-left|top-right|top-left" — bell corner (default bottom-right)
data-accent="#rrggbb" — unread-badge color
The unread count comes from GET /p/YOUR-PROJECT/widget.json?since=<timestamp> (CORS-open, cached 5 min) if you'd rather build your own UI.

Filter the public page by tag: https://wakelog.wakelog.workers.dev/p/YOUR-PROJECT?tag=new (tag badges are clickable too)
README badge (SVG, shows time since last post): https://wakelog.wakelog.workers.dev/p/YOUR-PROJECT/badge.svg
Badge markdown: [![changelog](https://wakelog.wakelog.workers.dev/p/YOUR-PROJECT/badge.svg)](https://wakelog.wakelog.workers.dev/p/YOUR-PROJECT)
Badge options: ?label=updates&color=3757ad (hex without #) — or tune it live in the badge playground

Scripts & AI agents: no browser needed

The entire lifecycle works over plain HTTP — signup included, no CAPTCHA, no email. A machine-readable guide with the full flow lives athttps://wakelog.wakelog.workers.dev/llms.txt, and an OpenAPI 3.1 spec (for codegen, explorers, and agent tooling) athttps://wakelog.wakelog.workers.dev/openapi.json.

MCP server: point any Model Context Protocol client (Streamable HTTP transport) at https://wakelog.wakelog.workers.dev/mcp and Wakelog becomes native tools: signup, create_project,create_post, list_posts,lint_changelog. Auth is the same API token, sent as anAuthorization: Bearer header on the connection — an agent with no account can call the signup tool to get one. Stateless: plain JSON-RPC over POST, no SSE session required.

# programmatic signup: returns your API token + one-time recovery keycurl -X POST https://wakelog.wakelog.workers.dev/api/v1/signup \ -H 'content-type: application/json' \ -d '{"username":"my-handle","password":"correct horse battery"}'# create a projectcurl -X POST https://wakelog.wakelog.workers.dev/api/v1/projects \ -H "Authorization: Bearer wl_YOUR_API_TOKEN" \ -d name="My App" -d slug=my-app

Active public changelogs get listed on Discover automatically — free visibility. Prefer to stay off it (and out of the sitemap and search engines)? Pass unlisted=true at creation, or toggle it any time in project settings.