mazu 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.
Files changed (48) hide show
  1. mazu-0.1.0/.gitignore +47 -0
  2. mazu-0.1.0/LICENSE +21 -0
  3. mazu-0.1.0/PKG-INFO +259 -0
  4. mazu-0.1.0/README.md +229 -0
  5. mazu-0.1.0/mazu/__init__.py +1 -0
  6. mazu-0.1.0/mazu/agent/__init__.py +0 -0
  7. mazu-0.1.0/mazu/agent/autonomous.py +226 -0
  8. mazu-0.1.0/mazu/agent/context.py +26 -0
  9. mazu-0.1.0/mazu/agent/council.py +151 -0
  10. mazu-0.1.0/mazu/agent/interaction.py +14 -0
  11. mazu-0.1.0/mazu/agent/loop.py +176 -0
  12. mazu-0.1.0/mazu/agent/prompts.py +50 -0
  13. mazu-0.1.0/mazu/agent/session.py +48 -0
  14. mazu-0.1.0/mazu/banner.py +33 -0
  15. mazu-0.1.0/mazu/checkpoint/__init__.py +0 -0
  16. mazu-0.1.0/mazu/checkpoint/manager.py +169 -0
  17. mazu-0.1.0/mazu/checkpoint/store.py +54 -0
  18. mazu-0.1.0/mazu/cli.py +386 -0
  19. mazu-0.1.0/mazu/config.py +45 -0
  20. mazu-0.1.0/mazu/llm/__init__.py +0 -0
  21. mazu-0.1.0/mazu/llm/client.py +110 -0
  22. mazu-0.1.0/mazu/llm/error_mapping.py +36 -0
  23. mazu-0.1.0/mazu/llm/errors.py +21 -0
  24. mazu-0.1.0/mazu/llm/pricing.py +29 -0
  25. mazu-0.1.0/mazu/llm/providers/__init__.py +0 -0
  26. mazu-0.1.0/mazu/llm/providers/anthropic_provider.py +82 -0
  27. mazu-0.1.0/mazu/llm/providers/base.py +31 -0
  28. mazu-0.1.0/mazu/llm/providers/deepseek_provider.py +10 -0
  29. mazu-0.1.0/mazu/llm/providers/openai_compatible.py +186 -0
  30. mazu-0.1.0/mazu/llm/providers/openai_provider.py +6 -0
  31. mazu-0.1.0/mazu/llm/retry.py +26 -0
  32. mazu-0.1.0/mazu/llm/types.py +8 -0
  33. mazu-0.1.0/mazu/memory/__init__.py +0 -0
  34. mazu-0.1.0/mazu/memory/bm25.py +52 -0
  35. mazu-0.1.0/mazu/memory/extraction.py +107 -0
  36. mazu-0.1.0/mazu/memory/retrieval.py +110 -0
  37. mazu-0.1.0/mazu/memory/schema.sql +25 -0
  38. mazu-0.1.0/mazu/memory/store.py +172 -0
  39. mazu-0.1.0/mazu/skills/__init__.py +0 -0
  40. mazu-0.1.0/mazu/skills/manager.py +129 -0
  41. mazu-0.1.0/mazu/tools/__init__.py +0 -0
  42. mazu-0.1.0/mazu/tools/base.py +24 -0
  43. mazu-0.1.0/mazu/tools/fs.py +140 -0
  44. mazu-0.1.0/mazu/tools/memory_tools.py +105 -0
  45. mazu-0.1.0/mazu/tools/registry.py +17 -0
  46. mazu-0.1.0/mazu/tools/shell.py +60 -0
  47. mazu-0.1.0/mazu/tools/skill_tools.py +91 -0
  48. mazu-0.1.0/pyproject.toml +57 -0
