zai-cli 0.1.0__py3-none-any.whl

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 (68) hide show
  1. zai/__init__.py +1 -0
  2. zai/__main__.py +4 -0
  3. zai/cli/__init__.py +1 -0
  4. zai/cli/common.py +16 -0
  5. zai/cli/integrations.py +319 -0
  6. zai/cli/interactive.py +518 -0
  7. zai/cli/settings.py +436 -0
  8. zai/cli/utilities.py +227 -0
  9. zai/cli/workflows.py +137 -0
  10. zai/commands/commit.md +24 -0
  11. zai/commands/explain.md +17 -0
  12. zai/commands/feature.md +34 -0
  13. zai/commands/fix.md +14 -0
  14. zai/commands/review.md +22 -0
  15. zai/config.py +307 -0
  16. zai/core/__init__.py +0 -0
  17. zai/core/agent.py +701 -0
  18. zai/core/cancellation.py +67 -0
  19. zai/core/commands.py +85 -0
  20. zai/core/context.py +299 -0
  21. zai/core/errors.py +125 -0
  22. zai/core/fallback.py +171 -0
  23. zai/core/hooks.py +115 -0
  24. zai/core/memory.py +57 -0
  25. zai/core/process.py +204 -0
  26. zai/core/repomap.py +381 -0
  27. zai/core/runtime.py +29 -0
  28. zai/core/security.py +33 -0
  29. zai/core/session.py +425 -0
  30. zai/core/storage.py +193 -0
  31. zai/core/streaming.py +157 -0
  32. zai/core/tool_schema.py +133 -0
  33. zai/core/undo.py +443 -0
  34. zai/core/watch.py +80 -0
  35. zai/main.py +210 -0
  36. zai/mcp/__init__.py +0 -0
  37. zai/mcp/client.py +431 -0
  38. zai/mcp/manager.py +118 -0
  39. zai/plugins/__init__.py +2 -0
  40. zai/plugins/base.py +49 -0
  41. zai/plugins/loader.py +404 -0
  42. zai/providers/__init__.py +22 -0
  43. zai/providers/anthropic.py +131 -0
  44. zai/providers/base.py +67 -0
  45. zai/providers/cerebras.py +57 -0
  46. zai/providers/gemini.py +119 -0
  47. zai/providers/groq.py +116 -0
  48. zai/providers/ollama.py +62 -0
  49. zai/providers/openai.py +124 -0
  50. zai/providers/openrouter.py +63 -0
  51. zai/providers/qwen.py +47 -0
  52. zai/skills/__init__.py +0 -0
  53. zai/skills/registry.py +52 -0
  54. zai/tools/__init__.py +0 -0
  55. zai/tools/browser.py +224 -0
  56. zai/tools/code_runner.py +49 -0
  57. zai/tools/files.py +53 -0
  58. zai/tools/git.py +38 -0
  59. zai/tools/search.py +157 -0
  60. zai/tools/vision.py +128 -0
  61. zai/ui/__init__.py +0 -0
  62. zai/ui/input.py +199 -0
  63. zai_cli-0.1.0.dist-info/METADATA +722 -0
  64. zai_cli-0.1.0.dist-info/RECORD +68 -0
  65. zai_cli-0.1.0.dist-info/WHEEL +5 -0
  66. zai_cli-0.1.0.dist-info/entry_points.txt +2 -0
  67. zai_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
  68. zai_cli-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,722 @@
