codex-statusline 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zimo Xu
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,107 @@
1
+ Metadata-Version: 2.4
2
+ Name: codex-statusline
3
+ Version: 0.1.0
4
+ Summary: A tmux statusline for OpenAI Codex CLI: context usage, 5h and weekly quota, and session tokens at a glance. Local-only.
5
+ Author: Zimo Xu
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Moviw/codex-statusline
8
+ Project-URL: Issues, https://github.com/Moviw/codex-statusline/issues
9
+ Project-URL: Changelog, https://github.com/Moviw/codex-statusline/blob/main/CHANGELOG.md
10
+ Keywords: codex,codex-cli,openai,statusline,tmux,quota,tokens,terminal
11
+ Classifier: Environment :: Console
12
+ Classifier: Operating System :: MacOS
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Terminals
16
+ Classifier: Topic :: Utilities
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Dynamic: license-file
21
+
22
+ # codex-statusline
23
+
24
+ **See your Codex context and quota at a glance.**
25
+
26
+ [![tests](https://github.com/Moviw/codex-statusline/actions/workflows/tests.yml/badge.svg)](https://github.com/Moviw/codex-statusline/actions/workflows/tests.yml)
27
+ [![PyPI](https://img.shields.io/pypi/v/codex-statusline)](https://pypi.org/project/codex-statusline/)
28
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
29
+
30
+ English | [简体中文](README.zh-CN.md)
31
+
32
+ A status bar for [OpenAI Codex CLI](https://github.com/openai/codex). It shows context used, 5-hour and weekly quota left with reset times, and session tokens. You keep running `codex` exactly as before.
33
+
34
+ ![codex-statusline demo](docs/preview.svg)
35
+
36
+ ```text
37
+ CTX USED ███░░░░░ 35% | 5h ████████░░ 78% 5:41pm | week ████░░░░░░ 39% Fri 3:41pm | tok 1.2M
38
+ ```
39
+
40
+ ## Why
41
+
42
+ - **No more `/status` interruptions.** Quota and context sit in view while you work.
43
+ - **Local only.** Never reads `auth.json`, never calls a quota API, never makes extra model calls.
44
+ - **Zero new habits.** Keep typing `codex`. `codex exec`, pipes, and scripts pass straight through to the official binary.
45
+ - **Honest numbers.** Unknown shows as `--` and stale quota shows as `refresh`. A missing value is never passed off as 0% or 100%.
46
+ - **Fits any width.** Segments collapse, then drop, as the terminal narrows.
47
+
48
+ ## Install
49
+
50
+ Requires macOS or Linux, [tmux](https://github.com/tmux/tmux), and Codex CLI ≥ 0.159.0. Bash, Zsh, and Fish are all detected automatically.
51
+
52
+ ```sh
53
+ curl -fsSL https://raw.githubusercontent.com/Moviw/codex-statusline/main/install.sh | sh
54
+ ```
55
+
56
+ The script installs [uv](https://docs.astral.sh/uv/) if needed (uv also fetches Python 3.11+ for you), installs the tool, then shows you the exact shell/hook diff and asks before writing anything.
57
+
58
+ Prefer to do it yourself:
59
+
60
+ ```sh
61
+ uv tool install codex-statusline # or: pipx install codex-statusline
62
+ codex-statusline install # add --dry-run to only preview the diff
63
+ ```
64
+
65
+ Then **open a new terminal** and run `codex`. The first time, Codex asks you to review a hook: confirm it is `codex-statusline binding`.
66
+
67
+ Missing tmux? `brew install tmux` or `sudo apt install tmux`.
68
+
69
+ ## Usage
70
+
71
+ ```sh
72
+ codex # same as always, now with a status bar
73
+ codex resume --last
74
+ codex exec 'task' # non-interactive: passed straight through, no bar
75
+
76
+ codex-statusline doctor # check versions and dependencies
77
+ codex-statusline preview --demo --width 80 # try it without launching Codex
78
+ codex-statusline uninstall
79
+ ```
80
+
81
+ Uninstall removes only what this tool added and still matches exactly. If you edited its block, it stops instead of overwriting. Backups live in `~/.local/share/codex-statusline/`.
82
+
83
+ ## Configuration
84
+
85
+ Optional. Create `~/.config/codex-statusline/config.toml`:
86
+
87
+ ```toml
88
+ segments = ["ctx", "5h", "week", "tokens"] # pick and reorder
89
+ theme = "dark" # dark | light
90
+ ascii = false # true for terminals without block glyphs
91
+ warn_at = 20 # quota remaining % that turns yellow
92
+ crit_at = 5 # quota remaining % that turns red
93
+ ```
94
+
95
+ Invalid values are reported and fall back to defaults.
96
+
97
+ ## How it works
98
+
99
+ `codex` becomes a small shell function that starts the official CLI inside a private tmux session and draws the bar at the bottom. Data comes from two places only: the terminal title Codex already emits (model, context, thread id), and the rollout log of *this* session, which a SessionStart hook pins by exact path. The official binary is not replaced or patched, and your tmux config is not touched. Details: [docs/architecture.md](docs/architecture.md).
100
+
101
+ ## FAQ
102
+
103
+ **How do I scroll or copy?** It runs inside tmux: press `Ctrl-B` then `[` to scroll and copy. The mouse wheel may behave differently from bare Codex.
104
+
105
+ **Windows?** Not supported (tmux).
106
+
107
+ **Is this official?** No. It is a third-party tool built on a version-sensitive integration.
@@ -0,0 +1,86 @@
1
+ # codex-statusline
2
+
3
+ **See your Codex context and quota at a glance.**
4
+
5
+ [![tests](https://github.com/Moviw/codex-statusline/actions/workflows/tests.yml/badge.svg)](https://github.com/Moviw/codex-statusline/actions/workflows/tests.yml)
6
+ [![PyPI](https://img.shields.io/pypi/v/codex-statusline)](https://pypi.org/project/codex-statusline/)
7
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
8
+
9
+ English | [简体中文](README.zh-CN.md)
10
+
11
+ A status bar for [OpenAI Codex CLI](https://github.com/openai/codex). It shows context used, 5-hour and weekly quota left with reset times, and session tokens. You keep running `codex` exactly as before.
12
+
13
+ ![codex-statusline demo](docs/preview.svg)
14
+
15
+ ```text
16
+ CTX USED ███░░░░░ 35% | 5h ████████░░ 78% 5:41pm | week ████░░░░░░ 39% Fri 3:41pm | tok 1.2M
17
+ ```
18
+
19
+ ## Why
20
+
21
+ - **No more `/status` interruptions.** Quota and context sit in view while you work.
22
+ - **Local only.** Never reads `auth.json`, never calls a quota API, never makes extra model calls.
23
+ - **Zero new habits.** Keep typing `codex`. `codex exec`, pipes, and scripts pass straight through to the official binary.
24
+ - **Honest numbers.** Unknown shows as `--` and stale quota shows as `refresh`. A missing value is never passed off as 0% or 100%.
25
+ - **Fits any width.** Segments collapse, then drop, as the terminal narrows.
26
+
27
+ ## Install
28
+
29
+ Requires macOS or Linux, [tmux](https://github.com/tmux/tmux), and Codex CLI ≥ 0.159.0. Bash, Zsh, and Fish are all detected automatically.
30
+
31
+ ```sh
32
+ curl -fsSL https://raw.githubusercontent.com/Moviw/codex-statusline/main/install.sh | sh
33
+ ```
34
+
35
+ The script installs [uv](https://docs.astral.sh/uv/) if needed (uv also fetches Python 3.11+ for you), installs the tool, then shows you the exact shell/hook diff and asks before writing anything.
36
+
37
+ Prefer to do it yourself:
38
+
39
+ ```sh
40
+ uv tool install codex-statusline # or: pipx install codex-statusline
41
+ codex-statusline install # add --dry-run to only preview the diff
42
+ ```
43
+
44
+ Then **open a new terminal** and run `codex`. The first time, Codex asks you to review a hook: confirm it is `codex-statusline binding`.
45
+
46
+ Missing tmux? `brew install tmux` or `sudo apt install tmux`.
47
+
48
+ ## Usage
49
+
50
+ ```sh
51
+ codex # same as always, now with a status bar
52
+ codex resume --last
53
+ codex exec 'task' # non-interactive: passed straight through, no bar
54
+
55
+ codex-statusline doctor # check versions and dependencies
56
+ codex-statusline preview --demo --width 80 # try it without launching Codex
57
+ codex-statusline uninstall
58
+ ```
59
+
60
+ Uninstall removes only what this tool added and still matches exactly. If you edited its block, it stops instead of overwriting. Backups live in `~/.local/share/codex-statusline/`.
61
+
62
+ ## Configuration
63
+
64
+ Optional. Create `~/.config/codex-statusline/config.toml`:
65
+
66
+ ```toml
67
+ segments = ["ctx", "5h", "week", "tokens"] # pick and reorder
68
+ theme = "dark" # dark | light
69
+ ascii = false # true for terminals without block glyphs
70
+ warn_at = 20 # quota remaining % that turns yellow
71
+ crit_at = 5 # quota remaining % that turns red
72
+ ```
73
+
74
+ Invalid values are reported and fall back to defaults.
75
+
76
+ ## How it works
77
+
78
+ `codex` becomes a small shell function that starts the official CLI inside a private tmux session and draws the bar at the bottom. Data comes from two places only: the terminal title Codex already emits (model, context, thread id), and the rollout log of *this* session, which a SessionStart hook pins by exact path. The official binary is not replaced or patched, and your tmux config is not touched. Details: [docs/architecture.md](docs/architecture.md).
79
+
80
+ ## FAQ
81
+
82
+ **How do I scroll or copy?** It runs inside tmux: press `Ctrl-B` then `[` to scroll and copy. The mouse wheel may behave differently from bare Codex.
83
+
84
+ **Windows?** Not supported (tmux).
85
+
86
+ **Is this official?** No. It is a third-party tool built on a version-sensitive integration.
@@ -0,0 +1,107 @@
1
+ Metadata-Version: 2.4
2
+ Name: codex-statusline
3
+ Version: 0.1.0
4
+ Summary: A tmux statusline for OpenAI Codex CLI: context usage, 5h and weekly quota, and session tokens at a glance. Local-only.
5
+ Author: Zimo Xu
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Moviw/codex-statusline
8
+ Project-URL: Issues, https://github.com/Moviw/codex-statusline/issues
9
+ Project-URL: Changelog, https://github.com/Moviw/codex-statusline/blob/main/CHANGELOG.md
10
+ Keywords: codex,codex-cli,openai,statusline,tmux,quota,tokens,terminal
11
+ Classifier: Environment :: Console
12
+ Classifier: Operating System :: MacOS
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Terminals
16
+ Classifier: Topic :: Utilities
17
+ Requires-Python: >=3.11
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Dynamic: license-file
21
+
22
+ # codex-statusline
23
+
24
+ **See your Codex context and quota at a glance.**
25
+
26
+ [![tests](https://github.com/Moviw/codex-statusline/actions/workflows/tests.yml/badge.svg)](https://github.com/Moviw/codex-statusline/actions/workflows/tests.yml)
27
+ [![PyPI](https://img.shields.io/pypi/v/codex-statusline)](https://pypi.org/project/codex-statusline/)
28
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
29
+
30
+ English | [简体中文](README.zh-CN.md)
31
+
32
+ A status bar for [OpenAI Codex CLI](https://github.com/openai/codex). It shows context used, 5-hour and weekly quota left with reset times, and session tokens. You keep running `codex` exactly as before.
33
+
34
+ ![codex-statusline demo](docs/preview.svg)
35
+
36
+ ```text
37
+ CTX USED ███░░░░░ 35% | 5h ████████░░ 78% 5:41pm | week ████░░░░░░ 39% Fri 3:41pm | tok 1.2M
38
+ ```
39
+
40
+ ## Why
41
+
42
+ - **No more `/status` interruptions.** Quota and context sit in view while you work.
43
+ - **Local only.** Never reads `auth.json`, never calls a quota API, never makes extra model calls.
44
+ - **Zero new habits.** Keep typing `codex`. `codex exec`, pipes, and scripts pass straight through to the official binary.
45
+ - **Honest numbers.** Unknown shows as `--` and stale quota shows as `refresh`. A missing value is never passed off as 0% or 100%.
46
+ - **Fits any width.** Segments collapse, then drop, as the terminal narrows.
47
+
48
+ ## Install
49
+
50
+ Requires macOS or Linux, [tmux](https://github.com/tmux/tmux), and Codex CLI ≥ 0.159.0. Bash, Zsh, and Fish are all detected automatically.
51
+
52
+ ```sh
53
+ curl -fsSL https://raw.githubusercontent.com/Moviw/codex-statusline/main/install.sh | sh
54
+ ```
55
+
56
+ The script installs [uv](https://docs.astral.sh/uv/) if needed (uv also fetches Python 3.11+ for you), installs the tool, then shows you the exact shell/hook diff and asks before writing anything.
57
+
58
+ Prefer to do it yourself:
59
+
60
+ ```sh
61
+ uv tool install codex-statusline # or: pipx install codex-statusline
62
+ codex-statusline install # add --dry-run to only preview the diff
63
+ ```
64
+
65
+ Then **open a new terminal** and run `codex`. The first time, Codex asks you to review a hook: confirm it is `codex-statusline binding`.
66
+
67
+ Missing tmux? `brew install tmux` or `sudo apt install tmux`.
68
+
69
+ ## Usage
70
+
71
+ ```sh
72
+ codex # same as always, now with a status bar
73
+ codex resume --last
74
+ codex exec 'task' # non-interactive: passed straight through, no bar
75
+
76
+ codex-statusline doctor # check versions and dependencies
77
+ codex-statusline preview --demo --width 80 # try it without launching Codex
78
+ codex-statusline uninstall
79
+ ```
80
+
81
+ Uninstall removes only what this tool added and still matches exactly. If you edited its block, it stops instead of overwriting. Backups live in `~/.local/share/codex-statusline/`.
82
+
83
+ ## Configuration
84
+
85
+ Optional. Create `~/.config/codex-statusline/config.toml`:
86
+
87
+ ```toml
88
+ segments = ["ctx", "5h", "week", "tokens"] # pick and reorder
89
+ theme = "dark" # dark | light
90
+ ascii = false # true for terminals without block glyphs
91
+ warn_at = 20 # quota remaining % that turns yellow
92
+ crit_at = 5 # quota remaining % that turns red
93
+ ```
94
+
95
+ Invalid values are reported and fall back to defaults.
96
+
97
+ ## How it works
98
+
99
+ `codex` becomes a small shell function that starts the official CLI inside a private tmux session and draws the bar at the bottom. Data comes from two places only: the terminal title Codex already emits (model, context, thread id), and the rollout log of *this* session, which a SessionStart hook pins by exact path. The official binary is not replaced or patched, and your tmux config is not touched. Details: [docs/architecture.md](docs/architecture.md).
100
+
101
+ ## FAQ
102
+
103
+ **How do I scroll or copy?** It runs inside tmux: press `Ctrl-B` then `[` to scroll and copy. The mouse wheel may behave differently from bare Codex.
104
+
105
+ **Windows?** Not supported (tmux).
106
+
107
+ **Is this official?** No. It is a third-party tool built on a version-sensitive integration.
@@ -0,0 +1,24 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ codex_statusline.egg-info/PKG-INFO
5
+ codex_statusline.egg-info/SOURCES.txt
6
+ codex_statusline.egg-info/dependency_links.txt
7
+ codex_statusline.egg-info/entry_points.txt
8
+ codex_statusline.egg-info/top_level.txt
9
+ src/__init__.py
10
+ src/__main__.py
11
+ src/cli.py
12
+ src/data.py
13
+ src/entry.py
14
+ src/hook.py
15
+ src/launcher.py
16
+ src/manage.py
17
+ src/render.py
18
+ tests/test_auto_shells.py
19
+ tests/test_data.py
20
+ tests/test_fish.py
21
+ tests/test_management.py
22
+ tests/test_render.py
23
+ tests/test_startup.py
24
+ tests/test_tmux.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ codex-statusline = src.cli:main
@@ -0,0 +1,39 @@
1
+ [project]
2
+ name = "codex-statusline"
3
+ version = "0.1.0"
4
+ description = "A tmux statusline for OpenAI Codex CLI: context usage, 5h and weekly quota, and session tokens at a glance. Local-only."
5
+ requires-python = ">=3.11"
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ authors = [{ name = "Zimo Xu" }]
9
+ keywords = ["codex", "codex-cli", "openai", "statusline", "tmux", "quota", "tokens", "terminal"]
10
+ classifiers = [
11
+ "Environment :: Console",
12
+ "Operating System :: MacOS",
13
+ "Operating System :: POSIX :: Linux",
14
+ "Programming Language :: Python :: 3",
15
+ "Topic :: Terminals",
16
+ "Topic :: Utilities",
17
+ ]
18
+
19
+ [project.urls]
20
+ Homepage = "https://github.com/Moviw/codex-statusline"
21
+ Issues = "https://github.com/Moviw/codex-statusline/issues"
22
+ Changelog = "https://github.com/Moviw/codex-statusline/blob/main/CHANGELOG.md"
23
+
24
+ [project.scripts]
25
+ codex-statusline = "src.cli:main"
26
+
27
+ [build-system]
28
+ requires = ["setuptools>=77"]
29
+ build-backend = "setuptools.build_meta"
30
+
31
+ [tool.setuptools]
32
+ packages = ["src"]
33
+
34
+ [tool.ruff]
35
+ line-length = 100
36
+ target-version = "py311"
37
+
38
+ [tool.ruff.lint]
39
+ select = ["E", "F", "W", "I", "UP", "B"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """A local-only tmux status area for the official Codex CLI."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ raise SystemExit(main())
@@ -0,0 +1,120 @@
1
+ import argparse
2
+ import json
3
+ import os
4
+ import shutil
5
+ import sys
6
+ import time
7
+ from pathlib import Path
8
+
9
+ from . import __version__
10
+
11
+
12
+ def main():
13
+ args = sys.argv[1:]
14
+ from .launcher import child, launch, official, raw, version
15
+
16
+ if args and args[0] in ("launch", "raw"):
17
+ try:
18
+ return (launch if args[0] == "launch" else raw)(args[1:])
19
+ except KeyboardInterrupt:
20
+ return 130
21
+ if args and args[0] == "_child":
22
+ return child(args[1])
23
+ if args and args[0] == "hook":
24
+ from .hook import record
25
+
26
+ record()
27
+ return 0
28
+ parser = argparse.ArgumentParser(
29
+ description="Third-party local tmux statusline for the official Codex CLI."
30
+ )
31
+ parser.add_argument("--version", action="version", version=__version__)
32
+ sub = parser.add_subparsers(dest="action", required=True)
33
+ for name in ("install", "uninstall"):
34
+ s = sub.add_parser(name)
35
+ s.add_argument(
36
+ "--shell",
37
+ choices=["auto", "bash", "zsh", "fish", "both", "all"],
38
+ default="auto",
39
+ help="default: all supported shells found on PATH",
40
+ )
41
+ s.add_argument("--home", default=str(Path.home()), help="target home (for isolated tests)")
42
+ s.add_argument(
43
+ "--yes",
44
+ action="store_true",
45
+ help="approve printed diff without interactive prompt",
46
+ )
47
+ s.add_argument("--dry-run", action="store_true")
48
+ sub.add_parser("doctor")
49
+ p = sub.add_parser("preview")
50
+ p.add_argument("--width", type=int, default=120)
51
+ p.add_argument("--theme", choices=["dark", "light"])
52
+ p.add_argument("--ascii", action="store_true")
53
+ p.add_argument("--tmux", action="store_true", help="emit tmux style syntax, not ANSI")
54
+ p.add_argument("--demo", action="store_true", help="show explicitly synthetic example data")
55
+ ns = parser.parse_args(args)
56
+ try:
57
+ if ns.action in ("install", "uninstall"):
58
+ from .manage import installation
59
+
60
+ return installation(ns, ns.action == "uninstall")
61
+ if ns.action == "doctor":
62
+ path = official()
63
+ data = {
64
+ "python": sys.version.split()[0],
65
+ "codex": path,
66
+ "codex_version": ".".join(map(str, version(path))),
67
+ "tmux": shutil.which("tmux"),
68
+ "shell": os.environ.get("SHELL"),
69
+ "tested_codex": "0.159.0",
70
+ "credentials_read": False,
71
+ }
72
+ print(json.dumps(data, indent=2))
73
+ return 0 if data["tmux"] and version(path) >= (0, 159, 0) else 1
74
+ if ns.action == "preview":
75
+ from .render import load_config, render
76
+
77
+ cfg = load_config()
78
+ now = time.time()
79
+ state = {
80
+ "model": "Codex",
81
+ "cwd": os.getcwd(),
82
+ "context_used": None,
83
+ "quotas": {},
84
+ }
85
+ if ns.demo:
86
+ state.update(
87
+ model="DEMO GPT-6",
88
+ context_used=35,
89
+ cwd="~/project",
90
+ branch="main",
91
+ tokens=1_234_567,
92
+ quotas={
93
+ "5h": {
94
+ "remaining": 78,
95
+ "reset_at": now + 7200,
96
+ "observed_at": now,
97
+ },
98
+ "weekly": {
99
+ "remaining": 39,
100
+ "reset_at": now + 172800,
101
+ "observed_at": now,
102
+ },
103
+ },
104
+ )
105
+ print(
106
+ render(
107
+ state,
108
+ ns.width,
109
+ theme=ns.theme or cfg["theme"],
110
+ ascii_only=ns.ascii or cfg["ascii"],
111
+ tmux=ns.tmux,
112
+ segments=cfg["segments"],
113
+ warn_at=cfg["warn_at"],
114
+ crit_at=cfg["crit_at"],
115
+ )
116
+ )
117
+ return 0
118
+ except (OSError, ValueError, RuntimeError, KeyError) as error:
119
+ print(f"codex-statusline: {error}", file=sys.stderr)
120
+ return 1