codex-agent-framework 0.1.22__tar.gz → 0.1.23__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.
Files changed (112) hide show
  1. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/CHANGELOG.md +19 -0
  2. codex_agent_framework-0.1.23/PKG-INFO +649 -0
  3. codex_agent_framework-0.1.23/README.md +600 -0
  4. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/__init__.py +2 -0
  5. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/agent.py +7 -0
  6. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/main.py +15 -1
  7. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/config.py +1 -1
  8. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/message.py +7 -4
  9. codex_agent_framework-0.1.23/codex_agent/stream.py +79 -0
  10. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tui/chat.py +86 -19
  11. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tui/lifecycle.py +63 -12
  12. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/utils.py +1 -1
  13. codex_agent_framework-0.1.23/codex_agent/version.py +1 -0
  14. codex_agent_framework-0.1.23/codex_agent_framework.egg-info/PKG-INFO +649 -0
  15. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/SOURCES.txt +1 -0
  16. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/pyproject.toml +1 -1
  17. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_agent.py +160 -1
  18. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_chat.py +90 -0
  19. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_cli.py +49 -0
  20. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_messages.py +13 -0
  21. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_tui.py +66 -0
  22. codex_agent_framework-0.1.22/PKG-INFO +0 -908
  23. codex_agent_framework-0.1.22/README.md +0 -859
  24. codex_agent_framework-0.1.22/codex_agent/version.py +0 -1
  25. codex_agent_framework-0.1.22/codex_agent_framework.egg-info/PKG-INFO +0 -908
  26. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/LICENSE +0 -0
  27. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/MANIFEST.in +0 -0
  28. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/__main__.py +0 -0
  29. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/agent_runtime.py +0 -0
  30. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/ai.py +0 -0
  31. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/browser.py +0 -0
  32. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_commands.py +0 -0
  33. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/__init__.py +0 -0
  34. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/bash/__init__.py +0 -0
  35. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/browser/__init__.py +0 -0
  36. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/content/__init__.py +0 -0
  37. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/content/system.py +0 -0
  38. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/content/vision.py +0 -0
  39. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/desktop/__init__.py +0 -0
  40. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/environment/__init__.py +0 -0
  41. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/files/__init__.py +0 -0
  42. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/files/tools.py +0 -0
  43. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/interface/__init__.py +0 -0
  44. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/memory/__init__.py +0 -0
  45. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/planner/__init__.py +0 -0
  46. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/python/__init__.py +0 -0
  47. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/scheduler/__init__.py +0 -0
  48. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/subagents/__init__.py +0 -0
  49. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/builtin_plugins/subagents/profiles/explorer.json +0 -0
  50. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/__init__.py +0 -0
  51. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/headless.py +0 -0
  52. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/output.py +0 -0
  53. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/root.py +0 -0
  54. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/cli/runner.py +0 -0
  55. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/client.py +0 -0
  56. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/command.py +0 -0
  57. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/context.py +0 -0
  58. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/desktop.py +0 -0
  59. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/event.py +0 -0
  60. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/get_text/__init__.py +0 -0
  61. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/get_text/default_gitignore +0 -0
  62. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/get_text/get_text.py +0 -0
  63. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/get_text/simpler_get_text.py +0 -0
  64. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/hooks.py +0 -0
  65. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/image.py +0 -0
  66. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/latex.py +0 -0
  67. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/mainloop.py +0 -0
  68. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/plugin.py +0 -0
  69. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/prompts/image_generation_system_prompt.txt +0 -0
  70. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/prompts/system_prompt.txt +0 -0
  71. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/provider.py +0 -0
  72. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/runtime.py +0 -0
  73. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/scheduler.py +0 -0
  74. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/scripts/install-system-dependencies.sh +0 -0
  75. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/server/__init__.py +0 -0
  76. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/server/app.py +0 -0
  77. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/server/core.py +0 -0
  78. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/service.py +0 -0
  79. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/sessions.py +0 -0
  80. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/status.py +0 -0
  81. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/stream_utils.py +0 -0
  82. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tool.py +0 -0
  83. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tray.py +0 -0
  84. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/tui/__init__.py +0 -0
  85. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/voice.py +0 -0
  86. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent/worker.py +0 -0
  87. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/dependency_links.txt +0 -0
  88. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/entry_points.txt +0 -0
  89. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/requires.txt +0 -0
  90. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/codex_agent_framework.egg-info/top_level.txt +0 -0
  91. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/dependencies.txt +0 -0
  92. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/setup.cfg +0 -0
  93. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_agent_runtime.py +0 -0
  94. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_ai.py +0 -0
  95. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_browser.py +0 -0
  96. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_builtin_config.py +0 -0
  97. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_cli_headless.py +0 -0
  98. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_cli_root.py +0 -0
  99. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_client.py +0 -0
  100. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_events.py +0 -0
  101. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_get_text_browser.py +0 -0
  102. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_hooks.py +0 -0
  103. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_image_message.py +0 -0
  104. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_local_desktop.py +0 -0
  105. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_memory.py +0 -0
  106. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_planner.py +0 -0
  107. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_scheduler.py +0 -0
  108. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_server.py +0 -0
  109. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_service.py +0 -0
  110. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_tray.py +0 -0
  111. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_utils.py +0 -0
  112. {codex_agent_framework-0.1.22 → codex_agent_framework-0.1.23}/tests/test_worker.py +0 -0