1
+ Metadata-Version: 2.4
2
+ Name: zai-cli
3
+ Version: 0.1.0
4
+ Summary: Your personal AI CLI — free, fast, and smart
5
+ License-Expression: MIT
6
+ Project-URL: Homepage, https://github.com/HumaizaNaz/zai_cli
7
+ Project-URL: Repository, https://github.com/HumaizaNaz/zai_cli
8
+ Project-URL: Issues, https://github.com/HumaizaNaz/zai_cli/issues
9
+ Project-URL: Changelog, https://github.com/HumaizaNaz/zai_cli/blob/main/CHANGELOG.md
10
+ Keywords: ai,cli,assistant,gemini,groq,llm
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Environment :: Console
19
+ Classifier: Topic :: Utilities
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: typer>=0.12.0
24
+ Requires-Dist: rich>=13.0.0
25
+ Requires-Dist: httpx>=0.27.0
26
+ Requires-Dist: python-dotenv>=1.1.0
27
+ Requires-Dist: pydantic>=2.0.0
28
+ Requires-Dist: Pillow>=10.0.0
29
+ Requires-Dist: prompt-toolkit>=3.0.48
30
+ Requires-Dist: pathspec>=0.12.1
31
+ Provides-Extra: gemini
32
+ Requires-Dist: google-genai>=1.0.0; extra == "gemini"
33
+ Provides-Extra: groq
34
+ Requires-Dist: groq>=0.11.0; extra == "groq"
35
+ Provides-Extra: cerebras
36
+ Requires-Dist: cerebras-cloud-sdk>=1.0.0; extra == "cerebras"
37
+ Provides-Extra: anthropic
38
+ Requires-Dist: anthropic>=0.40.0; extra == "anthropic"
39
+ Provides-Extra: openai
40
+ Requires-Dist: openai>=1.0.0; extra == "openai"
41
+ Provides-Extra: all
42
+ Requires-Dist: google-genai>=1.0.0; extra == "all"
43
+ Requires-Dist: groq>=0.11.0; extra == "all"
44
+ Requires-Dist: cerebras-cloud-sdk>=1.0.0; extra == "all"
45
+ Requires-Dist: anthropic>=0.40.0; extra == "all"
46
+ Requires-Dist: openai>=1.0.0; extra == "all"
47
+ Provides-Extra: dev
48
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
49
+ Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
50
+ Requires-Dist: build>=1.2.0; extra == "dev"
51
+ Requires-Dist: twine>=5.0.0; extra == "dev"
52
+ Requires-Dist: ruff>=0.12.0; extra == "dev"
53
+ Requires-Dist: mypy>=1.16.0; extra == "dev"
54
+ Requires-Dist: pip-audit>=2.9.0; extra == "dev"
55
+ Requires-Dist: tomli>=2.2.1; python_version < "3.11" and extra == "dev"
56
+ Dynamic: license-file
57
+
58
+ # zai
59
+
60
+ An extensible AI coding assistant for the terminal.
61
+
62
+ `zai` can chat about a project, inspect and modify files, run commands, resume
63
+ project-specific sessions, switch between model providers, and integrate with
64
+ plugins and MCP servers.
65
+
66
+ ## Requirements
67
+
68
+ - Python 3.10 or newer
69
+ - At least one supported API key, or a running local Ollama server
70
+ - Optional: Playwright for browser commands
71
+ - Optional: Node.js and `npx` for MCP servers
72
+
73
+ ## Install
74
+
75
+ ```bash
76
+ pip install zai-cli
77
+ zai setup
78
+ ```
79
+
80
+ The PyPI distribution is named `zai-cli`; the installed command and Python
81
+ package remain `zai`.
82
+
83
+ For local development:
84
+
85
+ ```bash
86
+ pip install -e ".[all,dev]"
87
+ python -m pytest -q
88
+ ```
89
+
90
+ Optional live service checks:
91
+
92
+ ```bash
93
+ ZAI_RUN_LIVE_TESTS=1 python -m pytest tests/integration -m integration
94
+ ```
95
+
96
+ Optional selectors include `ZAI_LIVE_PROVIDER=groq`,
97
+ `ZAI_LIVE_BROWSER=1`, and `ZAI_LIVE_MCP=1`. Live tests can consume provider
98
+ quota or download/start external tools.
99
+
100
+ ## Quick start
101
+
102
+ ```bash
103
+ # Configure providers
104
+ zai setup
105
+
106
+ # Start the interactive coding assistant in the current directory
107
+ zai
108
+
109
+ # One-off chat
110
+ zai ask "Explain recursion"
111
+
112
+ # Explicit chat command
113
+ zai chat "Explain this project"
114
+
115
+ # Work with code
116
+ zai skill review main.py
117
+ zai repo map
118
+ zai run script.py
119
+ zai git status
120
+ ```
121
+
122
+ ## Main commands
123
+
124
+ ```text
125
+ zai Start the interactive project assistant
126
+ zai ask <message> Send a one-off message
127
+ zai chat [message] Chat with the configured model
128
+ zai --plain ask <message> Emit only plain final response text
129
+ zai --debug ... Show full tracebacks for unexpected errors
130
+
131
+ zai file read <path> Read a file
132
+ zai file list [directory] Recursively list files
133
+ zai run <file.py> Run a Python file
134
+ zai repo map Build a repository map
135
+ zai repo ask <question> Ask about a repository
136
+ zai search <query> Search general DuckDuckGo web results and summarize
137
+
138
+ zai skill <name> <file> Run a built-in or plugin skill
139
+ zai git status Show Git status
140
+ zai git log Show recent commits
141
+ zai git diff Show changes
142
+ zai git commit Generate and optionally use a commit message
143
+ zai git review Review current changes
144
+
145
+ zai vision <image> Analyze an image with Gemini or Groq
146
+ zai browser scrape <url> Extract visible page text
147
+ zai browser screenshot <url>
148
+ zai browser analyze <url>
149
+
150
+ zai model list List configured models
151
+ zai model set <name> Set the default model
152
+ zai model fallback on|off Enable or disable automatic provider fallback
153
+ zai model add <name> Add a custom model alias
154
+ zai model remove <name> Remove a custom model alias
155
+ zai model configure <name> Set timeout and retry policy
156
+ zai model info <name> Show effective model configuration
157
+ zai model test <name> Verify credentials and model availability
158
+ zai memory show Show last task metadata
159
+ zai memory projects List remembered projects
160
+ zai memory clear Clear memory metadata
161
+
162
+ zai hook list
163
+ zai hook add <event> <command>
164
+ zai hook remove --id <id>
165
+
166
+ zai mcp available
167
+ zai mcp list
168
+ zai mcp add <name>
169
+ zai mcp connect <name>
170
+ zai mcp tools
171
+ zai mcp remove <name>
172
+
173
+ zai plugin list
174
+ zai plugin new <name>
175
+ zai plugin install <name>
176
+ zai plugin trust <name>
177
+ zai plugin untrust <name>
178
+ zai plugin enable <name>
179
+ zai plugin disable <name>
180
+ zai plugin remove <name>
181
+ ```
182
+
183
+ Run `zai --help` for the authoritative command list.
184
+
185
+ ### Plugin and browser security
186
+
187
+ Plugins execute Python with the same operating-system permissions as `zai`.
188
+ Local and pip-installed plugins therefore remain blocked until their current
189
+ code fingerprint is explicitly trusted:
190
+
191
+ ```bash
192
+ zai plugin install example
193
+ # Review the package or ~/.zai/plugins/example.py first
194
+ zai plugin trust example
195
+ ```
196
+
197
+ Every local plugin requires a `<name>.plugin.json` sidecar manifest. Packaged
198
+ plugins require `zai-plugin.json` in their distribution. Manifests declare the
199
+ plugin name, source, version, and requested permissions from:
200
+ `project_read`, `project_write`, `network`, `subprocess`, and `secrets`.
201
+
202
+ Trust fingerprints bind both code and manifest. If either changes, the plugin
203
+ is blocked until reviewed and re-trusted. Installing or enabling a plugin asks
204
+ for explicit confirmation. Agent-triggered plugin tools also show declared
205
+ permissions and ask for confirmation. Use `zai plugin untrust <name>` to revoke
206
+ trust.
207
+
208
+ Browser commands accept only credential-free public HTTP(S) URLs. Localhost,
209
+ private/link-local addresses, unsafe redirects, and non-HTTP schemes are
210
+ blocked. Screenshot output is restricted to PNG/JPEG paths inside the current
211
+ project. Browser downloads are disabled, top-level documents are capped at
212
+ 2 MB when the server reports their size, and search responses are capped at
213
+ 1 MB.
214
+
215
+ Vision input is decoded and verified before it is sent to a provider. Images
216
+ are limited to supported raster formats, 10 MB, and 40 megapixels.
217
+
218
+ ## Interactive commands
219
+
220
+ Inside `zai` interactive mode:
221
+
222
+ ```text
223
+ /help Show interactive commands
224
+ /files List current project files
225
+ /diff Show the Git diff
226
+ /undo Undo the latest recorded filesystem action
227
+ /plan <task> Generate a plan before execution
228
+ /test Run pytest and request fixes for failures
229
+ /watch Toggle file-change monitoring
230
+
231
+ /resume [name] Resume the latest project session or a named one
232
+ /session save [name] Save the current conversation
233
+ /session load <name> Load a named conversation
234
+ /session list List saved conversations
235
+ /session search <query> Search current-project conversations
236
+ /session rename <old> <new> Rename a saved conversation
237
+ /session delete <name> Delete a saved conversation
238
+
239
+ /model list List models
240
+ /model <name> Change model for this interactive session
241
+ /memory Show last task metadata
242
+ /commands List built-in and plugin slash commands
243
+ ```
244
+
245
+ Command names support safe typo correction when one close, unambiguous match
246
+ exists.
247
+
248
+ Interactive input also provides:
249
+
250
+ - persistent history in `~/.zai/input_history` with Up/Down navigation;
251
+ - Tab completion for slash commands, models, sessions, and project paths;
252
+ - multiline input with `Alt+Enter` or `Ctrl+J`;
253
+ - `Ctrl+C` to cancel the current input or operation without ending the session;
254
+ - a basic Rich prompt fallback in redirected or unsupported terminals.
255
+
256
+ ## Context management
257
+
258
+ All chat, workflow, utility, and agent requests use the same model-aware
259
+ context pipeline:
260
+
261
+ - the active provider's configured context window sets the request budget;
262
+ - system prompts, tool schemas, and output space are reserved before messages;
263
+ - initial project instructions and explicitly pinned messages are retained;
264
+ - assistant tool calls remain paired with their tool-result messages;
265
+ - oversized tool results keep their beginning and end with an omission marker;
266
+ - older turns are compacted into a structured summary while recent turns stay
267
+ verbatim;
268
+ - context usage uses a conservative shared token estimate, while provider
269
+ response usage is retained where the SDK reports it.
270
+
271
+ This replaces the previous fixed 100k limit and manual last-message truncation.
272
+
273
+ ## Providers and fallback
274
+
275
+ The default fallback order is:
276
+
277
+ ```text
278
+ gemini -> groq -> cerebras -> openrouter -> qwen -> claude -> gpt4o -> ollama
279
+ ```
280
+
281
+ Providers without an API key are skipped. Ollama is used only when its local
282
+ service is available. Provider quotas and model availability are controlled by
283
+ their respective services and can change independently of `zai`.
284
+
285
+ Supported configuration keys:
286
+
287
+ ```text
288
+ GEMINI_API_KEY
289
+ GROQ_API_KEY
290
+ CEREBRAS_API_KEY
291
+ OPENROUTER_API_KEY
292
+ QWEN_API_KEY
293
+ ANTHROPIC_API_KEY
294
+ OPENAI_API_KEY
295
+ ```
296
+
297
+ Keys are stored in `~/.zai/.env` by `zai setup`.
298
+
299
+ ## Sessions and undo
300
+
301
+ - Successful interactive turns are automatically saved per project.
302
+ - `/resume` loads the latest session for the current project.
303
+ - Sessions have stable IDs and can be resumed by name or ID prefix.
304
+ - Ambiguous partial names are rejected instead of loading the wrong session.
305
+ - Named and legacy sessions remain supported.
306
+ - The latest 100 named sessions are retained; project auto-sessions remain one
307
+ per project.
308
+ - Undo records are stored under the project's `.zai/undo/` directory.
309
+ - File creation, file edits, folder creation, and path renames are undoable.
310
+ - A non-empty generated folder is never removed by `/undo`.
311
+
312
+ Add `.zai/` to the project's `.gitignore` to avoid committing local undo data.
313
+
314
+ ## Safety
315
+
316
+ Model-controlled filesystem actions are restricted to the current project.
317
+ Writes, edits, folder creation, and renames are verified after execution.
318
+ Failed file verification triggers a best-effort rollback.
319
+
320
+ Shell commands are classified as:
321
+
322
+ - safe: executed directly;
323
+ - approval required: deletion, dependency changes, downloads, Git state
324
+ changes, shell chaining, and redirection;
325
+ - blocked: destructive operations such as `git reset --hard`, disk formatting,
326
+ shutdown commands, and destructive database statements.
327
+
328
+ Commands run as direct argument arrays with `shell=False`. Shell chaining,
329
+ redirection, command substitution, and shell interpreters are rejected.
330
+ User-defined slash-command substitutions can run only safe allowlisted
331
+ commands. Hooks also use direct executable invocation.
332
+
333
+ Tool calls use validated JSON schemas. Legacy XML tool calls remain accepted
334
+ temporarily for compatibility.
335
+
336
+ ## Hooks
337
+
338
+ Available hook events:
339
+
340
+ ```text
341
+ PreToolUse
342
+ PostToolUse
343
+ SessionStart
344
+ SessionEnd
345
+ UserPromptSubmit
346
+ ```
347
+
348
+ Hook commands receive event data as JSON on standard input. Exit code `2`
349
+ blocks the action for blocking events.
350
+
351
+ Example:
352
+
353
+ ```bash
354
+ zai hook add PreToolUse "python validate_tool.py"
355
+ ```
356
+
357
+ ## Browser support
358
+
359
+ Browser commands require Playwright:
360
+
361
+ ```bash
362
+ pip install playwright
363
+ playwright install chromium
364
+ ```
365
+
366
+ ## Development status
367
+
368
+ `zai` is currently version `0.1.0` and should be treated as a strong beta.
369
+ See `CHANGELOG.md` for release notes and known limitations.
370
+
371
+ Current quality baseline:
372
+
373
+ - 440 non-live tests passing
374
+ - 76% measured code coverage with a 75% CI minimum
375
+ - Python 3.10–3.14 test matrix
376
+ - installed-wheel smoke tests on Linux, Windows, and macOS
377
+ - wheel and source-package validation with Twine
378
+ - Ruff critical-rule linting, scoped MyPy checks for browser/search and
379
+ persistence safety modules, and dependency auditing
380
+ - project-scoped filesystem safety
381
+ - direct command execution with `shell=False`
382
+ - persistent sessions and undo
383
+ - structured and validated tool calls
384
+
385
+ Review generated changes and command output before using them in important
386
+ repositories.
387
+
388
+ ## Roadmap to a stable CLI
389
+
390
+ The following phases define the remaining work required before calling `zai`
391
+ stable. Phases should be completed in order because later work depends on the
392
+ reliability established by earlier phases.
393
+
394
+ ### Phase 1: Live service validation
395
+
396
+ Goal: prove that the mocked provider and integration tests match real external
397
+ services.
398
+
399
+ Validated on Windows on June 23, 2026:
400
+
401
+ - Groq chat and native tool-call flows;
402
+ - DuckDuckGo general web search;
403
+ - Playwright Chromium scrape and screenshot flows;
404
+ - filesystem MCP connection, tool discovery, and `list_directory` execution.
405
+
406
+ Gemini and a paid provider remain pending because credentials were not
407
+ available in the validation environment.
408
+
409
+ Implementation work:
410
+
411
+ 1. Test Groq with a real API key.
412
+ 2. Test Gemini with a real API key.
413
+ 3. Test at least one paid provider when credentials are available.
414
+ 4. Run the DuckDuckGo live search test.
415
+ 5. Install Playwright and test browser scrape and screenshot commands.
416
+ 6. Test one MCP server, preferably filesystem or GitHub.
417
+ 7. Verify provider fallback by intentionally making the preferred provider
418
+ unavailable.
419
+ 8. Record provider-specific errors and normalize any response differences.
420
+
421
+ Relevant locations:
422
+
423
+ ```text
424
+ tests/integration/test_live_services.py
425
+ zai/providers/
426
+ zai/tools/search.py
427
+ zai/tools/browser.py
428
+ zai/mcp/
429
+ ```
430
+
431
+ Commands:
432
+
433
+ ```bash
434
+ # Use a configured provider
435
+ ZAI_RUN_LIVE_TESTS=1 ZAI_LIVE_PROVIDER=groq \
436
+ python -m pytest tests/integration -m integration -v
437
+
438
+ # Browser validation
439
+ ZAI_RUN_LIVE_TESTS=1 ZAI_LIVE_BROWSER=1 \
440
+ python -m pytest tests/integration -m integration -v
441
+
442
+ # MCP validation
443
+ ZAI_RUN_LIVE_TESTS=1 ZAI_LIVE_MCP=1 \
444
+ python -m pytest tests/integration -m integration -v
445
+ ```
446
+
447
+ Definition of done:
448
+
449
+ - Groq and Gemini each complete chat and agent tool flows.
450
+ - Browser scrape and screenshot work on Windows and Linux.
451
+ - At least one MCP server connects, lists tools, and executes a tool.
452
+ - Provider fallback is demonstrated against real providers.
453
+ - Live failures produce actionable user-facing messages.
454
+
455
+ ### Phase 2: Terminal user experience
456
+
457
+ Goal: make interactive use comfortable for long coding sessions.
458
+
459
+ Completed:
460
+
461
+ - persistent history and Up/Down navigation using `prompt_toolkit`;
462
+ - slash-command, model, session, and project-path completion;
463
+ - multiline prompts using `Alt+Enter` or `Ctrl+J`;
464
+ - visible input/operation cancellation without ending the session;
465
+ - basic prompt fallback for terminals without an interactive screen buffer.
466
+
467
+ Global `--debug` enables full tracebacks for unexpected errors. Global
468
+ `--plain` makes one-shot AI requests use non-streaming calls and emit the final
469
+ response without model or token metadata, which is suitable for scripts and CI.
470
+
471
+ Ctrl+C uses a shared cooperative cancellation token across fallback attempts,
472
+ agent turns, subprocess commands, MCP requests, and plugin-call boundaries.
473
+ Running subprocesses are terminated, MCP servers receive cancellation
474
+ notifications, and session/undo state is saved only for completed turns.
475
+ Synchronous provider SDK calls are interrupted by Ctrl+C where the SDK permits;
476
+ otherwise their result is discarded at the next cancellation boundary.
477
+
478
+ Definition of done:
479
+
480
+ - Interactive history survives restart.
481
+ - Common commands and paths autocomplete.
482
+ - Long multiline requests can be entered naturally.
483
+ - Cancellation does not corrupt session or undo state.
484
+
485
+ ### Phase 3: Model and provider configuration
486
+
487
+ Goal: remove hard-coded model assumptions and make provider configuration easy
488
+ to maintain.
489
+
490
+ Completed:
491
+
492
+ 1. Custom model IDs and context windows can be stored in user configuration.
493
+ 2. Added:
494
+
495
+ ```text
496
+ zai model add
497
+ zai model remove
498
+ zai model info
499
+ zai model test
500
+ ```
501
+
502
+ 3. Users can select a model ID independently from the provider transport.
503
+ 4. Custom aliases are validated before saving.
504
+ 5. Existing configuration is normalized to schema version 3.
505
+ 6. Interactive completion and fallback include custom aliases.
506
+ 7. Per-model timeout and retry settings apply to built-in and custom aliases.
507
+ 8. Provider failures are normalized into authentication, quota/rate-limit,
508
+ model-not-found, timeout, network, and malformed-response categories.
509
+ 9. Successful responses display the selected alias, provider, and model ID.
510
+
511
+ Remaining:
512
+
513
+ 1. Add explicit migrations for schema versions after version 3.
514
+
515
+ Suggested configuration:
516
+
517
+ ```json
518
+ {
519
+ "default_model": "groq",
520
+ "auto_fallback": true,
521
+ "models": {
522
+ "groq": {
523
+ "provider": "groq",
524
+ "model_id": "provider-model-id",
525
+ "timeout": 60
526
+ }
527
+ }
528
+ }
529
+ ```
530
+
531
+ Definition of done:
532
+
533
+ - Changing a model never requires editing Python source.
534
+ - Invalid provider/model configuration is rejected clearly.
535
+ - `zai model test <name>` verifies credentials and model availability.
536
+ - Old configuration files migrate automatically.
537
+
538
+ Context-management work completed alongside this phase:
539
+
540
+ - model-specific context limits;
541
+ - shared budgeting across chat, workflows, utilities, and agent mode;
542
+ - pinned project context, structured compaction, and bounded tool results;
543
+ - native tool-call/result pair preservation during compaction.
544
+
545
+ ### Phase 4: Large repository performance
546
+
547
+ Goal: keep repository understanding fast and bounded on large projects.
548
+
549
+ Implementation work:
550
+
551
+ 1. [x] Respect `.gitignore`, `.ignore`, and configurable ignore patterns.
552
+ 2. [x] Enforce file-size, repository-size, indexed-file, and scanned-file limits.
553
+ 3. [x] Cache repository maps using paths, modification metadata, and SHA-256 hashes.
554
+ 4. [x] Re-extract symbols only for changed files.
555
+ 5. [x] Prioritize source files and skip generated, binary, secret, and symlinked files.
556
+ 6. [x] Extract symbols from Python, JavaScript/TypeScript, Go, Rust, Java, C#,
557
+ Ruby, PHP, Swift, and Kotlin.
558
+ 7. [x] Bound repository context using the active model's token budget.
559
+ 8. [x] Show indexing progress, cache activity, and skipped-file counts.
560
+
561
+ The incremental cache is stored at `.zai/cache/repomap.json` and should remain
562
+ excluded from version control.
563
+
564
+ Relevant locations:
565
+
566
+ ```text
567
+ zai/core/repomap.py
568
+ zai/core/context.py
569
+ zai/cli/utilities.py
570
+ ```
571
+
572
+ Performance targets:
573
+
574
+ - index 10,000 normal source files without loading every complete file;
575
+ - repeated map generation should use cache;
576
+ - default repository context should stay within the active model limit;
577
+ - generated directories and binary files should not enter prompts.
578
+
579
+ Definition of done:
580
+
581
+ - [x] large deterministic fixtures cover bounded scans and incremental cache hits;
582
+ - [x] cached scans avoid symbol extraction for unchanged files;
583
+ - [x] context selection is deterministic and token bounded.
584
+
585
+ ### P1.5: Plugin and browser security
586
+
587
+ Goal: prevent implicit arbitrary-code execution, SSRF, and filesystem escape.
588
+
589
+ - [x] Require a reviewed code fingerprint before loading local or pip plugins.
590
+ - [x] Require validated manifests and declared permissions before code import.
591
+ - [x] Confirm external installation and re-enabling.
592
+ - [x] Invalidate plugin trust when local code or package records change.
593
+ - [x] Require confirmation before every agent-triggered plugin tool call.
594
+ - [x] Reject plugin names that can escape the plugin directory.
595
+ - [x] Allow browser automation only for public credential-free HTTP(S) URLs.
596
+ - [x] Block private, loopback, link-local, and unsafe redirected requests.
597
+ - [x] Restrict screenshots to supported image files inside the current project.
598
+ - [x] Add regression tests for plugin trust and browser network boundaries.
599
+
600
+ ### Phase 5: Session and undo management
601
+
602
+ Goal: make session history and filesystem recovery manageable rather than only
603
+ automatic.
604
+
605
+ Available commands:
606
+
607
+ ```text
608
+ zai session list
609
+ zai session show <name>
610
+ zai session search <query>
611
+ zai session rename <old> <new>
612
+ zai session delete <name>
613
+ zai session export <name> --format md|json
614
+
615
+ zai undo list
616
+ zai undo show <id>
617
+ zai undo apply [id]
618
+ zai undo redo
619
+ zai undo clear
620
+ ```
621
+
622
+ Completed:
623
+
624
+ - stable session IDs, titles, creation/update timestamps, and project metadata;
625
+ - top-level `list`, `show`, `search`, `rename`, `delete`, and `export` commands;
626
+ - interactive `/resume`, `/session list|search|rename|delete`;
627
+ - project-scoped listing/search and exact or unambiguous ID/name resolution;
628
+ - Markdown and JSON session export restricted to the selected project;
629
+ - stable undo action IDs, timestamps, summaries, and affected paths;
630
+ - inspectable and selectable multi-step undo;
631
+ - redo and history clearing;
632
+ - conflict detection before restoring files changed outside ZAI;
633
+ - bounded retention for session history and undo backups;
634
+ - project-local cache and recovery data excluded from Git.
635
+
636
+ Definition of done:
637
+
638
+ - [x] users can inspect an operation before undoing it;
639
+ - [x] multiple undo and redo operations are deterministic;
640
+ - [x] stale/conflicting restores are blocked safely;
641
+ - [x] sessions can be searched, exported, renamed, and deleted.
642
+
643
+ ### Phase 6: Stable release
644
+
645
+ Goal: publish a reproducible release that works from a clean installation.
646
+
647
+ Release procedure:
648
+
649
+ 1. Run all non-live tests:
650
+
651
+ ```bash
652
+ python -m pytest -m "not integration" -q
653
+ ```
654
+
655
+ 2. Enforce coverage:
656
+
657
+ ```bash
658
+ python -m pytest -m "not integration" \
659
+ --cov=zai --cov-report=term-missing --cov-fail-under=75
660
+ ```
661
+
662
+ 3. Run configured live tests.
663
+ 4. Build and validate:
664
+
665
+ ```bash
666
+ python scripts/release_preflight.py
667
+ python -m build
668
+ python -m twine check dist/*
669
+ python scripts/release_preflight.py --artifacts dist
670
+ ```
671
+
672
+ 5. Install the wheel into fresh Windows and Linux virtual environments.
673
+ 6. Run smoke tests:
674
+
675
+ ```bash
676
+ zai --version
677
+ zai --help
678
+ zai model list
679
+ zai repo map
680
+ zai ask "Reply with ok"
681
+ ```
682
+
683
+ 7. [x] Add a real repository URL to `pyproject.toml`.
684
+ 8. [x] Write `CHANGELOG.md`.
685
+ 9. Bump the package version.
686
+ 10. Run the `Staged package release` workflow with `target=testpypi` and
687
+ install from TestPyPI.
688
+ 11. Run the same workflow with `target=pypi` only after the TestPyPI wheel
689
+ passes.
690
+ 12. Create a signed Git tag and GitHub release.
691
+
692
+ The publish workflow additionally runs release preflight with
693
+ `--require-repository-url`. Use `target=testpypi` for the staging publish and
694
+ `target=pypi` for the real PyPI publish.
695
+
696
+ Definition of done:
697
+
698
+ - clean wheel installation succeeds on Windows and Linux;
699
+ - CI passes for every supported Python version;
700
+ - package data includes all built-in slash commands;
701
+ - TestPyPI installation passes smoke tests;
702
+ - release notes document features, limitations, and migration steps.
703
+
704
+ ## Recommended implementation order
705
+
706
+ Use this order for the next development cycle:
707
+
708
+ 1. Live Groq validation, because Groq is the primary low-resource cloud option.
709
+ 2. Terminal history, autocomplete, multiline input, and cancellation.
710
+ 3. Configurable model IDs and `zai model test`.
711
+ 4. Repository-map caching and `.gitignore` support.
712
+ 5. Multi-step undo/redo and session management.
713
+ 6. Fresh wheel installation and TestPyPI release.
714
+
715
+ Do not add unrelated feature commands until these phases are complete. The
716
+ priority is predictable daily use, recoverability, and release quality.
717
+
718
+ ## License
719
+
720
+ MIT
721
+
722
+ # zai_cli