mazu-0.1.0/.gitignore ADDED
@@ -0,0 +1,47 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ *.egg
7
+ build/
8
+ dist/
9
+ .eggs/
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ env/
15
+ ENV/
16
+
17
+ # Mazu runtime state (per-project memory, checkpoints, skills) — local to each
18
+ # machine/project, never meant to be committed. `mazu init` also writes this entry
19
+ # into a project's own .gitignore for the same reason.
20
+ .mazu/
21
+
22
+ # Secrets / local config — API keys must only ever live in environment variables
23
+ # or ~/.mazu/config.toml (outside the repo), never in a tracked file.
24
+ .env
25
+ .env.*
26
+ *.pem
27
+ *.key
28
+ config.toml
29
+
30
+ # Test / coverage artifacts
31
+ .pytest_cache/
32
+ .coverage
33
+ .coverage.*
34
+ htmlcov/
35
+ .tox/
36
+ .mypy_cache/
37
+ .ruff_cache/
38
+
39
+ # Editors / OS
40
+ .vscode/
41
+ .idea/
42
+ *.swp
43
+ .DS_Store
44
+ Thumbs.db
45
+
46
+ # Claude Code's own local session state — not part of the project
47
+ .claude/
mazu-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Turgut Sofuyev
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.
mazu-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,259 @@
1
+ Metadata-Version: 2.4
2
+ Name: mazu
3
+ Version: 0.1.0
4
+ Summary: A memory-augmented, checkpointable coding agent CLI.
5
+ Project-URL: Homepage, https://github.com/turgutino/Mazu
6
+ Project-URL: Repository, https://github.com/turgutino/Mazu
7
+ Project-URL: Issues, https://github.com/turgutino/Mazu/issues
8
+ Author-email: Turgut Sofuyev <turgut.sofuyev@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,ai,anthropic,cli,coding-agent,deepseek,llm,memory,openai
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development
22
+ Classifier: Topic :: Software Development :: Build Tools
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: anthropic>=0.40.0
26
+ Requires-Dist: click>=8.1
27
+ Provides-Extra: openai
28
+ Requires-Dist: openai>=1.0; extra == 'openai'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Mazu
32
+
33
+ **A memory-augmented, checkpointable coding agent CLI.** Open source, runs entirely on your own machine, works with Anthropic, OpenAI, or DeepSeek.
34
+
35
+ Most coding agents forget everything the moment the session ends. Mazu doesn't. It keeps a real, queryable memory of your project — decisions, conventions, mistakes — that persists across sessions and gets surfaced automatically. And because every autonomous step is checkpointed (code + memory + conversation, together), you can let it run longer and less-supervised without losing the ability to undo it.
36
+
37
+ ```
38
+ ███╗ ███╗
39
+ ████╗ ████║ A Z U
40
+ ██╔████╔██║ ══════════════════════════════
41
+ ██║╚██╔╝██║ memory-augmented coding agent
42
+ ██║ ╚═╝ ██║ persistent memory · checkpoints · skills · multi-model
43
+ ╚═╝ ╚═╝
44
+ ```
45
+
46
+ ## What makes Mazu different
47
+
48
+ Compared to typical coding-agent CLIs, which reset context every session and rely on a static instructions file:
49
+
50
+ 1. **Persistent structured memory.** Decisions, conventions, and mistakes made on a project are written to a local SQLite database, ranked by local BM25 (zero API cost — no embedding calls) against your current task, and automatically injected back into context. You never have to re-explain "we use Postgres, not SQLite" in every new session.
51
+ 2. **A separate, global memory for *you*, not the project.** Personal facts — your name, preferred language, experience level, working style — live in `~/.mazu/global_memory.db` and follow you into every project, instead of being repeated (or lost) per-repo.
52
+ 3. **Checkpointable autonomy.** Every step of an autonomous run snapshots code (via git), the memory database, and the live conversation together. Roll back any one of them and you roll back all three, consistently — "undo" for an agent's actions, not just its files.
53
+ 4. **A self-growing local skill library.** When the agent solves something reusable, it can save it as a plain Python function. Next time a similar task comes up, it can run the skill directly — skipping the model call entirely.
54
+ 5. **Provider-agnostic.** Anthropic, OpenAI, and DeepSeek are all first-class, behind one thin adapter interface. Mazu auto-detects which one to use from whichever API key is actually set in your environment — no provider is required over another.
55
+ 6. **Council mode.** For a decision worth a second opinion, ask two or three different models the same question in parallel and have a lead model synthesize a final recommendation — opt-in, since it costs more than a single call.
56
+
57
+ Everything above (agent loop, tool execution, memory database, skill library, checkpoints) runs locally. The only network traffic is your chosen model's API call, plus one cheap end-of-session call (on the same provider) to extract memories from the transcript. Nothing else leaves your machine, and there is no server run by this project.
58
+
59
+ ## Installation
60
+
61
+ Requires **Python 3.11+** and **git** (used for checkpoints).
62
+
63
+ ```bash
64
+ git clone https://github.com/<your-username>/mazu.git
65
+ cd mazu
66
+ pip install -e .
67
+
68
+ # Only needed for openai:* or deepseek:* models (DeepSeek's API is OpenAI-compatible,
69
+ # so it reuses the same client library under a different base URL):
70
+ pip install -e ".[openai]"
71
+ ```
72
+
73
+ Then set at least one API key — Mazu picks whichever provider is present automatically, so you only need the one you actually plan to use:
74
+
75
+ ```bash
76
+ export ANTHROPIC_API_KEY=sk-ant-... # or store it in ~/.mazu/config.toml
77
+ export DEEPSEEK_API_KEY=sk-...
78
+ export OPENAI_API_KEY=sk-...
79
+ ```
80
+
81
+ On Windows (PowerShell): `$env:ANTHROPIC_API_KEY = "sk-ant-..."`
82
+
83
+ ## Quick start
84
+
85
+ ```bash
86
+ cd your-project/
87
+ mazu init # creates .mazu/ (local memory + checkpoints) and a git repo if needed
88
+ mazu chat # start talking to the agent
89
+ ```
90
+
91
+ ```
92
+ > we use PostgreSQL for this project, not SQLite. remember that.
93
+ [remember] saved (decision): use PostgreSQL, not SQLite
94
+ > /checkpoint
95
+ [checkpoint] cp_000001 saved (commit 4f2a91c)
96
+ > add a health-check endpoint to app.py and run the tests
97
+ ...
98
+ ```
99
+
100
+ Exit and come back later (even days later) — the next session already knows about PostgreSQL, without you repeating it:
101
+
102
+ ```bash
103
+ mazu chat
104
+ > what database does this project use?
105
+ [memory] loaded prior context relevant to this task
106
+
107
+ PostgreSQL — this was a project decision, not SQLite.
108
+ ```
109
+
110
+ ## Usage
111
+
112
+ ### Interactive chat
113
+
114
+ ```bash
115
+ mazu chat # start a session in the current directory
116
+ mazu chat --model deepseek:deepseek-chat
117
+ ```
118
+
119
+ Inside the `>` prompt, two extra commands are always available:
120
+
121
+ | Command | Effect |
122
+ |---|---|
123
+ | `/checkpoint` | Snapshot code, memory, and the live conversation right now |
124
+ | `/rollback [id]` | Restore all three to that checkpoint (defaults to the most recent one) |
125
+
126
+ Any destructive tool call (writing a file, editing a file, running a shell command) asks for confirmation first.
127
+
128
+ ### Autonomous runs
129
+
130
+ ```bash
131
+ mazu run "add input validation to utils.py, run the tests, and fix any failures" --max-steps 15
132
+ ```
133
+
134
+ The agent keeps working, unattended, across multiple tool-use rounds until it finishes, hits `--max-steps`, or trips a safety limit. It checkpoints automatically along the way (`--checkpoint-every N`, default every round), so anything it does can be rolled back.
135
+
136
+ Key flags:
137
+
138
+ | Flag | Purpose |
139
+ |---|---|
140
+ | `--max-steps N` | Stop after N tool-use rounds (default 15) |
141
+ | `--checkpoint-every N` | Snapshot every N rounds (default 1) |
142
+ | `--allow-shell` | Skip the confirmation prompt for shell commands (the hardcoded safety denylist below still applies) |
143
+ | `--max-cost USD` | Stop once estimated spend (from a built-in pricing table) reaches this amount |
144
+ | `--keep-checkpoints N` | Prune on-disk checkpoint data beyond the N most recent (default 50) |
145
+ | `--model provider:model` | Override the model for this run |
146
+
147
+ By default, file writes/edits proceed unattended in `run` mode (checkpoints make them recoverable), but shell commands still ask for confirmation unless `--allow-shell` is passed. Regardless of that flag, a hardcoded denylist always blocks a short list of genuinely dangerous commands: force-pushing, `sudo`, touching `~/.ssh`, disk-format commands, and `rm -rf /`-style wipes. Checkpoints undo file damage — they can't undo an irreversible external action like a force-push or a sent network request, so that backstop stays even with `--allow-shell`.
148
+
149
+ `mazu run` refuses to start on a dirty working tree, so the first checkpoint is always a clean baseline. If it's interrupted with **Ctrl-C**, you're offered `[c]ontinue`, `[r]ollback <id>`, or `[q]uit` before anything is lost.
150
+
151
+ ### Memory
152
+
153
+ ```bash
154
+ mazu memory list # everything remembered about this project
155
+ mazu memory list --category mistake # filter by category
156
+ mazu memory list --global # the cross-project store (facts about you, not the code)
157
+ mazu memory forget <id> # delete a memory by id
158
+ mazu memory forget <id> --global
159
+ ```
160
+
161
+ Memory categories: `decision`, `convention`, `mistake`, `task_outcome`, `fact` (all project-scoped) and `user_preference` (global — your name, language, experience level, working style; injected into every project's context automatically).
162
+
163
+ Memories are written two ways: explicitly, when the agent calls `remember` (you can just tell it "remember that..."), and automatically, via a cheap end-of-session pass that extracts anything notable you didn't ask it to remember. Both paths de-duplicate against existing memories (exact and fuzzy title matching) so the same fact doesn't pile up across sessions, and an explicit `remember` call can mark an older memory as superseded when something changes.
164
+
165
+ ### Skills
166
+
167
+ ```bash
168
+ mazu skills list # saved reusable solutions for this project
169
+ mazu skills forget <name> # delete one
170
+ ```
171
+
172
+ When the agent solves a reusable problem, it can save the solution as a plain Python function under `.mazu/skills/<name>/`. The next time a similar task comes up, it can call the skill directly instead of solving it again from scratch through the model — a real cost and latency win for repeated, mechanical work.
173
+
174
+ ### Checkpoints & rollback
175
+
176
+ ```bash
177
+ mazu checkpoint # manually snapshot code + memory (outside a chat session)
178
+ mazu checkpoint prune --keep 20 # drop old on-disk snapshot copies (git history is untouched)
179
+ mazu rollback # restore to the most recent checkpoint
180
+ mazu rollback cp_000003 # restore to a specific one
181
+ ```
182
+
183
+ A checkpoint bundles a git commit, a consistent copy of the memory database (taken via SQLite's online backup API, safe even mid-write), the skill library, and the conversation transcript. Restoring one restores all of them together, so code, what the agent remembers, and what it was talking about never drift out of sync with each other.
184
+
185
+ ### Council mode
186
+
187
+ ```bash
188
+ mazu council "should we migrate this service to async I/O, and how risky is it?"
189
+ mazu council "..." --models anthropic:claude-sonnet-5,openai:gpt-5,deepseek:deepseek-chat --lead anthropic:claude-opus-4-8
190
+ ```
191
+
192
+ Asks each model independently and in parallel (they don't see each other's answers), then has the lead model compare and synthesize a single recommendation. Council members get **read-only** tools only (`read_file`, `list_dir`, `glob_files`, `recall`, `list_skills`) — they can inspect your project to give an informed answer, but can't write, edit, or run anything, so asking several models at once never risks them clobbering each other's changes. This is opt-in and costs one API call per model plus one for the lead — not something you'd want as the default flow for routine tasks.
193
+
194
+ ## Model naming
195
+
196
+ Models are named `provider:model` — e.g. `anthropic:claude-sonnet-5`, `openai:gpt-5`, `deepseek:deepseek-chat`, `deepseek:deepseek-reasoner`. A bare name with no prefix (`MAZU_MODEL=claude-opus-4-8`) is assumed to be Anthropic.
197
+
198
+ Resolution order when you don't pass `--model`:
199
+ 1. `MAZU_MODEL` environment variable, if set.
200
+ 2. Auto-detected from whichever provider's API key is actually present in your environment.
201
+ 3. A hardcoded Anthropic fallback (which just surfaces a clear "set ANTHROPIC_API_KEY" message if you truly have no key configured).
202
+
203
+ A DeepSeek-only or OpenAI-only setup works with zero extra flags — Anthropic is only a tie-breaker if more than one key happens to be set, never a hard requirement.
204
+
205
+ ## How it fits together
206
+
207
+ ```
208
+ mazu/
209
+ ├── cli.py Click entry point — chat / run / council / memory / skills / checkpoint / rollback
210
+ ├── agent/
211
+ │ ├── loop.py interactive chat REPL
212
+ │ ├── autonomous.py unattended multi-step runner with circuit breaker + cost limit
213
+ │ ├── council.py parallel multi-model advisory round + lead synthesis
214
+ │ ├── context.py builds the system prompt from project + global memory + skills
215
+ │ └── prompts.py the system prompt itself
216
+ ├── llm/
217
+ │ ├── client.py single run_turn()/run_forced_tool() seam every provider call goes through
218
+ │ ├── providers/ Anthropic, OpenAI, DeepSeek adapters behind a common interface
219
+ │ ├── errors.py normalized error hierarchy (rate limit, auth, transient, context-length)
220
+ │ └── pricing.py rough per-model cost estimates for --max-cost
221
+ ├── memory/
222
+ │ ├── store.py SQLite-backed memory store (shared by project + global instances)
223
+ │ ├── retrieval.py BM25 ranking + context-block rendering
224
+ │ └── extraction.py end-of-session auto-extraction prompt
225
+ ├── checkpoint/
226
+ │ └── manager.py git commit + memory/skills/conversation snapshot, retention/pruning
227
+ ├── skills/
228
+ │ └── manager.py save/list/run local skill functions
229
+ └── tools/ read_file, write_file, edit_file, list_dir, glob_files, run_shell,
230
+ remember, recall, save_skill, run_skill, list_skills
231
+ ```
232
+
233
+ The project-scoped memory database lives at `.mazu/memory.db` (created by `mazu init`, gitignored by default). The global, cross-project store lives at `~/.mazu/global_memory.db`, outside any project entirely.
234
+
235
+ ## Security notes
236
+
237
+ - All file tools are sandboxed to the project root — paths (including through symlinks) that resolve outside it are rejected.
238
+ - Shell commands go through a shared denylist (destructive/irreversible patterns) in **both** `mazu chat` and `mazu run`, regardless of confirmation settings.
239
+ - API keys are only ever read from environment variables or `~/.mazu/config.toml` (outside any repo) — Mazu never writes a key to disk itself, and `.mazu/`, `.env`, and `config.toml` are all gitignored by default.
240
+ - `mazu run` refuses to start with uncommitted changes already present, so autonomous edits are always diffable against a clean baseline.
241
+
242
+ ## Status & roadmap
243
+
244
+ Milestones M1–M4 (bare tool loop, persistent memory, checkpoint/rollback, supervised autonomy) all have a working implementation, plus multi-provider support and council mode on top. This has been exercised through live testing against real Anthropic, OpenAI, and DeepSeek API keys — chat/run tool use, memory recall (project and global), skill save/run, checkpoint/rollback (including pruning and skill restoration), memory supersede, and parallel council queries have all been verified working end-to-end.
245
+
246
+ **Known gaps, honestly listed:**
247
+ - No automated test suite yet (`pytest`) — verification so far has been live testing plus ad-hoc smoke scripts, not a checked-in regression suite.
248
+ - No semantic/embedding-based memory retrieval yet — BM25 is a solid, zero-cost baseline, but pure keyword ranking can miss a relevant memory that's phrased very differently from the current task.
249
+ - Checkpoint/rollback is linear (like `git reset --hard`), not a branching tree.
250
+ - No context compaction for very long autonomous runs — a run that grows the conversation past a model's context window will surface a clear error rather than crash, but won't automatically summarize and continue.
251
+ - Windows-only testing so far; Mac/Linux should work (nothing OS-specific in the design) but hasn't been verified live.
252
+ - No `mazu memory consolidate` command yet for manually merging/cleaning up accumulated memories.
253
+ - No Google Gemini provider yet — the adapter interface is designed to make this a small addition, not a redesign.
254
+
255
+ Contributions and issue reports are welcome.
256
+
257
+ ## License
258
+
259
+ MIT — see [LICENSE](LICENSE). Free to use, modify, and distribute, commercially or otherwise, as long as the copyright notice (Turgut Sofuyev) is kept in copies of the software.
mazu-0.1.0/README.md ADDED
@@ -0,0 +1,229 @@
1
+ # Mazu
2
+
3
+ **A memory-augmented, checkpointable coding agent CLI.** Open source, runs entirely on your own machine, works with Anthropic, OpenAI, or DeepSeek.
4
+
5
+ Most coding agents forget everything the moment the session ends. Mazu doesn't. It keeps a real, queryable memory of your project — decisions, conventions, mistakes — that persists across sessions and gets surfaced automatically. And because every autonomous step is checkpointed (code + memory + conversation, together), you can let it run longer and less-supervised without losing the ability to undo it.
6
+
7
+ ```
8
+ ███╗ ███╗
9
+ ████╗ ████║ A Z U
10
+ ██╔████╔██║ ══════════════════════════════
11
+ ██║╚██╔╝██║ memory-augmented coding agent
12
+ ██║ ╚═╝ ██║ persistent memory · checkpoints · skills · multi-model
13
+ ╚═╝ ╚═╝
14
+ ```
15
+
16
+ ## What makes Mazu different
17
+
18
+ Compared to typical coding-agent CLIs, which reset context every session and rely on a static instructions file:
19
+
20
+ 1. **Persistent structured memory.** Decisions, conventions, and mistakes made on a project are written to a local SQLite database, ranked by local BM25 (zero API cost — no embedding calls) against your current task, and automatically injected back into context. You never have to re-explain "we use Postgres, not SQLite" in every new session.
21
+ 2. **A separate, global memory for *you*, not the project.** Personal facts — your name, preferred language, experience level, working style — live in `~/.mazu/global_memory.db` and follow you into every project, instead of being repeated (or lost) per-repo.
22
+ 3. **Checkpointable autonomy.** Every step of an autonomous run snapshots code (via git), the memory database, and the live conversation together. Roll back any one of them and you roll back all three, consistently — "undo" for an agent's actions, not just its files.
23
+ 4. **A self-growing local skill library.** When the agent solves something reusable, it can save it as a plain Python function. Next time a similar task comes up, it can run the skill directly — skipping the model call entirely.
24
+ 5. **Provider-agnostic.** Anthropic, OpenAI, and DeepSeek are all first-class, behind one thin adapter interface. Mazu auto-detects which one to use from whichever API key is actually set in your environment — no provider is required over another.
25
+ 6. **Council mode.** For a decision worth a second opinion, ask two or three different models the same question in parallel and have a lead model synthesize a final recommendation — opt-in, since it costs more than a single call.
26
+
27
+ Everything above (agent loop, tool execution, memory database, skill library, checkpoints) runs locally. The only network traffic is your chosen model's API call, plus one cheap end-of-session call (on the same provider) to extract memories from the transcript. Nothing else leaves your machine, and there is no server run by this project.
28
+
29
+ ## Installation
30
+
31
+ Requires **Python 3.11+** and **git** (used for checkpoints).
32
+
33
+ ```bash
34
+ git clone https://github.com/<your-username>/mazu.git
35
+ cd mazu
36
+ pip install -e .
37
+
38
+ # Only needed for openai:* or deepseek:* models (DeepSeek's API is OpenAI-compatible,
39
+ # so it reuses the same client library under a different base URL):
40
+ pip install -e ".[openai]"
41
+ ```
42
+
43
+ Then set at least one API key — Mazu picks whichever provider is present automatically, so you only need the one you actually plan to use:
44
+
45
+ ```bash
46
+ export ANTHROPIC_API_KEY=sk-ant-... # or store it in ~/.mazu/config.toml
47
+ export DEEPSEEK_API_KEY=sk-...
48
+ export OPENAI_API_KEY=sk-...
49
+ ```
50
+
51
+ On Windows (PowerShell): `$env:ANTHROPIC_API_KEY = "sk-ant-..."`
52
+
53
+ ## Quick start
54
+
55
+ ```bash
56
+ cd your-project/
57
+ mazu init # creates .mazu/ (local memory + checkpoints) and a git repo if needed
58
+ mazu chat # start talking to the agent
59
+ ```
60
+
61
+ ```
62
+ > we use PostgreSQL for this project, not SQLite. remember that.
63
+ [remember] saved (decision): use PostgreSQL, not SQLite
64
+ > /checkpoint
65
+ [checkpoint] cp_000001 saved (commit 4f2a91c)
66
+ > add a health-check endpoint to app.py and run the tests
67
+ ...
68
+ ```
69
+
70
+ Exit and come back later (even days later) — the next session already knows about PostgreSQL, without you repeating it:
71
+
72
+ ```bash
73
+ mazu chat
74
+ > what database does this project use?
75
+ [memory] loaded prior context relevant to this task
76
+
77
+ PostgreSQL — this was a project decision, not SQLite.
78
+ ```
79
+
80
+ ## Usage
81
+
82
+ ### Interactive chat
83
+
84
+ ```bash
85
+ mazu chat # start a session in the current directory
86
+ mazu chat --model deepseek:deepseek-chat
87
+ ```
88
+
89
+ Inside the `>` prompt, two extra commands are always available:
90
+
91
+ | Command | Effect |
92
+ |---|---|
93
+ | `/checkpoint` | Snapshot code, memory, and the live conversation right now |
94
+ | `/rollback [id]` | Restore all three to that checkpoint (defaults to the most recent one) |
95
+
96
+ Any destructive tool call (writing a file, editing a file, running a shell command) asks for confirmation first.
97
+
98
+ ### Autonomous runs
99
+
100
+ ```bash
101
+ mazu run "add input validation to utils.py, run the tests, and fix any failures" --max-steps 15
102
+ ```
103
+
104
+ The agent keeps working, unattended, across multiple tool-use rounds until it finishes, hits `--max-steps`, or trips a safety limit. It checkpoints automatically along the way (`--checkpoint-every N`, default every round), so anything it does can be rolled back.
105
+
106
+ Key flags:
107
+
108
+ | Flag | Purpose |
109
+ |---|---|
110
+ | `--max-steps N` | Stop after N tool-use rounds (default 15) |
111
+ | `--checkpoint-every N` | Snapshot every N rounds (default 1) |
112
+ | `--allow-shell` | Skip the confirmation prompt for shell commands (the hardcoded safety denylist below still applies) |
113
+ | `--max-cost USD` | Stop once estimated spend (from a built-in pricing table) reaches this amount |
114
+ | `--keep-checkpoints N` | Prune on-disk checkpoint data beyond the N most recent (default 50) |
115
+ | `--model provider:model` | Override the model for this run |
116
+
117
+ By default, file writes/edits proceed unattended in `run` mode (checkpoints make them recoverable), but shell commands still ask for confirmation unless `--allow-shell` is passed. Regardless of that flag, a hardcoded denylist always blocks a short list of genuinely dangerous commands: force-pushing, `sudo`, touching `~/.ssh`, disk-format commands, and `rm -rf /`-style wipes. Checkpoints undo file damage — they can't undo an irreversible external action like a force-push or a sent network request, so that backstop stays even with `--allow-shell`.
118
+
119
+ `mazu run` refuses to start on a dirty working tree, so the first checkpoint is always a clean baseline. If it's interrupted with **Ctrl-C**, you're offered `[c]ontinue`, `[r]ollback <id>`, or `[q]uit` before anything is lost.
120
+
121
+ ### Memory
122
+
123
+ ```bash
124
+ mazu memory list # everything remembered about this project
125
+ mazu memory list --category mistake # filter by category
126
+ mazu memory list --global # the cross-project store (facts about you, not the code)
127
+ mazu memory forget <id> # delete a memory by id
128
+ mazu memory forget <id> --global
129
+ ```
130
+
131
+ Memory categories: `decision`, `convention`, `mistake`, `task_outcome`, `fact` (all project-scoped) and `user_preference` (global — your name, language, experience level, working style; injected into every project's context automatically).
132
+
133
+ Memories are written two ways: explicitly, when the agent calls `remember` (you can just tell it "remember that..."), and automatically, via a cheap end-of-session pass that extracts anything notable you didn't ask it to remember. Both paths de-duplicate against existing memories (exact and fuzzy title matching) so the same fact doesn't pile up across sessions, and an explicit `remember` call can mark an older memory as superseded when something changes.
134
+
135
+ ### Skills
136
+
137
+ ```bash
138
+ mazu skills list # saved reusable solutions for this project
139
+ mazu skills forget <name> # delete one
140
+ ```
141
+
142
+ When the agent solves a reusable problem, it can save the solution as a plain Python function under `.mazu/skills/<name>/`. The next time a similar task comes up, it can call the skill directly instead of solving it again from scratch through the model — a real cost and latency win for repeated, mechanical work.
143
+
144
+ ### Checkpoints & rollback
145
+
146
+ ```bash
147
+ mazu checkpoint # manually snapshot code + memory (outside a chat session)
148
+ mazu checkpoint prune --keep 20 # drop old on-disk snapshot copies (git history is untouched)
149
+ mazu rollback # restore to the most recent checkpoint
150
+ mazu rollback cp_000003 # restore to a specific one
151
+ ```
152
+
153
+ A checkpoint bundles a git commit, a consistent copy of the memory database (taken via SQLite's online backup API, safe even mid-write), the skill library, and the conversation transcript. Restoring one restores all of them together, so code, what the agent remembers, and what it was talking about never drift out of sync with each other.
154
+
155
+ ### Council mode
156
+
157
+ ```bash
158
+ mazu council "should we migrate this service to async I/O, and how risky is it?"
159
+ mazu council "..." --models anthropic:claude-sonnet-5,openai:gpt-5,deepseek:deepseek-chat --lead anthropic:claude-opus-4-8
160
+ ```
161
+
162
+ Asks each model independently and in parallel (they don't see each other's answers), then has the lead model compare and synthesize a single recommendation. Council members get **read-only** tools only (`read_file`, `list_dir`, `glob_files`, `recall`, `list_skills`) — they can inspect your project to give an informed answer, but can't write, edit, or run anything, so asking several models at once never risks them clobbering each other's changes. This is opt-in and costs one API call per model plus one for the lead — not something you'd want as the default flow for routine tasks.
163
+
164
+ ## Model naming
165
+
166
+ Models are named `provider:model` — e.g. `anthropic:claude-sonnet-5`, `openai:gpt-5`, `deepseek:deepseek-chat`, `deepseek:deepseek-reasoner`. A bare name with no prefix (`MAZU_MODEL=claude-opus-4-8`) is assumed to be Anthropic.
167
+
168
+ Resolution order when you don't pass `--model`:
169
+ 1. `MAZU_MODEL` environment variable, if set.
170
+ 2. Auto-detected from whichever provider's API key is actually present in your environment.
171
+ 3. A hardcoded Anthropic fallback (which just surfaces a clear "set ANTHROPIC_API_KEY" message if you truly have no key configured).
172
+
173
+ A DeepSeek-only or OpenAI-only setup works with zero extra flags — Anthropic is only a tie-breaker if more than one key happens to be set, never a hard requirement.
174
+
175
+ ## How it fits together
176
+
177
+ ```
178
+ mazu/
179
+ ├── cli.py Click entry point — chat / run / council / memory / skills / checkpoint / rollback
180
+ ├── agent/
181
+ │ ├── loop.py interactive chat REPL
182
+ │ ├── autonomous.py unattended multi-step runner with circuit breaker + cost limit
183
+ │ ├── council.py parallel multi-model advisory round + lead synthesis
184
+ │ ├── context.py builds the system prompt from project + global memory + skills
185
+ │ └── prompts.py the system prompt itself
186
+ ├── llm/
187
+ │ ├── client.py single run_turn()/run_forced_tool() seam every provider call goes through
188
+ │ ├── providers/ Anthropic, OpenAI, DeepSeek adapters behind a common interface
189
+ │ ├── errors.py normalized error hierarchy (rate limit, auth, transient, context-length)
190
+ │ └── pricing.py rough per-model cost estimates for --max-cost
191
+ ├── memory/
192
+ │ ├── store.py SQLite-backed memory store (shared by project + global instances)
193
+ │ ├── retrieval.py BM25 ranking + context-block rendering
194
+ │ └── extraction.py end-of-session auto-extraction prompt
195
+ ├── checkpoint/
196
+ │ └── manager.py git commit + memory/skills/conversation snapshot, retention/pruning
197
+ ├── skills/
198
+ │ └── manager.py save/list/run local skill functions
199
+ └── tools/ read_file, write_file, edit_file, list_dir, glob_files, run_shell,
200
+ remember, recall, save_skill, run_skill, list_skills
201
+ ```
202
+
203
+ The project-scoped memory database lives at `.mazu/memory.db` (created by `mazu init`, gitignored by default). The global, cross-project store lives at `~/.mazu/global_memory.db`, outside any project entirely.
204
+
205
+ ## Security notes
206
+
207
+ - All file tools are sandboxed to the project root — paths (including through symlinks) that resolve outside it are rejected.
208
+ - Shell commands go through a shared denylist (destructive/irreversible patterns) in **both** `mazu chat` and `mazu run`, regardless of confirmation settings.
209
+ - API keys are only ever read from environment variables or `~/.mazu/config.toml` (outside any repo) — Mazu never writes a key to disk itself, and `.mazu/`, `.env`, and `config.toml` are all gitignored by default.
210
+ - `mazu run` refuses to start with uncommitted changes already present, so autonomous edits are always diffable against a clean baseline.
211
+
212
+ ## Status & roadmap
213
+
214
+ Milestones M1–M4 (bare tool loop, persistent memory, checkpoint/rollback, supervised autonomy) all have a working implementation, plus multi-provider support and council mode on top. This has been exercised through live testing against real Anthropic, OpenAI, and DeepSeek API keys — chat/run tool use, memory recall (project and global), skill save/run, checkpoint/rollback (including pruning and skill restoration), memory supersede, and parallel council queries have all been verified working end-to-end.
215
+
216
+ **Known gaps, honestly listed:**
217
+ - No automated test suite yet (`pytest`) — verification so far has been live testing plus ad-hoc smoke scripts, not a checked-in regression suite.
218
+ - No semantic/embedding-based memory retrieval yet — BM25 is a solid, zero-cost baseline, but pure keyword ranking can miss a relevant memory that's phrased very differently from the current task.
219
+ - Checkpoint/rollback is linear (like `git reset --hard`), not a branching tree.
220
+ - No context compaction for very long autonomous runs — a run that grows the conversation past a model's context window will surface a clear error rather than crash, but won't automatically summarize and continue.
221
+ - Windows-only testing so far; Mac/Linux should work (nothing OS-specific in the design) but hasn't been verified live.
222
+ - No `mazu memory consolidate` command yet for manually merging/cleaning up accumulated memories.
223
+ - No Google Gemini provider yet — the adapter interface is designed to make this a small addition, not a redesign.
224
+
225
+ Contributions and issue reports are welcome.
226
+
227
+ ## License
228
+
229
+ MIT — see [LICENSE](LICENSE). Free to use, modify, and distribute, commercially or otherwise, as long as the copyright notice (Turgut Sofuyev) is kept in copies of the software.
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
File without changes