seedagent 0.7.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.
Files changed (89) hide show
  1. seedagent-0.7.0/.gitignore +13 -0
  2. seedagent-0.7.0/LICENSE +21 -0
  3. seedagent-0.7.0/PKG-INFO +355 -0
  4. seedagent-0.7.0/README.md +318 -0
  5. seedagent-0.7.0/coding_agent/__init__.py +169 -0
  6. seedagent-0.7.0/coding_agent/__main__.py +5 -0
  7. seedagent-0.7.0/coding_agent/backups.py +89 -0
  8. seedagent-0.7.0/coding_agent/certificates.py +55 -0
  9. seedagent-0.7.0/coding_agent/cleanup.py +128 -0
  10. seedagent-0.7.0/coding_agent/cli.py +201 -0
  11. seedagent-0.7.0/coding_agent/common.py +190 -0
  12. seedagent-0.7.0/coding_agent/config.py +375 -0
  13. seedagent-0.7.0/coding_agent/context.py +280 -0
  14. seedagent-0.7.0/coding_agent/conversation.py +51 -0
  15. seedagent-0.7.0/coding_agent/credentials.py +56 -0
  16. seedagent-0.7.0/coding_agent/diagnose.py +81 -0
  17. seedagent-0.7.0/coding_agent/errors.py +106 -0
  18. seedagent-0.7.0/coding_agent/guard.py +97 -0
  19. seedagent-0.7.0/coding_agent/history.py +68 -0
  20. seedagent-0.7.0/coding_agent/index.py +390 -0
  21. seedagent-0.7.0/coding_agent/logs.py +133 -0
  22. seedagent-0.7.0/coding_agent/loop.py +301 -0
  23. seedagent-0.7.0/coding_agent/memories.py +98 -0
  24. seedagent-0.7.0/coding_agent/memory.py +210 -0
  25. seedagent-0.7.0/coding_agent/ocr.py +78 -0
  26. seedagent-0.7.0/coding_agent/prompts.py +128 -0
  27. seedagent-0.7.0/coding_agent/schemas.py +887 -0
  28. seedagent-0.7.0/coding_agent/session.py +121 -0
  29. seedagent-0.7.0/coding_agent/signin.py +85 -0
  30. seedagent-0.7.0/coding_agent/skills/ai-engineer/SKILL.md +283 -0
  31. seedagent-0.7.0/coding_agent/skills/azure-cloud-architect/SKILL.md +112 -0
  32. seedagent-0.7.0/coding_agent/skills/backend-engineer/SKILL.md +98 -0
  33. seedagent-0.7.0/coding_agent/skills/database-architect/SKILL.md +85 -0
  34. seedagent-0.7.0/coding_agent/skills/frontend-engineer/SKILL.md +113 -0
  35. seedagent-0.7.0/coding_agent/skills/web-browsing/SKILL.md +62 -0
  36. seedagent-0.7.0/coding_agent/skills.py +137 -0
  37. seedagent-0.7.0/coding_agent/state.py +94 -0
  38. seedagent-0.7.0/coding_agent/tools/__init__.py +181 -0
  39. seedagent-0.7.0/coding_agent/tools/browser.py +238 -0
  40. seedagent-0.7.0/coding_agent/tools/documents.py +814 -0
  41. seedagent-0.7.0/coding_agent/tools/excel_add.py +309 -0
  42. seedagent-0.7.0/coding_agent/tools/excel_look.py +364 -0
  43. seedagent-0.7.0/coding_agent/tools/excel_script.py +236 -0
  44. seedagent-0.7.0/coding_agent/tools/excel_xl.py +370 -0
  45. seedagent-0.7.0/coding_agent/tools/files.py +391 -0
  46. seedagent-0.7.0/coding_agent/tools/git.py +83 -0
  47. seedagent-0.7.0/coding_agent/tools/interaction.py +17 -0
  48. seedagent-0.7.0/coding_agent/tools/mail.py +263 -0
  49. seedagent-0.7.0/coding_agent/tools/network.py +190 -0
  50. seedagent-0.7.0/coding_agent/tools/office.py +151 -0
  51. seedagent-0.7.0/coding_agent/tools/python_runner.py +87 -0
  52. seedagent-0.7.0/coding_agent/tools/sms.py +86 -0
  53. seedagent-0.7.0/coding_agent/tools/web.py +619 -0
  54. seedagent-0.7.0/coding_agent/ui.py +323 -0
  55. seedagent-0.7.0/coding_agent/usage.py +82 -0
  56. seedagent-0.7.0/coding_agent/websessions.py +122 -0
  57. seedagent-0.7.0/pyproject.toml +70 -0
  58. seedagent-0.7.0/tests/conftest.py +85 -0
  59. seedagent-0.7.0/tests/fake_xlwings.py +309 -0
  60. seedagent-0.7.0/tests/test_browser.py +42 -0
  61. seedagent-0.7.0/tests/test_bundled_skills.py +21 -0
  62. seedagent-0.7.0/tests/test_certificates.py +24 -0
  63. seedagent-0.7.0/tests/test_cleanup.py +99 -0
  64. seedagent-0.7.0/tests/test_credentials.py +57 -0
  65. seedagent-0.7.0/tests/test_documents.py +559 -0
  66. seedagent-0.7.0/tests/test_errors.py +113 -0
  67. seedagent-0.7.0/tests/test_example_env.py +52 -0
  68. seedagent-0.7.0/tests/test_excel_add.py +217 -0
  69. seedagent-0.7.0/tests/test_excel_backends.py +260 -0
  70. seedagent-0.7.0/tests/test_excel_script.py +215 -0
  71. seedagent-0.7.0/tests/test_files.py +191 -0
  72. seedagent-0.7.0/tests/test_history.py +53 -0
  73. seedagent-0.7.0/tests/test_index.py +173 -0
  74. seedagent-0.7.0/tests/test_logs.py +75 -0
  75. seedagent-0.7.0/tests/test_loop.py +322 -0
  76. seedagent-0.7.0/tests/test_mail.py +231 -0
  77. seedagent-0.7.0/tests/test_memories.py +47 -0
  78. seedagent-0.7.0/tests/test_network_and_terminal.py +69 -0
  79. seedagent-0.7.0/tests/test_office.py +163 -0
  80. seedagent-0.7.0/tests/test_provider.py +166 -0
  81. seedagent-0.7.0/tests/test_read_folders.py +118 -0
  82. seedagent-0.7.0/tests/test_register_tool.py +104 -0
  83. seedagent-0.7.0/tests/test_runtime_config.py +254 -0
  84. seedagent-0.7.0/tests/test_sandbox_and_git.py +80 -0
  85. seedagent-0.7.0/tests/test_signin.py +99 -0
  86. seedagent-0.7.0/tests/test_sms.py +85 -0
  87. seedagent-0.7.0/tests/test_streaming_ui.py +67 -0
  88. seedagent-0.7.0/tests/test_usage.py +53 -0
  89. seedagent-0.7.0/tests/test_web.py +427 -0
