@maschinenlesbar.org/bundesrat-cli
v0.0.4
Published
TypeScript API client and CLI for the Bundesrat's public data feeds — plenary sessions, agenda items, members and vote distribution
Maintainers
Readme
bundesrat-cli
Follow Germany's Bundesrat — the chamber of the sixteen Länder — from your
terminal. bundesrat is a command-line tool over the Bundesrat's public data
feeds (the data behind the official Bundesrat app): the current plenary sitting's
agenda and its Drucksachen, the members, and committee dates — as clean JSON you
can pipe straight into jq.
- The current sitting's agenda — every Tagesordnungspunkt (TOP) with its Drucksache number, in one command.
- The members — all Bundesrat members with party and Land, filterable by
--state/--party. - Open data only — the CLI surfaces just the openly-licensed facts (names, parties, Länder, TOP/Drucksache numbers, dates). The feeds' copyright editorial text and images are deliberately not exposed — see DATA_LICENSE.md.
- No API key — the feeds are public.
- Clean JSON output — pretty by default,
--compactfor scripting,-o <file>to write to disk.
Want to use this as a TypeScript library, or curious how it parses the XML feeds with zero dependencies? See DEVELOPING.md.
Install
npm i -g @maschinenlesbar.org/bundesrat-cliThis installs the bundesrat command. Requires Node.js 20+. No API key.
Check it works:
bundesrat session | jq '.title'Quickstart
# The current plenary sitting: title + agenda items with their Drucksachen
bundesrat session | jq '{title, tops: [.tops[] | {toptitle, topdrucksache, topheader}]}'
# Every member from Bavaria
bundesrat members --state Bayern | jq -r '.[] | "\(.firstname) \(.name) — \(.party)"'
# All Green members across the Länder
bundesrat members --party grüne | jq length
# Committee appointments with their dates
bundesrat appointments | jq -r '.[] | "\(.startdate // "")\t\(.title)"'Commands
| Command | What it shows |
| --- | --- |
| session | Current plenary sitting: title, date and agenda items (TOPs) with their Drucksachen |
| members | Members of the Bundesrat (--state <Land>, --party <text>) |
| appointments | Committee appointments and dates (Termine) |
New to terms like TOP, Drucksache or Land? The Glossary decodes every one.
Why only three commands? The Bundesrat feeds also carry news/press items, the BundesratKOMPAKT editorial summaries, the Stimmverteilung graphic, and the Präsidium / next-sitting HTML pages. Those return copyright-protected editorial text and images, not open data, so this CLI doesn't expose them (and strips the editorial fields — HTML
detail, biographies, images — from the three it keeps). See DATA_LICENSE.md.
members filters
| Option | Meaning |
| --- | --- |
| --state <Land> | Only members of that federal state — case-insensitive, exact Land match (e.g. Bayern, Baden-Württemberg) |
| --party <text> | Only members whose party contains this text — case-insensitive substring (e.g. grüne, CDU) |
Filtering happens client-side (the feed returns everyone), so both filters compose
and an unmatched filter yields [] rather than the full list.
Output & scripting
Every command prints JSON to stdout; diagnostics go to stderr, so piping into
jq stays clean.
# How many agenda items in the current sitting?
bundesrat session | jq '.tops | length'
# Drucksachen on the agenda
bundesrat session | jq -r '.tops[].topdrucksache | select(.)'
# Members grouped by party
bundesrat members | jq -r 'group_by(.party)[] | "\(.[0].party): \(length)"'Use --compact for single-line JSON and -o <file> to write to a file — both are
global options that work before or after the command.
Exit codes make the CLI easy to use in scripts:
| Code | Meaning |
| --- | --- |
| 0 | Success (also --help / --version) |
| 2 | Bad usage / invalid argument (nothing was sent) |
| 4 | Not found (404 from the server) |
| 6 | Network / transport failure (DNS, connection, timeout, size cap) |
| 1 | Any other error — including a non-XML response (the feed returned the website's HTML shell) |
Troubleshooting
command not found: bundesrat— the global npm bin directory isn't on yourPATH. Runnpm bin -gto find it and add it, or run vianpx @maschinenlesbar.org/bundesrat-cli ….- Exit
1/ "received an HTML page" — the feed returned the website's HTML shell instead of XML (it may have moved). The CLI already adds the required?view=renderXmlrender parameter; if this persists, the upstream feed changed. - Empty
topsbetween sittings — outside an active sitting the agenda feed can be sparse:topsmay be[]andsession'stitle/headermay be absent (both are optional), so guard for them in scripts. - A field you expected is missing — the CLI surfaces only openly-licensed
factual fields; the feeds' HTML
detail/abstractbodies, biographies and images are stripped on purpose (see DATA_LICENSE.md).
Global options
Given before or after the command, e.g. bundesrat --compact session:
| Option | Description |
| --- | --- |
| -V, --version | Print the version number |
| -h, --help | Show help for the program or a command |
| --compact | Print JSON on a single line instead of pretty-printed |
| -o, --output <file> | Write output to this file instead of stdout |
| --base-url <url> | API base URL (default https://www.bundesrat.de) |
| --timeout <ms> | Per-request timeout (default 30000) |
| --user-agent <ua> | User-Agent header value |
| --max-retries <n> | Retries for transient 429/503 responses (0..10, default 2) |
| --max-response-bytes <n> | Cap response body size in bytes (0 = unlimited; default 100 MiB) |
Learn more
- SKILLS.md — Claude Code Agent Skills that drive this CLI.
- Usage.md — full use-case-driven cookbook.
- GLOSSARY.md — every domain term explained.
- DEVELOPING.md — TypeScript library usage, the XML parser, architecture, testing, CI.
Data license
This CLI is a client — it accesses data it does not own or redistribute. The upstream data is © the Bundesrat and licensed separately from this tool's code. See DATA_LICENSE.md.
Bundesrat — website content is copyright-protected (personal use only; commercial use / redistribution need permission), so cite "Quelle: Bundesrat" and don't republish editorial text or images without asking. The Drucksachen and Plenarprotokolle are amtliche Werke (§ 5 Abs. 2 UrhG) — free to reuse unaltered and with a source citation.
License
Dual-licensed — use it under either:
- AGPL-3.0-or-later (default, free). Note the AGPL's §13 network clause: if you run a modified version as a network service, you must offer that modified source to the service's users.
- Commercial license (paid), for closed-source / proprietary or SaaS use without the AGPL's obligations.
See LICENSING.md for details, and CONTRIBUTING.md for the contribution policy (this project does not accept external code contributions). Commercial enquiries: [email protected].
