Garbage in, sanity out.
Pintxøs grabs an RSS feed and republishes its articles as a new feed with neutral headlines and factual, ≤100-word summaries. No more clickbait or ragebait. Just plain facts.
Article titles around the web are increasingly written just to be clicked, not read. Some egregious examples:
- "Popular Open-World Franchise Quietly Confirms Huge Upgrade After Years of Waiting". Which franchise? What is the upgrade?
- "Major Premier League Star Subject to ‘Unbelievable’ Bid as Huge Transfer Formally Agreed". Who? Which teams?
- "Netflix's Renewed Sci-Fi Thriller With Perfect Rotten Tomatoes Score Officially Hits A Filming Milestone". Which show? What milestone?
Argh! 🤯
Pintxøs takes the original RSS feed, ingests the title and contents, and spits out a new RSS feed with a plain, useful title, a max. 100-word summary, and a link to the original post.
Example:
- Original headline: "Netflix's Renewed Sci-Fi Thriller With Perfect Rotten Tomatoes Score Officially Hits A Filming Milestone"
- Pintxøs' rewritten headline: "Netflix's Supacell completes season 2 filming"
Same story, no guessing games. Sanity restored. Point Pintxøs at a feed once, and every new item gets the same treatment automatically.
- OPML import and export. Load a feed list from any reader in one go, and download your list back out, either the original source feeds or the Pintxøs output feeds. An import of more than five feeds waits for your go-ahead on the Feeds page, which says how many summaries it may cost; starting the polls does five feeds right away, then one every two minutes.
- Model choice. Use Anthropic's Haiku directly, any model on OpenRouter, or a model on your own machine. Each feed can use a different model, to balance quality and cost.
- Model search. Type in the Model field (Settings, "Fallback model" there too, and each feed's Model tab) and pick from a dropdown over OpenRouter's model list instead of copying names.
- Local models. Run a
local:model on Ollama, llama.cpp, vLLM or LM Studio with no API key; see Local models. - Stats page. A 7-day dashboard of what Pintxøs read, filtered and saved, including a topic count for the week.
- Ad filtering. Skip deal posts, coupons and sponsored entries before they reach your feed. Built-in rules cover the usual "60% off" and promo-code posts. Each feed's Filtered tab shows what the last poll dropped and why.
- Keyword filtering. Block or keep entries by title, globally or per feed, e.g. drop everything mentioning
cricketorhoroscope. Supports regular expressions. - Full text inline. The whole article is appended below the summary, so you can read it in your feed reader without opening the site.
- English summaries of foreign-language feeds. By default headlines and summaries stay in the article's language. Turn that off, globally or per feed, to always get English.
- Paywalled sites. Paste your browser's cookies for sites you subscribe to and Pintxøs reads the full article instead of the teaser. Each feed shows whether the login worked.
- Word count and reading time on every item, so you know what you are clicking into.
- Topic mute. Tick any of 17 media categories (arts, sport, health, weather, ...) to mute them entirely.
- Volume warning and daily budget. A feed that produces an unusually high number of summaries gets a warning article in its output feed, once per day. Set a per-feed daily limit if you want a hard cap.
- Bypass feed cache. Some publishers' CDNs keep serving a stale feed: the London Review of Books caches its RSS for 14 days but publishes fortnightly, so new issues arrive late or not at all. Switch this on from the Feed fetch tab on the feed's page and each poll adds
_pintxos=<unix time>to the feed URL, keeping any query parameters it already has. Off by default; article fetches are unaffected. - Copy and share. Every feed item links to a page with one-tap Copy (rich text: bold headline, italic stats, small model name; plain text for iMessage/WhatsApp) and Share buttons, so you can pass an article on from a mobile feed reader.
- Add your favorite feeds to Pintxøs.
- Grab its output URL and read it in your RSS reader of choice.
- Done.
services:
pintxos:
image: ghcr.io/janw76/pintxos:latest
container_name: pintxos
ports:
- "8000:8000"
volumes:
- ./data:/data
environment:
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} # for models without a slash (Anthropic direct)
# PINTXOS_MODEL: z-ai/glm-5.3-flash
# PINTXOS_POLL_MINUTES: 30
# PINTXOS_ITEMS_PER_FEED: 50
# PINTXOS_BASE_URL: https://pintxos.example.com
restart: unless-stoppedPut the API key for your model's provider in a .env file next to
docker-compose.yml (see .env.example). The default model
z-ai/glm-5.3-flash runs on OpenRouter, so set OPENROUTER_API_KEY. To use
Anthropic directly instead, set ANTHROPIC_API_KEY and
PINTXOS_MODEL=claude-haiku-5-5 (no OpenRouter key needed). Setting
both keys is fine; local: models need no key (see API keys).
Then:
docker compose up -dOpen http://localhost:8000, add a feed URL, and copy the generated output
feed URL into your RSS reader of choice. My favorite is NetNewsWire.
The box above the table filters your feeds by title or URL as you type, and the Add
button activates once you paste in a feed URL.
If you run Tailscale, I recommend exposing Pintxøs as a service, which gives you a proper HTTPS URL that any RSS client in your Tailnet can reach.
Pintxøs is a single Python process with a SQLite file, so it runs fine without a container. You'll need Python 3.12 or newer.
Install it with uv:
uv tool install git+https://github.com/janw76/pintxos
pintxosOr run it without installing anything permanently:
uvx --from git+https://github.com/janw76/pintxos pintxosOr install it with pip:
python3 -m venv .venv && .venv/bin/pip install -e .
# or, without cloning the repo first:
python3 -m venv .venv && .venv/bin/pip install git+https://github.com/janw76/pintxosThen run it:
.venv/bin/pintxos
# or: .venv/bin/python -m pintxosCopy .env.example to .env in the directory you run pintxos from, and
fill in the key for your model's provider (OPENROUTER_API_KEY for the default
model, or ANTHROPIC_API_KEY with PINTXOS_MODEL=claude-haiku-5-5;
see API keys) plus any other overrides, or export the
variables directly — real environment variables always win over .env. The
SQLite database lives in ./data relative to that directory unless you set
PINTXOS_DATA_DIR, so run pintxos from a stable directory.
By default the server binds to 127.0.0.1:8000, i.e. only this machine can
reach it. To reach it from other machines — for example your RSS reader on a
phone, over Tailscale — set PINTXOS_HOST=0.0.0.0 or to your Tailscale IP,
or pass --host/--port on the command line. Before doing so, read the
Security warning section below.
To keep it running as a background service (systemd on Linux, launchd on macOS), see docs/deploy-native.md.
The model, fallback model, local server URL, API keys, poll interval, items per
feed, volume-warning thresholds, full text, language and ad-filter settings can be
set via environment variables, or (if unset) via the Settings page in the web UI,
which persists them to the database. PINTXOS_BASE_URL, PINTXOS_DATA_DIR,
PINTXOS_HOST, PINTXOS_PORT and PINTXOS_IMPERSONATE are environment-only;
PINTXOS_KEEP_PER_FEED, PINTXOS_DAILY_BUDGET, PINTXOS_LOCAL_LLM_KEY and
PINTXOS_LOCAL_LLM_TIMEOUT have no Settings field (the daily budget can also be
set per feed).
| Env var | Default | Meaning |
|---|---|---|
ANTHROPIC_API_KEY |
(none) | Anthropic API key. Set it to use a model without a slash in the name (Anthropic direct), e.g. claude-haiku-5-5. Not needed for OpenRouter or local: models. See "API keys". |
OPENROUTER_API_KEY |
(none) | OpenRouter API key. Set it to use the default model or any model with a slash in the name. Not needed if you only use Anthropic-direct or local: models. See "API keys". |
PINTXOS_LOCAL_LLM_URL |
http://127.0.0.1:11434/v1 |
Base URL of an OpenAI-compatible server (Ollama, llama.cpp, vLLM, LM Studio) used by models named local:<model>. See "Local models". |
PINTXOS_LOCAL_LLM_KEY |
(none) | Optional bearer token for that server. Most local servers need none. |
PINTXOS_LOCAL_LLM_TIMEOUT |
300 |
Seconds to wait for a local model's reply; CPU inference is slow. Connecting is capped at 10 s, so an unreachable server fails fast. Invalid values fall back to 300. No UI field. |
PINTXOS_MODEL |
z-ai/glm-5.3-flash |
Default model. Names with a slash go to OpenRouter, names without go to Anthropic, names starting with local: go to your own OpenAI-compatible server (see "Local models"). Feeds can override it. |
PINTXOS_FALLBACK_MODEL |
deepseek/deepseek-v4-flash |
Sent to OpenRouter as the fallback when the primary model fails. Only applies to OpenRouter models: Anthropic-direct and local: models get no fallback. Also on the Settings page ("Fallback model"). |
PINTXOS_POLL_MINUTES |
30 |
How often feeds are polled, in minutes. |
PINTXOS_ITEMS_PER_FEED |
50 |
Items in each output feed, and the most feed entries considered per poll. |
PINTXOS_KEEP_PER_FEED |
1000 |
Rows stored per feed; the oldest-inserted are pruned first. Keeps history well beyond the output feed so an entry that leaves and re-enters a publisher's feed is never summarized again. Roughly 5 KB per row with full text. -1 keeps every row forever (no pruning); the database then grows without bound. No UI field. |
PINTXOS_DAILY_BUDGET |
200 |
Default "Max summaries per day" for feeds whose own budget is blank. A per-feed value always wins; set it very high to effectively remove the cap. |
PINTXOS_WARN_AT |
100 |
Summaries per feed per day after which the output feed carries a warning item. Per-feed "Volume warning" turns the warning off for that feed. |
PINTXOS_WARN_HARD_AT |
180 |
From this many summaries the warning uses stronger wording. Must be at least PINTXOS_WARN_AT. |
PINTXOS_FILTER_ADS |
0 |
Skip ad/coupon entries before fetch/summarize. Set to 1 to turn this on. |
PINTXOS_FULL_TEXT |
1 |
Append the extracted article text after each summary in the output feed, below the Original line. Set to 0 to turn this off. |
PINTXOS_RESPECT_LANGUAGE |
1 |
Write headline and summary in the article's language. Set to 0 to always summarize in English. Appended full text is never translated. Each feed can override this on its Language tab. |
PINTXOS_AD_TITLE_PATTERNS |
(empty) | Extra title regexes, one per line, matched case-insensitively, in addition to the built-in ad rules. |
PINTXOS_AD_KEEP_PATTERNS |
(empty) | Title regexes, one per line, matched case-insensitively; a match overrides every block rule, built-ins included, and the entry is kept. |
PINTXOS_BASE_URL |
(none, inferred from the request) | Base URL used to build output feed links, e.g. https://pintxos.example.com. |
PINTXOS_DATA_DIR |
./data |
Directory for the SQLite database and cookies.txt. |
PINTXOS_HOST |
127.0.0.1 |
Host/interface the server binds to. The Docker image sets PINTXOS_HOST=0.0.0.0. |
PINTXOS_PORT |
8000 |
Port the server binds to. |
PINTXOS_IMPERSONATE |
safari17_0 |
curl_cffi browser TLS/HTTP fingerprint used for all fetches, so Cloudflare-fronted sites accept the request. Set empty to disable impersonation (uses the Pintxøs User-Agent instead). A comma-separated list is tried in turn when Cloudflare challenges a request, e.g. safari17_0,safari17_2_ios. |
PINTXOS_NO_SCHEDULER |
(unset) | Set to 1 to disable polling entirely, periodic and manual (Poll now queues forever). For tests and CI only. For a local run without periodic polls, set PINTXOS_POLL_MINUTES=1440 instead. |
The ad filter toggle and extra patterns can also be changed on the Settings page unless the corresponding environment variable is set.
If a feed only carries a short teaser and the article itself is behind a paywall, Pintxøs cannot read the full text. For sites you subscribe to, you can give Pintxøs your own login: log in to the site in your browser, then hand Pintxøs the login cookie. Each site's cookie is only ever sent back to that same site.
- Install the free, open-source Cookie-Editor browser extension (Safari, Chrome, Firefox).
- Open the website you want full articles from and log in.
- Click the Cookie-Editor icon, choose Export, then Netscape. The cookies are now on your clipboard.
- Open the feed from the Feeds page, go to its Paywall tab, paste the cookies and click Save. Only that site's login is replaced; clear the box and save to remove it. Repeat for each site.
The Paywall section on the Settings page is an overview: the sites with a
saved login and the feeds that currently have a paywall, each linking to
its Paywall tab. It also takes a whole cookies.txt file for all sites at
once (replacing every saved login), or you can copy the file to
<PINTXOS_DATA_DIR>/cookies.txt by hand.
Pintxøs uses the new cookies on the next poll. On a feed's Status tab, "Retry N items" re-reads articles that could not be read in full (teasers, blocked pages, failed fetches) and summarizes items that have no summary. When the Feeds page shows "unreadable with login", it means either your cookies expired or those articles are outside your subscription; cookies only need re-exporting in the first case.
Short pages that declare themselves free (schema.org isAccessibleForFree)
or are video/audio pages are summarized as they are and never reported as
paywalled.
Fetches impersonate a real browser (PINTXOS_IMPERSONATE, default
safari17_0), because these sites reject plain HTTP clients before ever
looking at a cookie. A challenged request is retried on the next
profile in the list, requests to one site are spaced two seconds
apart, and each scheduled poll re-fetches up to three items that were
blocked earlier (until the feed's daily budget is reached).
The ad filter is off by default; turn it on with PINTXOS_FILTER_ADS=1 or the
checkbox on the Settings page. When enabled, it skips entries that look like
ads or coupon posts before fetching or summarizing them, so they cost
nothing and never reach the output feed — detected by RSS category (e.g.
Wired's "Gear / Deals" tag), title shape ("Groupon Promo Codes: 60% Off in
September 2026"), or a URL slug ending in -promo-code/-coupons. The
built-in rules also cover Tom's Guide style sale posts ("Labor Day sale",
"save up to 50%", "44% off"). You can
add your own regexes, one per line, via PINTXOS_AD_TITLE_PATTERNS or the
same Settings textarea. Titles matching PINTXOS_AD_KEEP_PATTERNS (also one
regex per line, editable on the Settings page) are never filtered, overriding
every block rule including the built-ins. Built-in keep rules already rescue
obvious news headlines (stock sale, for sale, lawsuits, fraud) from the block
rules above; PINTXOS_AD_KEEP_PATTERNS adds to them. The filter only applies to entries
seen after it is turned on — it never touches items already stored. The Feeds page shows "N
filtered" under a feed's item count for its last poll. Each feed can also
override the global switch and choose whether it inherits, extends, or
ignores the global patterns from its Ad filter tab. The feed's page also
lets you override its title; leave the field blank to fall back to the
feed's own title.
Example patterns, one per line:
black friday
\bgiveaway\b
^sponsored:
The filter was contributed by Eric Bowman (@ebowman) — see pintxos#2.
The ad filter is free and catches deal posts; topic mute is for muting whole subjects (sport, weather, arts, ...) that you never want in your feed, at the cost of one small AI call per new item. It's off by default, per feed: set the feed's Topic mute tab to On and each new item is classified into one of the 17 IPTC Media Topics top-level topics, then matched against the topics you've ticked to mute.
- Tick any of the 17 topics to mute it; a muted item is dropped before summarizing, so it costs nothing and never reaches the output feed.
- Each topic shows a running percentage — the share of classified items so far that fell into it — shown once at least one item fell into that topic.
- Keyword title patterns (above) are free and run first; reach for topic mute only for what they can't catch.
- The feed's Filtered tab ("Filtered at last poll") shows every item dropped by either mechanism and why. Ad-filtered and muted-topic rows carry a Summarize button to release that one item into the output feed anyway.
IPTC Media Topics vocabulary © IPTC (https://iptc.org/), used under CC BY 4.0. Icons from Lucide (https://lucide.dev/), used under the ISC license.
A feed that starts producing an unusual number of summaries in a day is
worth a second look — it may be an oversized feed, a misconfigured URL, or
just a very busy news day. Once a feed reaches PINTXOS_WARN_AT summaries
on a given day (default 100), Pintxøs prepends a warning article to that
feed's output — a stronger one at PINTXOS_WARN_HARD_AT (default 180) —
that explains what happened and links to the feed's page, where the setting lives on the Volume tab.
Both thresholds can be changed on the Settings page unless the
corresponding environment variable is set. Each level fires once per day;
the warning never touches the feed's own items.
- The warning is per feed, On by default; flip it Off on the "Volume" tab of the feed's page if you'd rather not see it.
- "Max summaries per day" sets a hard budget for the feed; blank falls back
to the default
PINTXOS_DAILY_BUDGET(200), not unlimited — set it very high on a feed if you want to effectively remove its cap. Once the budget is reached, further entries are skipped before any fetch or summary call, so they cost nothing. - Skipped entries show up in the feed's Filtered tab like any other filtered item, with a Summarize button to release one anyway.
- The feed's Status tab always shows "Summaries: N paid today, K new items kept, M total". Paid vs. kept tells you whether summaries are being paid for and then discarded; the warning article itself states both numbers and calls out a likely re-summarize loop when fewer than half were kept.
Pintxøs has no authentication. Anyone who can reach the web UI can add,
delete, or repoll feeds, and anyone who can reach an output feed URL can read
it — this is by design, so RSS readers can fetch feeds without credentials.
Only run Pintxøs on localhost, over Tailscale/a VPN, or behind a reverse
proxy that handles authentication for you. Do not expose it directly to the
public internet. If you use the paywalled-feeds feature above, the cookies
file is equivalent to being logged in to those sites and is stored
unencrypted in the data directory, so keep it on a private machine and
remove it once you stop using it (a site's login on the feed's Paywall tab,
all of them with "Remove all saved logins" on Settings); it's meant for reading with
your own account, so check the publisher's terms.
There are two API keys: ANTHROPIC_API_KEY and OPENROUTER_API_KEY. Set the
key for your model's provider:
- a model name with a slash (the default
z-ai/glm-5.3-flashis one) goes to OpenRouter and needsOPENROUTER_API_KEY; - a model name without a slash (e.g.
claude-haiku-5-5) goes to Anthropic and needsANTHROPIC_API_KEY; - a
local:model needs no key (see Local models).
You need only the key for the provider you use; setting both is fine. For an
Anthropic-only setup, set ANTHROPIC_API_KEY and
PINTXOS_MODEL=claude-haiku-5-5. With only OPENROUTER_API_KEY set,
a claude-* model fails, and with only ANTHROPIC_API_KEY set the default
model fails until you change it. See
Choosing a model below. For both keys, the primary way to
configure them is the environment variable (shown in the Quickstart above);
if — and only if — the environment variable is not set, the Settings page
lets you store that key in the database instead.
- Pintxøs normally makes one summary call per new article: items are stored
(up to
PINTXOS_KEEP_PER_FEEDper feed) and a stored, summarized item is not summarized again. The exception is a blocked article (the site answered with HTTP 401, 403 or 429): it is summarized from the feed's excerpt, or its title when there is no usable excerpt, and if you have set up cookies for the article's site it is re-read and summarized again when the fetch later gets through (see "Paywalled feeds"). - If a summary call fails — unparsable model output, a transport error — the item is kept without a summary and retried automatically on later polls. An item held without a summary gets at most three automatic tries; the wait grows between tries (it doubles; at the default 30 minute poll interval the three tries span at least 90 minutes). A try stopped by an account error (no credit, bad key) is not counted as one of the three. Successful calls count against the daily budget and the feed's stats; of the failed tries only those where the provider actually answered (such as unusable JSON) count, a transport failure does not. Once the three tries are used up, the item shows its original title with a note and is not retried by the automatic retries. The one exception: if its article was blocked and your cookies later let the fetch through, it is re-read and summarized once, within the daily budget (the cookie re-read stops for the day once the feed's daily budget is reached). The "Retry N items" button on the feed's Status tab re-summarizes it, one call per item.
- The database grows to about 5 MB per feed at the default retention.
Pintxøs never runs
VACUUM, so deleting a feed shrinks the file only after runningsqlite3 pintxos.db 'VACUUM'by hand. - Feeds with Topic mute set to On add one more small call per new item — the topic classification call is roughly 15% of the cost of a summary call, and only runs on feeds with the switch on. As a rule of thumb, topic mute pays for itself once the muted topics make up more than about 15% of a feed's items (the feed's Topic mute tab shows the share of items in each topic).
- A per-feed "Max summaries per day" budget caps the number of summary calls that feed can make in a day, regardless of how much it polls.
- Pintxøs avoids re-polling and re-summarizing, but I still recommend watching cost — on Claude Console for Anthropic models, and on OpenRouter's activity page for models with a slash. Cost scales with the number of feeds you poll and how many articles they publish.
A model name with a slash (e.g. google/gemini-2.5-flash-lite) is sent to OpenRouter using OPENROUTER_API_KEY; a name without a slash (e.g. claude-haiku-5-5) is sent to Anthropic using ANTHROPIC_API_KEY. Both providers bill per token through API keys — a ChatGPT or Claude chat subscription cannot be used.
| Model | Approx. cost per 100 articles | Notes |
|---|---|---|
z-ai/glm-5.3-flash |
~$0.02 | Default. Via OpenRouter; fast, large context, good summaries. |
claude-haiku-5-5 |
~$0.04 | Anthropic direct. Strongest multilingual output. |
deepseek/deepseek-v4.1-flash |
~$0.01 | Cheapest of the set. Large context, solid summaries. |
google/gemini-2.5-flash-lite |
~$0.04 | Fast, reliable JSON, good in European languages. |
deepseek/deepseek-v4-flash-0731 |
~$0.04 | Older DeepSeek flash snapshot. Large context, solid summaries. |
Prices are from OpenRouter and Anthropic as of October 2026, assuming about 2,500 input and 300 output tokens per article, and drift; see the full list at openrouter.ai/models. The same five presets are clickable on the Settings page.
Each feed can override the model on its Model tab — e.g., a premium model for one feed, the cheapest for another; leaving it blank uses the global default.
Save the model on the Settings page first, then click "Test saved model" to run a tiny completion with it and the saved key.
Any OpenAI-compatible server works, with no API key. With Ollama: ollama pull <model>, then set the model to local:<model> (e.g. local:glm4:9b).
The local: prefix is stripped before the name is sent to the server, and it wins over the slash rule, so names like local:hf.co/org/model work.
The server address is PINTXOS_LOCAL_LLM_URL (Settings page: "Local LLM URL"); the fallback model is not used for local: models.
In Docker, 127.0.0.1 is the container itself: use http://host.docker.internal:11434/v1 instead.
On Docker Desktop and Colima (macOS, Windows) this works out of the box: host.docker.internal reaches the host's loopback, so a default Ollama needs no changes.
On native Linux Docker, add extra_hosts: ["host.docker.internal:host-gateway"] (or --add-host) and start Ollama with OLLAMA_HOST=0.0.0.0, because host-gateway is the docker0 bridge IP, not loopback.
OLLAMA_HOST=0.0.0.0 exposes Ollama on all interfaces: firewall port 11434, or bind to the docker0 IP (e.g. OLLAMA_HOST=172.17.0.1) instead.
The same setup runs on Linux and macOS; expect slow replies on CPU-only machines.
Long articles make prompts of up to ~7.6k tokens, but Ollama's default context depends on the machine (4k/32k/256k based on VRAM, per ollama serve --help), so set OLLAMA_CONTEXT_LENGTH=16384 or more.
Current Ollama rejects a prompt that doesn't fit with an error, logged and recorded as the item's summarize error; older versions and some other servers may cut it silently instead, so pintxos logs a warning when the server reports far fewer prompt tokens than it sent.
If the local server is unreachable, an item is tried three times over at least 90 minutes at the default 30 minute poll interval (the wait doubles per attempt).
After that the item appears in the feed with its original title and a note that no summary could be made, and it is not retried automatically. Once the server is back, the "Retry N items" button on the feed's Status tab re-summarizes them.
python -m venv .venv && .venv/bin/pip install -e .[dev]
.venv/bin/pytest
.venv/bin/pintxos # or: python -m pintxos
docker build -t pintxos .Versions look like 26.09.1: year, month, and a number that starts at 1 and
increments with each release in that month, resetting to 1 next month. For
example 26.09.1, 26.09.2, then 26.10.1. Each release is tagged in git
as vYY.MM.N; the app displays the version without the leading v.
Pintxøs doesn't use semantic versioning — it's an app, not a library, so
API-compatibility semantics wouldn't mean anything here.
Every merge to main is a release. CI runs the tests, works out the next
number for the current month from the existing tags, builds and pushes the
Docker image as ghcr.io/janw76/pintxos:<version> and :latest, tags the
commit v<version>, and creates a GitHub Release. The release notes are
generated by GitHub from the merged pull requests' titles and bodies since
the previous tag, plus a collapsed list of commits.
The running app shows its version in the footer of the Settings page. The
image build bakes it in as the PINTXOS_VERSION environment variable; when
that variable is absent, for example in a source checkout, the footer shows
"dev" instead.
/health also reports the running version, which the deploy script uses.
To pin a deployment to a specific version instead of always tracking
:latest, use an image tag like ghcr.io/janw76/pintxos:26.09.1 in your
docker-compose.yml.
See also docs/prior-art.md for a full survey. Many of these do amazing things, but I wanted something simple that does the one or two things I need very well, and nothing else.
MIT — see LICENSE.
