fed-debt 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fed_debt-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xorn the first
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: fed-debt
3
+ Version: 0.1.0
4
+ Summary: Check the current US federal debt to the penny
5
+ Author-email: xorn the first <x0rn@gitlab.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://gitlab.com/x0rn/fed-debt
8
+ Project-URL: Repository, https://gitlab.com/x0rn/fed-debt
9
+ Project-URL: Bug Tracker, https://gitlab.com/x0rn/fed-debt/-/issues
10
+ Keywords: treasury,debt,us-debt,finance
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Topic :: Office/Business :: Financial
18
+ Classifier: Intended Audience :: End Users/Desktop
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: httpx
23
+ Requires-Dist: rich
24
+ Provides-Extra: ticker
25
+ Requires-Dist: windows-curses; sys_platform == "win32" and extra == "ticker"
26
+ Dynamic: license-file
27
+
28
+ # fed-debt πŸ‡ΊπŸ‡Έ
29
+
30
+ Check the current US federal debt, to the penny.
31
+
32
+ ```
33
+ $ fed-debt
34
+ $39,828,435,390,891.55
35
+
36
+ $ fed-debt --verbose
37
+ US Federal Debt β€” 2026-08-04
38
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
39
+ β”‚ Metric β”‚ Amount β”‚
40
+ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
41
+ β”‚ Total Public Debt Outstanding β”‚ $39,828,435,390,891.55 β”‚
42
+ β”‚ Debt Held by the Public β”‚ $32,100,703,256,953.12 β”‚
43
+ β”‚ Intragovernmental Holdings β”‚ $7,727,732,133,938.43 β”‚
44
+ β”‚ Debt per US Citizen β”‚ $118,890.85 β”‚
45
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
46
+ ```
47
+
48
+ ## Install
49
+
50
+ ### From PyPI (recommended)
51
+
52
+ ```bash
53
+ pip install fed-debt
54
+ ```
55
+
56
+ Or with ticker support (requires `windows-curses` on Windows):
57
+
58
+ ```bash
59
+ pip install "fed-debt[ticker]"
60
+ ```
61
+
62
+ ### From source
63
+
64
+ ```bash
65
+ git clone https://gitlab.com/x0rn/fed-debt.git
66
+ cd fed-debt
67
+ py -m pip install -e .
68
+ ```
69
+
70
+ Or for the ticker:
71
+
72
+ ```bash
73
+ py -m pip install -e ".[ticker]"
74
+ ```
75
+
76
+ ## Usage
77
+
78
+ | Command | What it does |
79
+ |------------------------|-------------------------------------------------|
80
+ | `fed-debt` | Prints the latest total debt to the penny |
81
+ | `fed-debt --verbose` | Detailed breakdown table with per-citizen debt |
82
+ | `fed-debt --ticker` | Opens a small live-updating ticker window |
83
+ | `fed-debt --version` | Prints version number |
84
+ | `fed-debt --help` | Shows usage |
85
+
86
+ ### Ticker
87
+
88
+ The `--ticker` flag opens a thin, 3-line curses window that shows a
89
+ **continuously incrementing** debt counter. Instead of polling the API
90
+ every few seconds (wasteful β€” the data only updates once a day at
91
+ 3:00 PM ET), it:
92
+
93
+ 1. Fetches the latest official reading on startup
94
+ 2. Estimates the per-second growth from recent history (~$1.3B/day)
95
+ 3. Interpolates the current value in real-time
96
+
97
+ Press `q` to quit, `r` to force a re-sync with the Treasury API.
98
+
99
+ ## Data Source
100
+
101
+ U.S. Treasury Fiscal Data β€” [Debt to the Penny](https://fiscaldata.treasury.gov/datasets/debt-to-the-penny)
102
+ endpoint, updated daily at 3:00 PM ET.
103
+
104
+ ## Future
105
+
106
+ - `--chart` β€” terminal-based historical charts (via `plotext`)
107
+ - `--since` β€” see the debt on a specific past date
108
+ - GUI/web backend using the same `api.py` module
@@ -0,0 +1,81 @@
1
+ # fed-debt πŸ‡ΊπŸ‡Έ
2
+
3
+ Check the current US federal debt, to the penny.
4
+
5
+ ```
6
+ $ fed-debt
7
+ $39,828,435,390,891.55
8
+
9
+ $ fed-debt --verbose
10
+ US Federal Debt β€” 2026-08-04
11
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
12
+ β”‚ Metric β”‚ Amount β”‚
13
+ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
14
+ β”‚ Total Public Debt Outstanding β”‚ $39,828,435,390,891.55 β”‚
15
+ β”‚ Debt Held by the Public β”‚ $32,100,703,256,953.12 β”‚
16
+ β”‚ Intragovernmental Holdings β”‚ $7,727,732,133,938.43 β”‚
17
+ β”‚ Debt per US Citizen β”‚ $118,890.85 β”‚
18
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
19
+ ```
20
+
21
+ ## Install
22
+
23
+ ### From PyPI (recommended)
24
+
25
+ ```bash
26
+ pip install fed-debt
27
+ ```
28
+
29
+ Or with ticker support (requires `windows-curses` on Windows):
30
+
31
+ ```bash
32
+ pip install "fed-debt[ticker]"
33
+ ```
34
+
35
+ ### From source
36
+
37
+ ```bash
38
+ git clone https://gitlab.com/x0rn/fed-debt.git
39
+ cd fed-debt
40
+ py -m pip install -e .
41
+ ```
42
+
43
+ Or for the ticker:
44
+
45
+ ```bash
46
+ py -m pip install -e ".[ticker]"
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ | Command | What it does |
52
+ |------------------------|-------------------------------------------------|
53
+ | `fed-debt` | Prints the latest total debt to the penny |
54
+ | `fed-debt --verbose` | Detailed breakdown table with per-citizen debt |
55
+ | `fed-debt --ticker` | Opens a small live-updating ticker window |
56
+ | `fed-debt --version` | Prints version number |
57
+ | `fed-debt --help` | Shows usage |
58
+
59
+ ### Ticker
60
+
61
+ The `--ticker` flag opens a thin, 3-line curses window that shows a
62
+ **continuously incrementing** debt counter. Instead of polling the API
63
+ every few seconds (wasteful β€” the data only updates once a day at
64
+ 3:00 PM ET), it:
65
+
66
+ 1. Fetches the latest official reading on startup
67
+ 2. Estimates the per-second growth from recent history (~$1.3B/day)
68
+ 3. Interpolates the current value in real-time
69
+
70
+ Press `q` to quit, `r` to force a re-sync with the Treasury API.
71
+
72
+ ## Data Source
73
+
74
+ U.S. Treasury Fiscal Data β€” [Debt to the Penny](https://fiscaldata.treasury.gov/datasets/debt-to-the-penny)
75
+ endpoint, updated daily at 3:00 PM ET.
76
+
77
+ ## Future
78
+
79
+ - `--chart` β€” terminal-based historical charts (via `plotext`)
80
+ - `--since` β€” see the debt on a specific past date
81
+ - GUI/web backend using the same `api.py` module
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "fed-debt"
7
+ version = "0.1.0"
8
+ description = "Check the current US federal debt to the penny"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ {name = "xorn the first", email = "x0rn@gitlab.com"},
15
+ ]
16
+ keywords = ["treasury", "debt", "us-debt", "finance"]
17
+ classifiers = [
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Operating System :: OS Independent",
24
+ "Topic :: Office/Business :: Financial",
25
+ "Intended Audience :: End Users/Desktop",
26
+ ]
27
+
28
+ dependencies = [
29
+ "httpx",
30
+ "rich",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ ticker = ["windows-curses; sys_platform == 'win32'"]
35
+
36
+ [project.urls]
37
+ Homepage = "https://gitlab.com/x0rn/fed-debt"
38
+ Repository = "https://gitlab.com/x0rn/fed-debt"
39
+ "Bug Tracker" = "https://gitlab.com/x0rn/fed-debt/-/issues"
40
+
41
+ [project.scripts]
42
+ fed-debt = "fed_debt.cli:main"
43
+
44
+ [tool.setuptools.packages.find]
45
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,7 @@
1
+ """fed-debt: Check the current US federal debt to the penny."""
2
+
3
+ __version__ = "0.1.0"
4
+
5
+ # Rough US population estimate (used for per-capita calculations).
6
+ # Source: Census Bureau quick facts (~335M as of 2025-2026).
7
+ US_POPULATION = 335_000_000
@@ -0,0 +1,6 @@
1
+ """python -m fed_debt entry point."""
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == "__main__":
6
+ raise SystemExit(main())
@@ -0,0 +1,137 @@
1
+ """Fetch US federal debt data from the Treasury Fiscal Data API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import dataclasses
6
+ import datetime
7
+ from typing import Any
8
+
9
+ import httpx
10
+
11
+ BASE_URL = (
12
+ "https://api.fiscaldata.treasury.gov/services/api/fiscal_service"
13
+ )
14
+ ENDPOINT = "/v2/accounting/od/debt_to_penny"
15
+
16
+ # Seconds in a full day (used for real-time ticker interpolation)
17
+ SECONDS_PER_DAY = 86_400
18
+
19
+
20
+ @dataclasses.dataclass(frozen=True)
21
+ class DebtSnapshot:
22
+ """A single official debt reading from the Treasury."""
23
+
24
+ record_date: datetime.date
25
+ tot_pub_debt_out_amt: float
26
+ debt_held_public_amt: float
27
+ intragov_hold_amt: float
28
+
29
+ @property
30
+ def debt_per_citizen(self) -> float:
31
+ from fed_debt import US_POPULATION
32
+ return self.tot_pub_debt_out_amt / US_POPULATION
33
+
34
+ def format_dollar(self, value: float) -> str:
35
+ """Format a dollar amount with commas and 2 decimal places."""
36
+ return f"${value:,.2f}"
37
+
38
+ def total_dollar(self) -> str:
39
+ return self.format_dollar(self.tot_pub_debt_out_amt)
40
+
41
+ def public_dollar(self) -> str:
42
+ return self.format_dollar(self.debt_held_public_amt)
43
+
44
+ def intragov_dollar(self) -> str:
45
+ return self.format_dollar(self.intragov_hold_amt)
46
+
47
+ def per_citizen_dollar(self) -> str:
48
+ return self.format_dollar(self.debt_per_citizen)
49
+
50
+ def __str__(self) -> str:
51
+ return self.total_dollar()
52
+
53
+
54
+ class DebtClient:
55
+ """Client for the Treasury Fiscal Data API."""
56
+
57
+ def __init__(self, timeout: float = 15.0) -> None:
58
+ self._client = httpx.Client(timeout=timeout)
59
+
60
+ def close(self) -> None:
61
+ self._client.close()
62
+
63
+ def __enter__(self) -> DebtClient:
64
+ return self
65
+
66
+ def __exit__(self, *args: Any) -> None:
67
+ self.close()
68
+
69
+ # ------------------------------------------------------------------
70
+ # Public methods
71
+ # ------------------------------------------------------------------
72
+
73
+ def latest(self) -> DebtSnapshot:
74
+ """Fetch the single most recent debt record."""
75
+ raw = self._fetch(params={
76
+ "sort": "-record_date",
77
+ "page[size]": 1,
78
+ })
79
+ return self._parse_row(raw["data"][0])
80
+
81
+ def last_n(self, n: int) -> list[DebtSnapshot]:
82
+ """Fetch the *n* most recent debt records (newest first)."""
83
+ raw = self._fetch(params={
84
+ "sort": "-record_date",
85
+ "page[size]": n,
86
+ })
87
+ return [self._parse_row(row) for row in raw["data"]]
88
+
89
+ # ------------------------------------------------------------------
90
+ # Internal helpers
91
+ # ------------------------------------------------------------------
92
+
93
+ def _fetch(self, params: dict[str, Any]) -> dict[str, Any]:
94
+ url = BASE_URL + ENDPOINT
95
+ resp = self._client.get(url, params=params)
96
+ resp.raise_for_status()
97
+ return resp.json()
98
+
99
+ @staticmethod
100
+ def _parse_row(row: dict[str, str]) -> DebtSnapshot:
101
+ return DebtSnapshot(
102
+ record_date=datetime.date.fromisoformat(row["record_date"]),
103
+ tot_pub_debt_out_amt=float(row["tot_pub_debt_out_amt"]),
104
+ debt_held_public_amt=float(row["debt_held_public_amt"]),
105
+ intragov_hold_amt=float(row["intragov_hold_amt"]),
106
+ )
107
+
108
+ # ------------------------------------------------------------------
109
+ # Ticker helpers: compute a per-second growth rate
110
+ # ------------------------------------------------------------------
111
+
112
+ def daily_increase(self, n_days: int = 2) -> float:
113
+ """Return the average *daily* increase over the last *n_days*.
114
+
115
+ Fetches ``n_days + 1`` records so we can compute deltas between
116
+ consecutive business-day readings, then returns the mean daily
117
+ change in dollars.
118
+ """
119
+ records = self.last_n(n_days + 1)
120
+ if len(records) < 2:
121
+ return 0.0
122
+ deltas = []
123
+ for i in range(len(records) - 1):
124
+ delta = (
125
+ records[i].tot_pub_debt_out_amt
126
+ - records[i + 1].tot_pub_debt_out_amt
127
+ )
128
+ # Only count positive deltas (the debt grows)
129
+ if delta > 0:
130
+ deltas.append(delta)
131
+ if not deltas:
132
+ return 0.0
133
+ return sum(deltas) / len(deltas)
134
+
135
+ def per_second_increase(self, n_days: int = 5) -> float:
136
+ """Return the average *per-second* increase in dollars."""
137
+ return self.daily_increase(n_days) / SECONDS_PER_DAY
@@ -0,0 +1,116 @@
1
+ """Main CLI entry point for fed-debt."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import sys
7
+ from typing import NoReturn
8
+
9
+ from . import __version__
10
+ from .api import DebtClient
11
+ from .ticker import run_ticker
12
+
13
+
14
+ def build_parser() -> argparse.ArgumentParser:
15
+ parser = argparse.ArgumentParser(
16
+ prog="fed-debt",
17
+ description="Show the current US federal debt, to the penny.",
18
+ )
19
+ parser.add_argument(
20
+ "--verbose", "-v",
21
+ action="store_true",
22
+ help="Show a detailed breakdown including public vs intragovernmental "
23
+ "holdings and debt per citizen.",
24
+ )
25
+ parser.add_argument(
26
+ "--ticker", "-t",
27
+ action="store_true",
28
+ help="Open a small, continuously updating debt ticker window.",
29
+ )
30
+ parser.add_argument(
31
+ "--version",
32
+ action="store_true",
33
+ help="Print the version number and exit.",
34
+ )
35
+ return parser
36
+
37
+
38
+ def print_verbose(snapshot: "DebtSnapshot") -> None:
39
+ """Print a Rich-formatted detail table."""
40
+ try:
41
+ from rich.console import Console
42
+ from rich.table import Table
43
+ except ImportError:
44
+ # Fallback: plain-text output
45
+ print(f"Record date: {snapshot.record_date}")
46
+ print(f"Total debt: {snapshot.total_dollar()}")
47
+ print(f"Held by the public: {snapshot.public_dollar()}")
48
+ print(f"Intragovernmental: {snapshot.intragov_dollar()}")
49
+ print(f"Per US citizen: {snapshot.per_citizen_dollar()}")
50
+ print()
51
+ print(
52
+ "Data from the U.S. Treasury Fiscal Data API. "
53
+ "Updated at end of each business day with the "
54
+ "prior business day's figures."
55
+ )
56
+ return
57
+
58
+ console = Console()
59
+ table = Table(title=f"US Federal Debt β€” {snapshot.record_date}")
60
+
61
+ table.add_column("Metric", style="cyan", no_wrap=True)
62
+ table.add_column("Amount", style="bold green", justify="right")
63
+
64
+ table.add_row("Total Public Debt Outstanding", snapshot.total_dollar())
65
+ table.add_row("Debt Held by the Public", snapshot.public_dollar())
66
+ table.add_row("Intragovernmental Holdings", snapshot.intragov_dollar())
67
+ table.add_row("Debt per US Citizen", snapshot.per_citizen_dollar())
68
+
69
+ console.print(table)
70
+ console.print(
71
+ "[dim]Data from the U.S. Treasury Fiscal Data API. "
72
+ "Updated at end of each business day with the prior "
73
+ "business day's figures.[/dim]"
74
+ )
75
+
76
+
77
+ def print_brief(snapshot: "DebtSnapshot") -> None:
78
+ """Print just the dollar amount, with optional Rich styling."""
79
+ try:
80
+ from rich.console import Console
81
+ console = Console()
82
+ console.print(f"[bold green]{snapshot.total_dollar()}[/bold green]")
83
+ except ImportError:
84
+ print(snapshot.total_dollar())
85
+
86
+
87
+ def main(argv: list[str] | None = None) -> int:
88
+ parser = build_parser()
89
+ args = parser.parse_args(argv)
90
+
91
+ if args.version:
92
+ print(f"fed-debt v{__version__}")
93
+ return 0
94
+
95
+ if args.ticker:
96
+ return run_ticker()
97
+
98
+ # Normal mode: fetch and display the latest debt
99
+ try:
100
+ client = DebtClient()
101
+ snapshot = client.latest()
102
+ client.close()
103
+ except Exception as exc:
104
+ print(f"Error fetching debt data: {exc}", file=sys.stderr)
105
+ return 1
106
+
107
+ if args.verbose:
108
+ print_verbose(snapshot)
109
+ else:
110
+ print_brief(snapshot)
111
+
112
+ return 0
113
+
114
+
115
+ if __name__ == "__main__":
116
+ sys.exit(main())
@@ -0,0 +1,163 @@
1
+ """Curses-based live debt ticker window.
2
+
3
+ Usage
4
+ -----
5
+ from fed_debt.ticker import run_ticker
6
+ run_ticker() # opens the curses window
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import datetime
12
+ import time
13
+ from typing import Any
14
+
15
+ from .api import DebtClient, DebtSnapshot
16
+
17
+ # ── constants ────────────────────────────────────────────────────────
18
+ REFRESH_INTERVAL = 1.0 # seconds between display updates
19
+ SYNC_INTERVAL = 3600.0 # re-fetch official data every hour
20
+ SECONDS_PER_DAY = 86_400.0
21
+
22
+ # Coordinates of the three lines in the ticker window
23
+ LINE_DATE = 0
24
+ LINE_VALUE = 1
25
+ LINE_HELP = 2
26
+
27
+ WINDOW_HEIGHT = 3
28
+
29
+
30
+ def _format_float(value: float) -> str:
31
+ """Format a large dollar figure with commas and two decimals."""
32
+ return f"${value:,.2f}"
33
+
34
+
35
+ def _compute_current(
36
+ snapshot: DebtSnapshot,
37
+ per_second: float,
38
+ elapsed: float,
39
+ ) -> float:
40
+ """Interpolate the current debt based on the last official snapshot.
41
+
42
+ Parameters
43
+ ----------
44
+ snapshot :
45
+ The most recent official reading.
46
+ per_second :
47
+ Estimated per-second increase (dollars).
48
+ elapsed :
49
+ Number of seconds since the official snapshot's record date
50
+ (specifically, since midnight of that date β€” a reasonable
51
+ approximation).
52
+ """
53
+ return snapshot.tot_pub_debt_out_amt + (per_second * elapsed)
54
+
55
+
56
+ def _seconds_since_midnight(d: datetime.date) -> float:
57
+ """How many seconds have passed since midnight UTC of *d*."""
58
+ then = datetime.datetime(
59
+ d.year, d.month, d.day, tzinfo=datetime.timezone.utc,
60
+ )
61
+ now = datetime.datetime.now(datetime.timezone.utc)
62
+ return (now - then).total_seconds()
63
+
64
+
65
+ def run_ticker() -> int:
66
+ """Open the curses debt-ticker and block until the user quits.
67
+
68
+ Returns 0 on clean exit, 1 on error.
69
+ """
70
+ # ── bootstrap data ─────────────────────────────────────────────
71
+ try:
72
+ client = DebtClient()
73
+ snapshot = client.latest()
74
+ per_second = client.per_second_increase(n_days=5)
75
+ client.close()
76
+ except Exception as exc:
77
+ print(f"Error fetching initial debt data: {exc}")
78
+ return 1
79
+
80
+ last_sync = time.monotonic()
81
+ # Estimate seconds since midnight of the record date
82
+ elapsed = _seconds_since_midnight(snapshot.record_date)
83
+
84
+ # ── curses setup ────────────────────────────────────────────────
85
+ import curses
86
+
87
+ def _main(stdscr: Any) -> None:
88
+ nonlocal snapshot, per_second, last_sync, elapsed
89
+
90
+ curses.curs_set(0) # hide cursor
91
+ stdscr.nodelay(True) # non-blocking getch()
92
+ stdscr.timeout(int(REFRESH_INTERVAL * 1000))
93
+
94
+ while True:
95
+ now = time.monotonic()
96
+
97
+ # ── periodic re-sync with the API ─────────────────────
98
+ if now - last_sync >= SYNC_INTERVAL:
99
+ try:
100
+ cli = DebtClient()
101
+ fresh = cli.latest()
102
+ fresh_ps = cli.per_second_increase(n_days=5)
103
+ cli.close()
104
+ # Only update if the record date actually changed
105
+ if fresh.record_date != snapshot.record_date:
106
+ snapshot = fresh
107
+ per_second = fresh_ps
108
+ elapsed = _seconds_since_midnight(
109
+ snapshot.record_date,
110
+ )
111
+ last_sync = now
112
+ except Exception:
113
+ pass # keep going with stale data
114
+
115
+ # ── compute interpolated value ─────────────────────────
116
+ elapsed = _seconds_since_midnight(snapshot.record_date)
117
+ current = _compute_current(snapshot, per_second, elapsed)
118
+
119
+ # ── render ─────────────────────────────────────────────
120
+ height, width = stdscr.getmaxyx()
121
+
122
+ # Date line
123
+ date_str = f" Record date: {snapshot.record_date} "
124
+ stdscr.addstr(LINE_DATE, 0, date_str[: width - 1])
125
+
126
+ # Value line (centred if possible)
127
+ val_str = _format_float(current)
128
+ x = max(0, (width - len(val_str)) // 2)
129
+ stdscr.addstr(LINE_VALUE, x, val_str[: width - x - 1])
130
+
131
+ # Help line
132
+ help_str = " [q] quit [r] refresh "
133
+ stdscr.addstr(LINE_HELP, 0, help_str[: width - 1])
134
+
135
+ stdscr.refresh()
136
+
137
+ # ── keyboard handling ──────────────────────────────────
138
+ key = stdscr.getch()
139
+ if key in (ord("q"), ord("Q")):
140
+ break
141
+ if key in (ord("r"), ord("R")):
142
+ # Force re-sync now
143
+ try:
144
+ cli = DebtClient()
145
+ fresh = cli.latest()
146
+ fresh_ps = cli.per_second_increase(n_days=5)
147
+ cli.close()
148
+ if fresh.record_date != snapshot.record_date:
149
+ snapshot = fresh
150
+ per_second = fresh_ps
151
+ elapsed = _seconds_since_midnight(
152
+ snapshot.record_date,
153
+ )
154
+ last_sync = now
155
+ except Exception:
156
+ pass
157
+
158
+ try:
159
+ curses.wrapper(_main)
160
+ except KeyboardInterrupt:
161
+ pass
162
+
163
+ return 0
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: fed-debt
3
+ Version: 0.1.0
4
+ Summary: Check the current US federal debt to the penny
5
+ Author-email: xorn the first <x0rn@gitlab.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://gitlab.com/x0rn/fed-debt
8
+ Project-URL: Repository, https://gitlab.com/x0rn/fed-debt
9
+ Project-URL: Bug Tracker, https://gitlab.com/x0rn/fed-debt/-/issues
10
+ Keywords: treasury,debt,us-debt,finance
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Topic :: Office/Business :: Financial
18
+ Classifier: Intended Audience :: End Users/Desktop
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: httpx
23
+ Requires-Dist: rich
24
+ Provides-Extra: ticker
25
+ Requires-Dist: windows-curses; sys_platform == "win32" and extra == "ticker"
26
+ Dynamic: license-file
27
+
28
+ # fed-debt πŸ‡ΊπŸ‡Έ
29
+
30
+ Check the current US federal debt, to the penny.
31
+
32
+ ```
33
+ $ fed-debt
34
+ $39,828,435,390,891.55
35
+
36
+ $ fed-debt --verbose
37
+ US Federal Debt β€” 2026-08-04
38
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
39
+ β”‚ Metric β”‚ Amount β”‚
40
+ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
41
+ β”‚ Total Public Debt Outstanding β”‚ $39,828,435,390,891.55 β”‚
42
+ β”‚ Debt Held by the Public β”‚ $32,100,703,256,953.12 β”‚
43
+ β”‚ Intragovernmental Holdings β”‚ $7,727,732,133,938.43 β”‚
44
+ β”‚ Debt per US Citizen β”‚ $118,890.85 β”‚
45
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
46
+ ```
47
+
48
+ ## Install
49
+
50
+ ### From PyPI (recommended)
51
+
52
+ ```bash
53
+ pip install fed-debt
54
+ ```
55
+
56
+ Or with ticker support (requires `windows-curses` on Windows):
57
+
58
+ ```bash
59
+ pip install "fed-debt[ticker]"
60
+ ```
61
+
62
+ ### From source
63
+
64
+ ```bash
65
+ git clone https://gitlab.com/x0rn/fed-debt.git
66
+ cd fed-debt
67
+ py -m pip install -e .
68
+ ```
69
+
70
+ Or for the ticker:
71
+
72
+ ```bash
73
+ py -m pip install -e ".[ticker]"
74
+ ```
75
+
76
+ ## Usage
77
+
78
+ | Command | What it does |
79
+ |------------------------|-------------------------------------------------|
80
+ | `fed-debt` | Prints the latest total debt to the penny |
81
+ | `fed-debt --verbose` | Detailed breakdown table with per-citizen debt |
82
+ | `fed-debt --ticker` | Opens a small live-updating ticker window |
83
+ | `fed-debt --version` | Prints version number |
84
+ | `fed-debt --help` | Shows usage |
85
+
86
+ ### Ticker
87
+
88
+ The `--ticker` flag opens a thin, 3-line curses window that shows a
89
+ **continuously incrementing** debt counter. Instead of polling the API
90
+ every few seconds (wasteful β€” the data only updates once a day at
91
+ 3:00 PM ET), it:
92
+
93
+ 1. Fetches the latest official reading on startup
94
+ 2. Estimates the per-second growth from recent history (~$1.3B/day)
95
+ 3. Interpolates the current value in real-time
96
+
97
+ Press `q` to quit, `r` to force a re-sync with the Treasury API.
98
+
99
+ ## Data Source
100
+
101
+ U.S. Treasury Fiscal Data β€” [Debt to the Penny](https://fiscaldata.treasury.gov/datasets/debt-to-the-penny)
102
+ endpoint, updated daily at 3:00 PM ET.
103
+
104
+ ## Future
105
+
106
+ - `--chart` β€” terminal-based historical charts (via `plotext`)
107
+ - `--since` β€” see the debt on a specific past date
108
+ - GUI/web backend using the same `api.py` module
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/fed_debt/__init__.py
5
+ src/fed_debt/__main__.py
6
+ src/fed_debt/api.py
7
+ src/fed_debt/cli.py
8
+ src/fed_debt/ticker.py
9
+ src/fed_debt.egg-info/PKG-INFO
10
+ src/fed_debt.egg-info/SOURCES.txt
11
+ src/fed_debt.egg-info/dependency_links.txt
12
+ src/fed_debt.egg-info/entry_points.txt
13
+ src/fed_debt.egg-info/requires.txt
14
+ src/fed_debt.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ fed-debt = fed_debt.cli:main
@@ -0,0 +1,7 @@
1
+ httpx
2
+ rich
3
+
4
+ [ticker]
5
+
6
+ [ticker:sys_platform == "win32"]
7
+ windows-curses
@@ -0,0 +1 @@
1
+ fed_debt