@@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  This project loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and uses semantic versioning where practical.
6
6
 
7
+ ## [0.1.23] - 2026-05-10
8
+ ### Added
9
+ - Add the SDK `Agent.stream(prompt=None)` API for iterating turn events while still exposing the final `AgentTurn` through `.turn`.
10
+ - Add root-level `Agent.add_plugin(plugin)` as a convenience API for registering plugin tools, providers, commands, hooks, and events.
11
+
12
+ ### Changed
13
+ - Rework the README around a faster reader path: compact quick start, clearer Python API examples, grouped extension guidance, and updated runtime/CLI documentation.
14
+ - Change the default runtime directory from `~/.agent_runtime` to `~/.codex-agent` and align tests, services, examples, and ignore rules with the new location.
15
+ - Disable voice by default so SDK agents with OpenAI keys remain text-first unless voice is explicitly enabled.
16
+ - Make bare `codex-agent` attach to an already-running local server when available, otherwise start a temporary TUI-bound server.
17
+ - Improve TUI tool-call display with immediate start/done lines, ordered text flushing before tools, compact status icons, shortened call IDs, and cleaner terminal launch environment handling.
18
+
19
+ ### Fixed
20
+ - Restrict prompt templating to `SystemMessage` content so developer messages, user messages, assistant messages, and tool outputs remain literal.
21
+ - Prevent TUI tool-call start events from being buffered until step completion, allowing long-running tool calls to show immediately.
22
+
23
+ ### Tests
24
+ - Add regression coverage for SDK streaming, root plugin registration, runtime directory defaults, CLI local-server attachment, message templating scope, TUI tool-call ordering/rendering, and terminal environment sanitization.
25
+
7
26
  ## [0.1.22] - 2026-05-10
8
27
  ### Changed
9
28
  - Harden the FastAPI/SSE bridge and Textual TUI streaming path after a stabilization audit: finite SSE read timeouts, batched live deltas, synchronous replay delta flushes, and explicit stale-subscriber replacement shutdowns.