@@ -0,0 +1,13 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .env
5
+ candidatures/
6
+ etablissements/
7
+ logement/
8
+ scripts/test_coding_agent.py
9
+ shortlist_appartements_strasbourg.md
10
+ tomodify
11
+ top.txt
12
+ scripts/prompt_for_claude_code.md
13
+ test.txt
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DemePS
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,355 @@
1
+ Metadata-Version: 2.5
2
+ Name: seedagent
3
+ Version: 0.7.0
4
+ Summary: A coding and document agent on Claude (Azure / Microsoft Foundry): tools, safety rules, memory and context management, usable from the terminal or as a library
5
+ Project-URL: Homepage, https://github.com/DemePS/CodeAgent
6
+ Project-URL: Source, https://github.com/DemePS/CodeAgent
7
+ Project-URL: Issues, https://github.com/DemePS/CodeAgent/issues
8
+ Author: DemePS
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,anthropic,azure,claude,excel,foundry,pdf
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Topic :: Office/Business :: Financial :: Spreadsheet
18
+ Classifier: Topic :: Software Development
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: anthropic<1,>=0.125.0
21
+ Requires-Dist: azure-identity-broker<2,>=1.3.0; sys_platform == 'win32'
22
+ Requires-Dist: azure-identity<2,>=1.25.3
23
+ Requires-Dist: httpx<1,>=0.28.1
24
+ Requires-Dist: openpyxl<4,>=3.1.5
25
+ Requires-Dist: pillow>=10
26
+ Requires-Dist: pypdf<7,>=6.19.0
27
+ Requires-Dist: pypdfium2<5,>=4.30
28
+ Requires-Dist: pytesseract<1,>=0.3.10
29
+ Requires-Dist: python-dotenv<2,>=1.1.1
30
+ Requires-Dist: truststore<1,>=0.10.0
31
+ Provides-Extra: browser
32
+ Requires-Dist: playwright<2,>=1.63.0; extra == 'browser'
33
+ Provides-Extra: excel
34
+ Requires-Dist: xlwings<1,>=0.33; extra == 'excel'
35
+ Provides-Extra: pdf-image
36
+ Description-Content-Type: text/markdown
37
+
38
+ # CodeAgent
39
+
40
+ A document and coding agent. It reads and edits files, Excel workbooks and PDFs (scans included) in a project
41
+ folder, searches a library of documents, browses the web, writes mail drafts and code, asks before every
42
+ change, and remembers what it learned about each project. The model is Claude (Anthropic's API, or your own
43
+ Azure subscription through Microsoft Foundry) or DeepSeek. Use it from the terminal, or as a library to build
44
+ your own tool on top of it (a desktop app that fills Excel workbooks from invoices, a voice assistant over
45
+ a library of PDFs...).
46
+
47
+ ```bash
48
+ pip install seedagent
49
+ ```
50
+
51
+ Or from a clone of this repository: `uv sync` installs the package and the `coding-agent` command in `.venv` (`uv run coding-agent`), and
52
+ `uv sync --all-extras` adds the browser and the Excel backend. An application built on it just runs `uv sync` too: its own `pyproject.toml`
53
+ and `uv.lock` say which version of the engine to fetch.
54
+
55
+ The package `seedagent` installs the `coding_agent` Python package and the `coding-agent` command (also available as `seedagent`).
56
+ Python 3.10 or later; Windows, macOS and Linux.
57
+
58
+ ## Configure
59
+
60
+ Environment variables, or a `.env` file in the folder you run from (or `~/.coding-agent/.env`):
61
+
62
+ | Variable | Meaning |
63
+ |---|---|
64
+ | `ANTHROPIC_FOUNDRY_ENDPOINT` | `https://<resource>.services.ai.azure.com/anthropic` |
65
+ | `ANTHROPIC_FOUNDRY_DEPLOYMENT` | your Claude deployment name |
66
+ | `ANTHROPIC_FOUNDRY_API_KEY` | an API key; leave unset to sign in with your Microsoft work account |
67
+
68
+ Without an API key, the agent signs in with the account of your Windows session, a developer's
69
+ `az login`, or else the Microsoft sign-in page (once; the account is remembered).
70
+
71
+ **Without Azure**, use Anthropic's own API: leave `ANTHROPIC_FOUNDRY_ENDPOINT` unset and set
72
+
73
+ | Variable | Meaning |
74
+ |---|---|
75
+ | `ANTHROPIC_API_KEY` | an API key from [console.anthropic.com](https://console.anthropic.com) |
76
+ | `ANTHROPIC_MODEL` | a model ID (default `claude-sonnet-5`) |
77
+
78
+ Models: `claude-sonnet-5` (the default, $2/$10 per million input/output tokens), `claude-sonnet-5-5` (same price), `claude-haiku-4-5`
79
+ ($1/$5, the cheapest; no effort setting, weaker with tools; good for the two background models `AGENT_MEMORY_MODEL` and
80
+ `AGENT_COMPACT_MODEL`), `claude-opus-5-5` ($4/$20), `claude-opus-5` ($5/$25) and `claude-fable-5-1` ($10/$50, its thinking cannot be turned off).
81
+
82
+ **Thinking and effort** (cost and speed), for the agent's own requests:
83
+
84
+ | Variable | Meaning |
85
+ |---|---|
86
+ | `CODEAGENT_THINKING` | thinking before the answer: `off` (the default), `adaptive`, `between_tools` or `disabled` |
87
+ | `CODEAGENT_EFFORT` | how much the model thinks and writes: `medium` (the default), `low`, `high`, `xhigh`, `max`, or `default` (nothing is sent: the model's own default applies) |
88
+
89
+ `off` means the lowest setting the model accepts: `disabled`, `between_tools` on `claude-sonnet-5-5` (it answers 400 to `disabled`), `adaptive` on
90
+ `claude-opus-5-5` (it answers 400 to both), and
91
+ no thinking field at all on `claude-fable-*` (its thinking cannot be turned off). On Foundry the model is a deployment name, so `off` may guess
92
+ wrong: name `between_tools` or `disabled` yourself. `between_tools` does not work with effort `xhigh` or `max`, and `claude-haiku-*` has no effort
93
+ setting (none is sent). A value that is not allowed is explained, never replaced. An application can also call `configure(effort=...)`.
94
+ `coding-agent --check` shows the thinking and effort it sends. `example.env` lists every variable the agent reads: copy it to `.env`.
95
+
96
+ A Foundry endpoint always wins: with `ANTHROPIC_FOUNDRY_ENDPOINT` set, the agent uses Foundry even if
97
+ `ANTHROPIC_API_KEY` is also set.
98
+
99
+ ### DeepSeek instead of Claude
100
+
101
+ DeepSeek offers an Anthropic-compatible API (`https://api.deepseek.com/anthropic`), so the same client and the same tools work with a
102
+ DeepSeek model. Set `DEEPSEEK_API_KEY` (and nothing else: no `ANTHROPIC_API_KEY`, no Foundry endpoint), or `CODEAGENT_PROVIDER=deepseek` to
103
+ choose it over them. `CODEAGENT_PROVIDER=claude` does the opposite: Claude (Anthropic's API or Foundry) is used even when a DeepSeek key is set. The model is `deepseek-flash` by default; `ANTHROPIC_MODEL=deepseek-v4-pro` selects the larger one. Setting
104
+ `ANTHROPIC_API_KEY` to a DeepSeek key with `ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic` also works and is recognised.
105
+ `coding-agent --check` tests the connection.
106
+
107
+ What DeepSeek does not take, and what the agent does about it: no `web_search` tool (it is left out, `Web search: off`); no `cache_control`
108
+ (DeepSeek caches by itself); no PDF `document` blocks, so `read_pdf` sends pages as rendered images instead (pypdfium2) and scans are read
109
+ by OCR or by looking at the page; thinking is sent as `disabled` for `CODEAGENT_THINKING=off`. `deepseek-flash` looks at images;
110
+ `deepseek-v4-pro` does not (it answers "unsupported image"): the tools that return an image are then not offered and `read_pdf` has no visual
111
+ mode (`AGENT_VISION=on|off` overrides the list for a model that is not in it). Set `AGENT_CONTEXT_WINDOW` to the model's real window (the
112
+ default is 200,000 tokens). An application can hand the key over without any environment variable: `configure(api_key=..., model=...)`.
113
+
114
+ ## Use it in the terminal
115
+
116
+ ```bash
117
+ coding-agent -d path/to/project "Add input validation to the CLI"
118
+ coding-agent -d path/to/project # interactive
119
+ coding-agent -d path/to/project -r # resume the last conversation
120
+ coding-agent -d path/to/project --read D:/docs --read //server/share # also read (never write) other folders
121
+ coding-agent --check # Claude not answering? test each step of a call
122
+ coding-agent --help
123
+ ```
124
+
125
+ In the interactive mode, the up arrow at the `You:` prompt recalls earlier questions, also from earlier
126
+ runs (kept in `~/.coding-agent/history`; needs `readline`: Linux, macOS, WSL; the Windows console recalls
127
+ the questions of the running session by itself).
128
+
129
+ ## Use it as a library
130
+
131
+ ```python
132
+ from coding_agent import session
133
+ from coding_agent.ui import TerminalUI # or your own UI (subclass coding_agent.ui.UI)
134
+
135
+ session.open_project("path/to/folder", ui=TerminalUI(),
136
+ tools=["read_excel", "edit_excel", "read_pdf", "ask_human"], # optional subset
137
+ system_prompt=None) # or your own instructions
138
+ ok, message = session.check_connection() # can Claude be reached?
139
+ session.send("Fill costs.xlsx from invoice.pdf")
140
+ session.close()
141
+ ```
142
+
143
+ `session.open_project(..., excel_first=True)` (for an application that fills workbooks) refuses `read_pdf`
144
+ until `read_excel` has run, when the instruction mentions a spreadsheet; it is off by default.
145
+
146
+ An application that fills one workbook can also set, after `open_project`: `state.excel_writable = {path}` (no other workbook can be changed
147
+ or created), `state.excel_protect_formulas = True` (a formula can be neither replaced nor cleared), and `state.excel_edit_sheets[path] = {"Sheet1"}`
148
+ (only those sheets). They are checked by the tool, not asked of the model.
149
+
150
+ `session.stop()` stops the running instruction from another thread (e.g. a Stop button);
151
+ `session.add_read_folder(path)` lets the agent read (never write) another folder. Every approval,
152
+ question and progress message goes through the UI object, so a web or desktop front end can show them.
153
+
154
+ ### Your own tools
155
+
156
+ An application adds a tool of its own without changing the package:
157
+
158
+ ```python
159
+ import coding_agent
160
+
161
+ def say_hello(who: str, loud: bool = False) -> str: # called as handler(**arguments)
162
+ return f"Hello {who}{'!' if loud else ''}"
163
+
164
+ coding_agent.register_tool(
165
+ {"name": "say_hello", "description": "Greet someone.",
166
+ "input_schema": {"type": "object", "properties": {"who": {"type": "string"}, "loud": {"type": "boolean"}}, "required": ["who"]}},
167
+ say_hello)
168
+ session.open_project(folder, ui=ui, tools=["read_file", "say_hello"]) # a tool is offered only when the session lists it
169
+ ```
170
+
171
+ The handler gets one keyword argument per property of the `input_schema` and returns a string or a list of content blocks
172
+ (`{"type": "text", ...}`, `{"type": "image", ...}`). To report a failure Claude should see, it raises `coding_agent.common.ToolError`; any other
173
+ exception also reaches Claude as an error result and does not stop the agent. It runs in the agent's thread and can use `coding_agent.state`
174
+ (`state.ui`, `state.workspace`). CodeAgent's path checks and confirmations guard only its own tools: what the handler does is the application's
175
+ responsibility (to read a file the way the built-in tools do, `coding_agent.common.resolve_readable(path)` applies the same rules). A built-in
176
+ tool cannot be replaced, registering the same handler twice does nothing, and a second handler under a taken name is an error.
177
+
178
+ ## Tools
179
+
180
+ 45 tools; an application offers the subset it wants (`session.open_project(tools=[...])`).
181
+
182
+ | Group | Tools |
183
+ |---|---|
184
+ | Files | `read_file`, `write_file`, `edit_file`, `list_directory`, `change_directory`, `grep`, `copy_path`, `delete_file`, `delete_folder` |
185
+ | Documents | `read_pdf`, `search_pdf`, `search_library`, `view_image`, `read_word`, `read_powerpoint` |
186
+ | Excel | `read_excel`, `edit_excel`, `view_excel`, `format_excel`, `add_chart`, `add_table`, `add_pivot_table`, `restore_backup`, `run_python_excel` |
187
+ | Web | `web_search`, `web_open`, `web_click`, `web_type`, `web_back`, `web_page`, `web_look`, `screenshot_page`, `web_sign_in`, `web_set_token`, `web_close`, `download_file` |
188
+ | Mail and SMS | `mail_login`, `mail_draft`, `send_mail`, `send_sms` |
189
+ | Code | `run_python` (sandboxed), `git` (read-only), `clone_repo` |
190
+ | Other | `load_skill`, `ask_human` |
191
+
192
+ `read_file` reads UTF-8 and, failing that, Windows-1252 (the usual export of Excel and French accounting software; the result says so).
193
+ `grep` cuts a matching line at 300 characters and bounds its whole result, so a minified file cannot flood the conversation.
194
+
195
+ ### Documents, scans and the library
196
+
197
+ - `read_pdf` reads **text** by default (page ranges). Its **visual** mode (pages rendered as images, at most 20 per call) is allowed once a
198
+ text read happened in the conversation, to check what a scan or a table really shows; names, dates and amounts taken from a scan should be
199
+ checked that way. A model that cannot see images gets no visual mode.
200
+ - Scanned pages are read by **OCR** (tesseract and its language packs must be installed); the text is kept in `AGENT_OCR_DIR` so a page is
201
+ read once. `coding-agent --ocr PDF...` does it ahead of time.
202
+ - `search_library` searches a library of PDFs, Word and PowerPoint files and text files (the read-only folders and the project) through a full-text index
203
+ (SQLite FTS5; alternatives with `a | b | c`, ranked by the words found). Files that are new or changed are indexed on the way, up to a
204
+ size; bigger ones, and a first indexing with OCR, are done once with `coding-agent --index FOLDER...` (`AGENT_INDEX_DIR` moves the index).
205
+ - `read_word` (.docx: paragraphs and tables) and `read_powerpoint` (.pptx: slides and speaker notes) read the text only, with no extra
206
+ dependency; a long document is read in parts with `start`, a slide alone with `slide`. Both are in the search index (a slide is a page; a
207
+ Word file is cut in blocks, located by character). A picture inside is not read.
208
+ - `read_pdf`, `read_file`, `search_library` and `grep` also read the folders given with `--read` / `session.add_read_folder` (never write).
209
+
210
+ ### Browsing the web
211
+
212
+ `web_search` finds pages; `web_open` reads one in a hidden browser that stays open, and lists its text
213
+ and its links, buttons and fields with numbers. The agent goes through a site with `web_click 3` and
214
+ `web_type 5 "weather paris" submit`, reads long pages with `web_page`, goes back with `web_back`, sees
215
+ the page with `web_look` and ends with `web_close`. It needs Playwright and a browser, like
216
+ `screenshot_page` (`uv sync --extra browser`, then `playwright install chromium`; `coding-agent
217
+ --check-browser` tests it).
218
+
219
+ What keeps it safe (in the tools, not only in the prompt):
220
+
221
+ - The first visit to a public site asks you, with the full URL (`[a]ll sites for this session` stops the
222
+ questions until the session ends; `AGENT_WEB_APPROVE=off` never asks, for unattended runs); after that
223
+ the agent can click and type on that site. Links to other sites are refused until the agent opens them with `web_open`,
224
+ which asks you. localhost, private addresses and workspace HTML files need no question.
225
+ - It never types into password, sign-in or payment fields. When a site needs you signed in, `web_sign_in` opens
226
+ a visible window where you type the password yourself; the agent never sees it and keeps only the session
227
+ (cookies) of that site, for 30 days (`AGENT_WEB_SESSION_DAYS`), in `~/.coding-agent/web-sessions` (owner-only
228
+ files). `coding-agent --forget-logins` deletes them (`--forget-logins SITE` for one). A saved session is as
229
+ good as a password until it expires: keep it for sites you are comfortable with.
230
+ - A form that sends data (POST), by a button or by pressing Enter, shows what it sends and asks first.
231
+ - Downloads are blocked, metadata addresses are refused, and nothing is kept on disk (apart from sign-ins you made with `web_sign_in`): cookies and
232
+ history end with the session (`web_close`, or the program ending).
233
+ - The page text reaches Claude marked as untrusted content, and the tools say that pages cannot give
234
+ it instructions.
235
+
236
+ Limits: content inside frames and shadow DOM is not listed, nothing is drawn on a canvas for the text
237
+ view (use `web_look`), and a site that blocks automated browsers will block this one too.
238
+
239
+ ### Excel: two backends
240
+
241
+ Who changes, formats and renders workbooks is set by `AGENT_EXCEL_BACKEND`:
242
+
243
+ | | `openpyxl` | `xlwings` (`uv sync --extra excel`) |
244
+ |---|---|---|
245
+ | Runs on | anywhere | Windows or macOS with Excel installed |
246
+ | Saving | rewrites the file: charts, pictures, pivot tables can be damaged (you are warned first) | Excel saves: nothing is lost |
247
+ | Formulas after an edit | old results until the file is opened in Excel | recalculated at once |
248
+ | `view_excel` | a drawing of the cells (needs the `browser` extra); charts listed, not drawn | what Excel prints, charts included |
249
+ | A workbook open in Excel | refused (locked) | written in that window, if it has no unsaved changes |
250
+ | `add_chart`, `add_table` | written by openpyxl | added by Excel |
251
+ | `add_pivot_table` | refused (openpyxl cannot build them) | built by Excel |
252
+
253
+ `auto` (the default) uses xlwings when it is installed and Excel can be started, else openpyxl.
254
+ Reading (`read_excel`) is the same in both: it never changes the file, lists the charts, pictures,
255
+ tables and pivot tables of a sheet, and shows a long cell whole when that one cell is read.
256
+ `scripts/compare_excel_backends.py` runs the same edits, formatting and views with both backends and
257
+ reports what each kept (run it on a PC with Excel: `uv run --extra excel --extra browser python
258
+ scripts/compare_excel_backends.py [your.xlsx ...]`).
259
+
260
+ ### Excel scripts (`run_python_excel`)
261
+
262
+ For what no Excel tool does, the agent has `run_python_excel`: a Python
263
+ script run with Excel (xlwings backend only) on a workbook, which it gets as `book`. Excel can do far
264
+ more than the `run_python` sandbox can see (run macros, start programs, open and save any file), so:
265
+
266
+ - the script is checked before it runs, and refused if it uses macros (`Run`, `Evaluate`,
267
+ `VBProject`, `ExecuteExcel4Macro`...), programs or links (`Shell`, `FollowHyperlink`, DDE
268
+ formulas such as `=cmd|...`), other files or workbooks (`save`, `SaveAs`, `Open`, `books`,
269
+ `app`, `Application`, `Parent`), external data (`QueryTables`, `WEBSERVICE`), imports beyond
270
+ `math`, `datetime`, `re`, `collections`... , or ways around the check (`eval`, `exec`, `getattr`
271
+ with a computed name, `_private` attributes);
272
+ - you approve the script (unless autonomous mode is on), and a backup of the workbook is kept first
273
+ (`restore_backup` undoes it);
274
+ - it runs in its own invisible Excel with macros forced off and events off, inside the `run_python`
275
+ sandbox; macros it adds are refused and the workbook is put back;
276
+ - you see what it changed: cells, sheets, charts, tables, pivot tables.
277
+
278
+ The check reads the script; it cannot prove what Excel will do. An application that passes its own
279
+ list of tools (`session.open_project(tools=[...])`) does not get it unless it lists it, and it is
280
+ refused in applications that restrict edits (chosen sheets, protected formulas, no formatting).
281
+
282
+ ## Safety
283
+
284
+ - It writes only inside the project folder. Reading elsewhere: in the terminal the agent asks you the first time it wants to read a folder outside the project (`Allow the agent to read (never change) files in ...?`), and remembers the answer for the session; folders given with `--read` need no question. Keys and settings (`~/.ssh`, `~/.aws`, `~/.azure`, `~/.coding-agent`, `.env` files, `*.pem`, `*.key`...) are never read. An application built on the package keeps reading limited to what it was given.
285
+ - Every file or workbook change is shown (a diff, or a cell-by-cell table) and waits for your
286
+ approval; a copy of the previous version of each workbook is kept in `~/.coding-agent/backups/` for 3 days,
287
+ and `restore_backup` puts one back ("undo your changes to costs.xlsx"). Applications can list and
288
+ restore them with `coding_agent.backups` (`versions()`, `restore()`).
289
+ - Deleting always asks, even in autonomous mode; downloads and clones always ask; the agent cannot
290
+ modify its own files; `run_python` cannot start processes or delete files.
291
+ - **No secret reaches code the model wrote.** `run_python` and Excel scripts run with an environment from which every variable that says
292
+ it is a secret (`*KEY*`, `*TOKEN*`, `*SECRET*`, `*PASSWORD*`, `*AUTH*`), the variables of cloud and model services (`ANTHROPIC_*`,
293
+ `DEEPSEEK_*`, `AZURE_*`, `AWS_*`, `GITHUB_*`...) and any copy of an API key are removed, and the output of the script has those values
294
+ hidden. A document that steers the model cannot make it print your keys.
295
+ - The agent never reads `~/.coding-agent` (credentials and its own settings), so a knowledge folder must live elsewhere.
296
+
297
+ ## What stays on your machine
298
+
299
+ Everything is in `~/.coding-agent` (`$HOME`, or your user folder on Windows), cleaned automatically
300
+ (`coding_agent/cleanup.py`): once per process, at the start of `coding-agent` and the first time an application
301
+ opens a project (`session.open_project`). `AGENT_CLEANUP=off` switches that off; an application that runs for
302
+ weeks (a server) can call `coding_agent.cleanup.run()` itself, daily (a call counts as the run):
303
+
304
+ | What | Where | Kept |
305
+ |---|---|---|
306
+ | Copies of workbooks before each change | `backups/` | 3 days (`AGENT_BACKUP_DAYS`) |
307
+ | What the agent learned about each project | `memory/<project>-<code>/` | notes capped in size; deleted after 90 days unused (`AGENT_MEMORY_DAYS`) |
308
+ | The saved conversation (`--resume`) | `memory/<project>-<code>/conversation.json` | 30 days (`AGENT_CONVERSATION_DAYS`) |
309
+
310
+ `AGENT_MEMORY=off` stops the agent from writing memory at all.
311
+
312
+ For developers, to see and delete what the agent remembers:
313
+
314
+ ```bash
315
+ coding-agent --memories # every project's memory: name, last used, size, notes
316
+ coding-agent --memories myapp # one project's notes, in full
317
+ coding-agent --forget myapp # delete one project's memory (asks first)
318
+ coding-agent --forget . -d path # the memory of that project folder
319
+ coding-agent --forget all # delete every project's memory (asks first)
320
+ ```
321
+
322
+ ## Development
323
+
324
+ ```bash
325
+ uv sync --all-extras # the exact versions the tests ran with (uv.lock), with the browser and Excel extras
326
+ uv run playwright install chromium # the browser tools and their tests need it
327
+ uv run pytest
328
+ uv build # dist/seedagent-<version>.tar.gz and .whl
329
+ ```
330
+
331
+ The CI (`.github/workflows/package.yml`) runs the same on Linux and Windows, Python 3.10 and 3.14, with every extra and Chromium
332
+ installed, then installs the built wheel in a fresh environment and runs the tests there. A test must not depend on a `.env`, on the
333
+ order of files or on the repository layout (the wheel's tests run from a copy of `tests/`).
334
+
335
+ ## Releasing (maintainers)
336
+
337
+ The workflow (`.github/workflows/package.yml`) publishes to PyPI by trusted publishing (no token stored). The project is `seedagent`; its
338
+ publisher on pypi.org is owner `DemePS`, repository `CodeAgent`, workflow `package.yml`, environment `pypi` (also an environment `pypi` in
339
+ the repository's settings). PyPI refuses a name that equals an existing one once `-`, `_` and `.` are removed (`codeagent` was refused:
340
+ `code-agent` exists), so check a new name against the full list before registering it.
341
+
342
+ To publish a version, tag the commit whose `pyproject.toml` has that version, with CI green, and push the tag:
343
+
344
+ ```bash
345
+ git fetch origin
346
+ git tag -a v0.7.0 origin/main -m "v0.7.0"
347
+ git push origin v0.7.0
348
+ ```
349
+
350
+ The tag runs the tests and the build, publishes to PyPI and creates a GitHub Release. A tag whose version differs from `pyproject.toml` is
351
+ refused. A published version can never be replaced: fix forward with a new version. Applications then depend on `seedagent==<version>`.
352
+
353
+ ## License
354
+
355
+ MIT (see LICENSE).