@@ -0,0 +1,649 @@
1
+ Metadata-Version: 2.4
2
+ Name: codex-agent-framework
3
+ Version: 0.1.23
4
+ Summary: A lightweight event-driven Codex agent runtime.
5
+ Author: Baptiste
6
+ License-Expression: MIT
7
+ Keywords: agent,ai,codex,openai,tools
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: audioop-lts; python_version >= "3.13"
19
+ Requires-Dist: beautifulsoup4
20
+ Requires-Dist: codex-backend-sdk
21
+ Requires-Dist: fastapi
22
+ Requires-Dist: filetype
23
+ Requires-Dist: modict
24
+ Requires-Dist: mss
25
+ Requires-Dist: numpy
26
+ Requires-Dist: odfpy
27
+ Requires-Dist: openai
28
+ Requires-Dist: openpyxl
29
+ Requires-Dist: pathspec
30
+ Requires-Dist: pillow
31
+ Requires-Dist: playwright
32
+ Requires-Dist: pydub
33
+ Requires-Dist: pypdf
34
+ Requires-Dist: pynteract
35
+ Requires-Dist: pywinctl
36
+ Requires-Dist: python-docx
37
+ Requires-Dist: PyYAML
38
+ Requires-Dist: regex
39
+ Requires-Dist: requests
40
+ Requires-Dist: rich
41
+ Requires-Dist: textual
42
+ Requires-Dist: tiktoken
43
+ Requires-Dist: trafilatura
44
+ Requires-Dist: uvicorn
45
+ Provides-Extra: dev
46
+ Requires-Dist: build; extra == "dev"
47
+ Requires-Dist: pytest; extra == "dev"
48
+ Dynamic: license-file
49
+
50
+ # codex-agent
51
+
52
+ `codex-agent-framework` is a local-first Python framework for building and running tool-using AI agents.
53
+
54
+ Use it as a ready-to-run terminal assistant, or import `Agent` when you want to build your own workflow in Python.
55
+
56
+ > Early alpha: APIs are still evolving and breaking changes are expected while the architecture settles.
57
+
58
+ ## Quick start
59
+
60
+ Install the package:
61
+
62
+ ```bash
63
+ python -m pip install codex-agent-framework
64
+ ```
65
+
66
+ For the recommended local setup, run:
67
+
68
+ ```bash
69
+ codex-agent bootstrap -- -y
70
+ ```
71
+
72
+ `bootstrap` installs the desktop/browser/tray dependencies, installs the user services, and starts them. It is currently aimed mostly at Debian-like Linux systems. Use an X11 session for the best desktop automation support; Wayland is fine if you do not use the desktop plugin.
73
+
74
+ Open the assistant:
75
+
76
+ ```bash
77
+ codex-agent
78
+ ```
79
+
80
+ If a local agent server is already running, the TUI connects to it. Otherwise `codex-agent` starts a temporary server for that TUI session and shuts it down when the TUI exits.
81
+
82
+ Inside the TUI, start with:
83
+
84
+ ```text
85
+ /help
86
+ /sessions
87
+ /new_session
88
+ /load_session latest
89
+ /compact
90
+ /config
91
+ ```
92
+
93
+ Use `/compact` when a long session needs to reduce its active context. It keeps a backend summary and prunes older raw history from the active session file.
94
+
95
+ Prefer the SDK? Start with this:
96
+
97
+ ```python
98
+ from codex_agent import Agent
99
+
100
+ agent = Agent(session="new")
101
+ turn = agent("Summarize this repository in three practical bullet points.")
102
+
103
+ print(turn.result)
104
+ ```
105
+
106
+ ## Contents
107
+
108
+ - [Python API](#python-api)
109
+ - [Core concepts](#core-concepts)
110
+ - [Extending the agent](#extending-the-agent)
111
+ - [Built-in capabilities](#built-in-capabilities)
112
+ - [Running modes](#running-modes)
113
+ - [Configuration and runtime files](#configuration-and-runtime-files)
114
+ - [Development](#development)
115
+ - [Recent releases](#recent-releases)
116
+ - [Safety notes](#safety-notes)
117
+
118
+ ## Python API
119
+
120
+ ### Minimal agent
121
+
122
+ ```python
123
+ from codex_agent import Agent
124
+
125
+ agent = Agent(session="new", username="Baptiste")
126
+ turn = agent("Summarize this repository in three practical bullet points.")
127
+
128
+ print("completed:", turn.completed)
129
+ print("reason:", turn.reason)
130
+ print("result:", turn.result)
131
+ ```
132
+
133
+ `agent(...)` blocks until the turn completes and returns an `AgentTurn`. Use `turn.result` for the final result; `turn.messages` and `turn.events` contain what happened during the turn.
134
+
135
+ ### Stream events from a turn
136
+
137
+ Use `agent.stream(...)` when you want live events and the final turn:
138
+
139
+ ```python
140
+ from codex_agent import Agent, ResponseContentDeltaEvent
141
+
142
+ agent = Agent(session="new")
143
+ stream = agent.stream("Explain what this project does.")
144
+
145
+ for event in stream:
146
+ if isinstance(event, ResponseContentDeltaEvent):
147
+ print(event.delta, end="", flush=True)
148
+
149
+ turn = stream.turn
150
+ print("\ncompleted:", turn.completed)
151
+ ```
152
+
153
+ `stream.turn` waits for the final `AgentTurn`; it does not expose a partial turn object.
154
+
155
+ You can get a similar effect with the event bus and a normal blocking call:
156
+
157
+ ```python
158
+ from codex_agent import Agent, ResponseContentDeltaEvent
159
+
160
+ agent = Agent(session="new")
161
+
162
+ @agent.on(ResponseContentDeltaEvent)
163
+ def print_delta(event):
164
+ print(event.delta, end="", flush=True)
165
+
166
+ turn = agent("Explain what this project does.")
167
+ print("\ncompleted:", turn.completed)
168
+ ```
169
+
170
+ ### Open an interactive session from Python
171
+
172
+ ```python
173
+ from codex_agent import Agent
174
+
175
+ agent = Agent(session="latest")
176
+ agent.interact()
177
+ ```
178
+
179
+ Voice is disabled by default. Enable it explicitly for a voice session:
180
+
181
+ ```python
182
+ from codex_agent import Agent
183
+
184
+ agent = Agent(
185
+ session="latest",
186
+ openai_api_key="sk-...",
187
+ voice_enabled=True,
188
+ voice="nova",
189
+ )
190
+ agent.interact()
191
+ ```
192
+
193
+ ### Add a tool
194
+
195
+ Tools are actions the model may choose to call.
196
+
197
+ For a tool without parameters, a plain docstring becomes the tool description:
198
+
199
+ ```python
200
+ import subprocess
201
+ from codex_agent import Agent, tool
202
+
203
+ @tool
204
+ def list_changed_files() -> list[str]:
205
+ """Return modified or untracked files in the current git repository."""
206
+ output = subprocess.check_output(["git", "status", "--short"], text=True)
207
+ return [line[3:] for line in output.splitlines() if line.strip()]
208
+
209
+ agent = Agent(session="latest")
210
+ agent.add_tool(list_changed_files)
211
+ ```
212
+
213
+ For a parameterized tool, use a YAML docstring to describe the schema exposed to the model:
214
+
215
+ ```python
216
+ from pathlib import Path
217
+ from codex_agent import Agent, tool
218
+
219
+ @tool
220
+ def read_project_note(path: str):
221
+ """
222
+ description: Read a UTF-8 project note file.
223
+ parameters:
224
+ path:
225
+ type: string
226
+ description: Path to the note file, relative to the current project.
227
+ required:
228
+ - path
229
+ """
230
+ return Path(path).read_text(encoding="utf-8")
231
+
232
+ agent = Agent(session="latest")
233
+ agent.add_tool(read_project_note)
234
+ agent("Look at my project notes and tell me what changed recently.")
235
+ ```
236
+
237
+ ### Add live context
238
+
239
+ Providers inject fresh context before a model call without saving it as permanent conversation history.
240
+
241
+ ```python
242
+ from datetime import datetime
243
+ from zoneinfo import ZoneInfo
244
+ from codex_agent import Agent, provider
245
+
246
+ @provider
247
+ def current_time():
248
+ now = datetime.now(ZoneInfo("Europe/Paris"))
249
+ return f"Current local time: {now:%Y-%m-%d %H:%M:%S %Z}"
250
+
251
+ agent = Agent(session="latest")
252
+ agent.add_provider(current_time)
253
+ agent("Given the current time, should I start a long-running task now?")
254
+ ```
255
+
256
+ ### Add a slash command
257
+
258
+ Commands are explicit user actions triggered with `/name`.
259
+
260
+ ```python
261
+ from codex_agent import Agent, command, get_agent
262
+
263
+ @command
264
+ def repo():
265
+ """Show the active session and current repository hint."""
266
+ agent = get_agent()
267
+ return f"session={agent.current_session_id}; repo=codex-agent"
268
+
269
+ agent = Agent(session="latest")
270
+ agent.add_command(repo)
271
+ print(agent("/repo").result)
272
+ ```
273
+
274
+ ## Core concepts
275
+
276
+ The framework is built around a few extension points:
277
+
278
+ | Concept | What it is for |
279
+ | --- | --- |
280
+ | Session | Saved conversation and agent state. |
281
+ | Turn | One user request plus the model/tool loop needed to answer it. |
282
+ | Tool | An action the model may choose to call. |
283
+ | Provider | Fresh context injected before a response, not saved as chat history. |
284
+ | Command | A user-triggered operation such as `/compact` or `/config`. |
285
+ | Plugin | A bundle of state, tools, providers, commands, events, hooks, and prompt text. |
286
+
287
+ ### Sessions and turns
288
+
289
+ ```python
290
+ Agent(session="new") # fresh session
291
+ Agent(session="latest") # newest saved session
292
+ Agent(session="<session_id>") # specific saved session
293
+ Agent(session="/path/to/session.json") # session file
294
+ ```
295
+
296
+ By default, a turn runs until the agent has completed its tool/model loop. `auto_proceed=False` is an advanced mode for external orchestration: your application can pause after each model step, inspect state, approve or cancel work, and resume explicitly.
297
+
298
+ ```python
299
+ agent = Agent(session="new", auto_proceed=False)
300
+ turn = agent("Please explore the current repo. Use tools if needed.")
301
+
302
+ while not turn.completed and turn.reason == "requires_next_step":
303
+ # External monitoring, approval, logging, cancellation, etc. can happen here.
304
+ turn = agent.resume_turn(turn)
305
+ ```
306
+
307
+ ## Extending the agent
308
+
309
+ Use runtime extensions when you want to customize an installed agent without forking the repository.
310
+
311
+ At startup, the agent scans:
312
+
313
+ ```text
314
+ ~/.codex-agent/plugins/*.py
315
+ ~/.codex-agent/commands/*.py
316
+ ```
317
+
318
+ Files starting with `_` are ignored.
319
+
320
+ A plugin module may expose:
321
+
322
+ - a `Plugin` subclass;
323
+ - a `register(agent)` function;
324
+ - decorated `@tool`, `@provider`, or `@command` callables for small extensions.
325
+
326
+ Direct runtime `tools/` and `providers/` folders are intentionally not loaded. Put simple runtime tools/providers in a plugin module, or use `agent.add_tool()` and `agent.add_provider()` in SDK code.
327
+
328
+ ### Plugin example
329
+
330
+ ```python
331
+ from codex_agent import Agent, Plugin, provider, tool
332
+
333
+ class ProjectNotesPlugin(Plugin):
334
+ name = "project_notes"
335
+ system_prompt = "# Project Notes\nUse project notes when relevant."
336
+
337
+ def __init__(self, agent):
338
+ super().__init__(agent)
339
+ self.notes = []
340
+
341
+ @tool
342
+ def remember_note(self, note: str):
343
+ """
344
+ description: Store a project note that should be available in later turns.
345
+ parameters:
346
+ note:
347
+ type: string
348
+ description: The note to remember. Keep it concise and project-specific.
349
+ required:
350
+ - note
351
+ """
352
+ self.notes.append(note)
353
+ return f"Stored {len(self.notes)} note(s)."
354
+
355
+ @provider
356
+ def project_notes(self):
357
+ if not self.notes:
358
+ return None
359
+ return "Project notes:\n" + "\n".join(f"- {note}" for note in self.notes)
360
+
361
+ agent = Agent(session="latest")
362
+ agent.add_plugin(ProjectNotesPlugin(agent))
363
+ ```
364
+
365
+ ### Runtime plugin example
366
+
367
+ `~/.codex-agent/plugins/git_helpers.py`:
368
+
369
+ ```python
370
+ from datetime import datetime
371
+ from zoneinfo import ZoneInfo
372
+ import subprocess
373
+ from codex_agent import provider, tool
374
+
375
+ @tool
376
+ def current_branch() -> str:
377
+ """Return the current git branch."""
378
+ return subprocess.check_output(
379
+ ["git", "branch", "--show-current"],
380
+ text=True,
381
+ ).strip()
382
+
383
+ @provider
384
+ def current_time():
385
+ now = datetime.now(ZoneInfo("Europe/Paris"))
386
+ return f"Current local time: {now:%Y-%m-%d %H:%M:%S %Z}"
387
+ ```
388
+
389
+ `~/.codex-agent/commands/repo.py`:
390
+
391
+ ```python
392
+ from codex_agent import command, get_agent
393
+
394
+ @command(name="repo")
395
+ def repo(args=""):
396
+ agent = get_agent()
397
+ return f"session={agent.current_session_id}; args={args}"
398
+ ```
399
+
400
+ ### Events and hooks
401
+
402
+ `Agent` exposes an event bus for UIs, automation, and plugins:
403
+
404
+ ```python
405
+ from codex_agent import Agent, MessageAddedEvent, ToolCallStartEvent
406
+
407
+ agent = Agent(session="new")
408
+
409
+ @agent.on(MessageAddedEvent)
410
+ def log_message(event):
411
+ print("message", event.message.type)
412
+
413
+ @agent.on(ToolCallStartEvent)
414
+ def log_tool(event):
415
+ print("tool", event.name)
416
+ ```
417
+
418
+ Plugins and tools may also emit custom events and expose custom hook points:
419
+
420
+ ```python
421
+ from codex_agent import Agent, Event, Plugin, tool
422
+
423
+ class NoteStoredEvent(Event):
424
+ note = ""
425
+
426
+ class NotesPlugin(Plugin):
427
+ name = "notes"
428
+
429
+ @tool
430
+ def remember_note(self, note: str):
431
+ """
432
+ description: Store a note and notify listeners.
433
+ parameters:
434
+ note:
435
+ type: string
436
+ description: Note to store.
437
+ required:
438
+ - note
439
+ """
440
+ context = self.agent.run_hook("notes.before_store", note=note)
441
+ if context.stopped:
442
+ return "Note rejected."
443
+ note = context.payload.note
444
+ self.agent.emit(NoteStoredEvent, note=note)
445
+ return "Note stored."
446
+
447
+ agent = Agent(session="new")
448
+ agent.add_plugin(NotesPlugin(agent))
449
+
450
+ @agent.on(NoteStoredEvent)
451
+ def log_note(event):
452
+ print("stored note:", event.note)
453
+
454
+ @agent.add_hook("notes.before_store")
455
+ def trim_note(context):
456
+ context.payload.note = context.payload.note.strip()
457
+ ```
458
+
459
+ Plugin methods can also subscribe declaratively with `@event_handler(...)` and `@hook_handler(...)`.
460
+
461
+ ## Built-in capabilities
462
+
463
+ The default agent includes practical local tools grouped as plugins:
464
+
465
+ | Area | Examples | Purpose |
466
+ | --- | --- | --- |
467
+ | Files | `read`, `view`, `write`, `edit` | Strict text reads, broad extraction, exact-string edits. |
468
+ | Shell | `bash`, `python` | Shell commands and persistent Python execution. |
469
+ | Memory | `memory_add`, `memory_search`, `/memory_config` | Durable semantic memory and retrieval context. |
470
+ | Planner | `planner_create`, `planner_check` | Persistent named todos surfaced as context. |
471
+ | Scheduler | `scheduler_schedule`, `scheduler_restart_and_wakeup` | Future turns and post-restart continuation. |
472
+ | Browser | `browser_open`, `browser_click`, `browser_fill` | Persistent Playwright/Chromium automation. |
473
+ | Desktop | `desktop_start_session`, `desktop_run_commands` | Screenshot-backed Linux desktop automation. |
474
+ | Subagents | `subagents_run` | Ephemeral child agents from predefined profiles. |
475
+
476
+ Current built-in plugin modules include `files`, `content`, `bash`, `python`, `interface`, `environment`, `memory`, `planner`, `scheduler`, `browser`, `desktop`, and `subagents`.
477
+
478
+ The `subagents` plugin ships an `explorer` profile: a read-only codebase inspection agent.
479
+
480
+ Select built-ins explicitly when you want a smaller agent:
481
+
482
+ ```python
483
+ agent = Agent(
484
+ session="latest",
485
+ builtin_plugins=["files", "content", "bash", "python", "memory", "planner"],
486
+ )
487
+ ```
488
+
489
+ `None` loads all built-ins, `[]` loads none, and an explicit list selects plugin module names.
490
+
491
+ ## Running modes
492
+
493
+ You can ignore this section for normal TUI usage. It is for services, automation, and integrations.
494
+
495
+ | Mode | Entry point | Best for |
496
+ | --- | --- | --- |
497
+ | Embedded Python | `Agent(...)` | Scripts, notebooks, tests, custom applications. |
498
+ | Interactive TUI | `codex-agent` | Daily local assistant usage. |
499
+ | Persistent server | `codex-agent start server` | Long-lived local service used by UIs or scripts. |
500
+ | Headless CLI | `codex-agent run ...` | Automation and shell pipelines. |
501
+ | Process runtime | `codex-agent run --runtime process ...` | One-shot isolated runs without an existing server. |
502
+ | Tray/service setup | `codex-agent bootstrap` | Desktop availability independent of a terminal. |
503
+
504
+ Run a persistent background server:
505
+
506
+ ```bash
507
+ codex-agent start server
508
+ codex-agent open tui
509
+ ```
510
+
511
+ Detached logs are written under `~/.codex-agent/logs/server.log`.
512
+
513
+ Useful headless commands:
514
+
515
+ ```bash
516
+ codex-agent status --json
517
+ codex-agent tools
518
+ codex-agent config get model
519
+ codex-agent run "Run a quick repository health check."
520
+ git diff -- README.md | codex-agent run --stdin "Review this documentation diff."
521
+ codex-agent run --runtime process "Summarize the current project layout."
522
+ codex-agent interrupt "user changed priority"
523
+ ```
524
+
525
+ The local server exposes FastAPI REST/SSE endpoints for health, status, sessions, config, messages, tools, wakeups, live events, replay, turns, interrupts, and restart. The TUI uses SSE, tracks event cursors, replays the latest turn when opened mid-session, and reconnects after server restarts or transient stream loss.
526
+
527
+ ## Configuration and runtime files
528
+
529
+ Configure `Agent` directly:
530
+
531
+ ```python
532
+ from codex_agent import Agent
533
+
534
+ agent = Agent(
535
+ session="latest",
536
+ model="gpt-5.5",
537
+ reasoning_effort="medium",
538
+ verbosity="medium",
539
+ input_token_limit=128000,
540
+ auto_compact=True,
541
+ web_search_enabled=False,
542
+ image_generation_enabled=False,
543
+ builtin_plugins=None, # None = all, [] = none, or explicit plugin names
544
+ custom_plugins=None, # None = all runtime plugins, [] = none
545
+ )
546
+ ```
547
+
548
+ Or update saved config from the CLI:
549
+
550
+ ```bash
551
+ codex-agent config get
552
+ codex-agent config set input_token_limit 128000
553
+ codex-agent config set voice_enabled=true
554
+ codex-agent config set builtin_plugins='["memory", "planner", "scheduler"]'
555
+ codex-agent config set --no-save verbosity low
556
+ ```
557
+
558
+ Saved local state lives in `~/.codex-agent` by default:
559
+
560
+ ```text
561
+ sessions/ persisted conversation histories as JSON
562
+ workfolder/ generated or uploaded working files
563
+ plugins/ user runtime plugins
564
+ commands/ user runtime slash commands
565
+ browser/ persistent browser profiles and screenshots
566
+ logs/ detached server/tray logs
567
+ memory.json durable semantic memory entries
568
+ planner.json persistent named todos
569
+ wakeups.json scheduled autonomous wakeups
570
+ agent_config.json persisted runtime configuration
571
+ ```
572
+
573
+ Override it with:
574
+
575
+ ```bash
576
+ AGENT_RUNTIME_DIR=/tmp/my-codex-agent-runtime codex-agent
577
+ ```
578
+
579
+ ## Development
580
+
581
+ Project layout:
582
+
583
+ ```text
584
+ codex_agent/ Python package
585
+ codex_agent/agent.py Central Agent object and high-level public methods
586
+ codex_agent/mainloop.py Turn loop, assistant calls, tool execution, pending results
587
+ codex_agent/stream.py SDK event stream wrapper around an AgentFuture
588
+ codex_agent/context.py Context assembly and token budgeting
589
+ codex_agent/sessions.py Persistent sessions and compaction
590
+ codex_agent/tool.py Tool model, decorators, and manager
591
+ codex_agent/provider.py Provider decorator and manager
592
+ codex_agent/plugin.py Stateful plugin base class and manager
593
+ codex_agent/command.py Slash command registry and dispatch
594
+ codex_agent/hooks.py Generic runtime hook manager
595
+ codex_agent/event.py Event classes and event bus
596
+ codex_agent/server/ FastAPI REST/SSE bridge package
597
+ codex_agent/tui/ Textual TUI client
598
+ codex_agent/cli/ Root CLI and headless runners
599
+ codex_agent/builtin_plugins/ Built-in capabilities grouped as plugins
600
+ tests/ Test suite
601
+ ```
602
+
603
+ Run checks:
604
+
605
+ ```bash
606
+ python -m pyflakes codex_agent tests
607
+ python -m pytest
608
+ ```
609
+
610
+ The current tree validates at:
611
+
612
+ ```text
613
+ 489 passed
614
+ ```
615
+
616
+ Build distributions:
617
+
618
+ ```bash
619
+ python -m pip install build twine
620
+ rm -rf build dist *.egg-info
621
+ python -m build
622
+ python -m twine check dist/*
623
+ ```
624
+
625
+ ## Recent releases
626
+
627
+ - `0.1.23`: add SDK event streaming with `Agent.stream()`, root `Agent.add_plugin()`, a faster README flow, the `~/.codex-agent` runtime default, text-first voice defaults, safer prompt templating limited to system messages, smarter `codex-agent` local-server attachment, and clearer TUI tool-call progress lines.
628
+ - `0.1.22`: harden FastAPI/SSE and TUI streaming after a stabilization audit; add finite SSE read timeouts, stale-subscriber shutdown, persisted turn-event locking, synchronous replay delta flushes, process-runtime startup guards, isolated event handlers, and shared version metadata.
629
+ - `0.1.21`: add structured `AgentTurn` returns with messages/events, resumable non-terminal turns for `auto_proceed=False`, profile-based subagents, hierarchical message/event types, and internal wakeups as developer messages.
630
+ - `0.1.20`: make runtime plugins the user-facing extension unit for tools/providers/commands, remove legacy direct runtime tool/provider loading, split tool/provider managers, and keep system-prompt templating on an explicit minimal namespace.
631
+
632
+ See [`CHANGELOG.md`](CHANGELOG.md) for the full history.
633
+
634
+ ## Safety notes
635
+
636
+ This project lets an AI assistant act on the local machine. That is useful, but risky.
637
+
638
+ Recommended practices:
639
+
640
+ - Use a dedicated runtime directory for experiments.
641
+ - Review tool calls before enabling autonomous workflows.
642
+ - Avoid running the agent with elevated privileges.
643
+ - Keep secrets out of prompts, logs, committed runtime files, and shared session exports.
644
+ - Treat browser and desktop automation as real user actions.
645
+ - Keep important runtime plugins under version control.
646
+
647
+ ## License
648
+
649
+ MIT. See [LICENSE](LICENSE).