aichs 0.4.9__py3-none-win_amd64.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 (148) hide show
  1. aichs-0.4.9.data/data/share/aichs/docs/agent-canvas.md +38 -0
  2. aichs-0.4.9.data/data/share/aichs/docs/compact.md +43 -0
  3. aichs-0.4.9.data/data/share/aichs/docs/configuration.md +41 -0
  4. aichs-0.4.9.data/data/share/aichs/docs/custom-models.md +299 -0
  5. aichs-0.4.9.data/data/share/aichs/docs/extensions.md +823 -0
  6. aichs-0.4.9.data/data/share/aichs/docs/mcp.md +181 -0
  7. aichs-0.4.9.data/data/share/aichs/docs/organization-governance.md +730 -0
  8. aichs-0.4.9.data/data/share/aichs/docs/project-memory.md +45 -0
  9. aichs-0.4.9.data/data/share/aichs/docs/skills.md +69 -0
  10. aichs-0.4.9.data/data/share/aichs/docs/yuk.md +49 -0
  11. aichs-0.4.9.data/purelib/aichs_native/THIRD_PARTY_NOTICES.md +23 -0
  12. aichs-0.4.9.data/purelib/aichs_native/__init__.py +10 -0
  13. aichs-0.4.9.data/purelib/aichs_native/bin/aichs-indexer.exe +0 -0
  14. aichs-0.4.9.data/purelib/aichs_native/bin/rg.exe +0 -0
  15. aichs-0.4.9.data/purelib/aichs_native/wheel_tags.py +11 -0
  16. aichs-0.4.9.data/purelib/app.py +4 -0
  17. aichs-0.4.9.data/purelib/assets/__init__.py +1 -0
  18. aichs-0.4.9.data/purelib/assets/avatars/agent.svg +15 -0
  19. aichs-0.4.9.data/purelib/assets/avatars/crew_archivist.svg +8 -0
  20. aichs-0.4.9.data/purelib/assets/avatars/crew_scout.svg +7 -0
  21. aichs-0.4.9.data/purelib/assets/avatars/human.svg +8 -0
  22. aichs-0.4.9.data/purelib/assets/checkmark.svg +3 -0
  23. aichs-0.4.9.data/purelib/assets/icon.svg +44 -0
  24. aichs-0.4.9.data/purelib/assets/logo.png +0 -0
  25. aichs-0.4.9.data/purelib/assets/logo.svg +62 -0
  26. aichs-0.4.9.data/purelib/assets/png/icon-128.png +0 -0
  27. aichs-0.4.9.data/purelib/assets/png/icon-16.png +0 -0
  28. aichs-0.4.9.data/purelib/assets/png/icon-256.png +0 -0
  29. aichs-0.4.9.data/purelib/assets/png/icon-32.png +0 -0
  30. aichs-0.4.9.data/purelib/assets/png/icon-512.png +0 -0
  31. aichs-0.4.9.data/purelib/assets/png/icon-64.png +0 -0
  32. aichs-0.4.9.data/purelib/config.py +51 -0
  33. aichs-0.4.9.data/purelib/main.py +185 -0
  34. aichs-0.4.9.data/purelib/services/__init__.py +0 -0
  35. aichs-0.4.9.data/purelib/services/agent_canvas_run.py +294 -0
  36. aichs-0.4.9.data/purelib/services/audit.py +115 -0
  37. aichs-0.4.9.data/purelib/services/auto_title.py +205 -0
  38. aichs-0.4.9.data/purelib/services/chat.py +1040 -0
  39. aichs-0.4.9.data/purelib/services/chat_drag.py +153 -0
  40. aichs-0.4.9.data/purelib/services/code_completion.py +154 -0
  41. aichs-0.4.9.data/purelib/services/commit_message.py +409 -0
  42. aichs-0.4.9.data/purelib/services/compaction.py +393 -0
  43. aichs-0.4.9.data/purelib/services/content.py +410 -0
  44. aichs-0.4.9.data/purelib/services/context_budget.py +108 -0
  45. aichs-0.4.9.data/purelib/services/continuation.py +116 -0
  46. aichs-0.4.9.data/purelib/services/conversation_run.py +257 -0
  47. aichs-0.4.9.data/purelib/services/crew.py +269 -0
  48. aichs-0.4.9.data/purelib/services/crew_context.py +44 -0
  49. aichs-0.4.9.data/purelib/services/diff_html.py +112 -0
  50. aichs-0.4.9.data/purelib/services/export.py +150 -0
  51. aichs-0.4.9.data/purelib/services/extension_installer.py +517 -0
  52. aichs-0.4.9.data/purelib/services/file_editor_refs.py +94 -0
  53. aichs-0.4.9.data/purelib/services/file_ref_clipboard.py +71 -0
  54. aichs-0.4.9.data/purelib/services/file_refs.py +52 -0
  55. aichs-0.4.9.data/purelib/services/file_search.py +288 -0
  56. aichs-0.4.9.data/purelib/services/file_tree_snapshot.py +165 -0
  57. aichs-0.4.9.data/purelib/services/filename_indexer.py +165 -0
  58. aichs-0.4.9.data/purelib/services/git_diff.py +276 -0
  59. aichs-0.4.9.data/purelib/services/git_snapshot.py +108 -0
  60. aichs-0.4.9.data/purelib/services/git_status.py +360 -0
  61. aichs-0.4.9.data/purelib/services/highlight.py +42 -0
  62. aichs-0.4.9.data/purelib/services/key_bindings.py +30 -0
  63. aichs-0.4.9.data/purelib/services/language_features.py +640 -0
  64. aichs-0.4.9.data/purelib/services/language_snapshot.py +89 -0
  65. aichs-0.4.9.data/purelib/services/mcp_config.py +470 -0
  66. aichs-0.4.9.data/purelib/services/mcp_logs.py +258 -0
  67. aichs-0.4.9.data/purelib/services/mcp_oauth.py +227 -0
  68. aichs-0.4.9.data/purelib/services/mcp_tools.py +1288 -0
  69. aichs-0.4.9.data/purelib/services/model_registry.py +525 -0
  70. aichs-0.4.9.data/purelib/services/model_requests.py +57 -0
  71. aichs-0.4.9.data/purelib/services/organization_policy.py +674 -0
  72. aichs-0.4.9.data/purelib/services/palette.py +155 -0
  73. aichs-0.4.9.data/purelib/services/performance.py +241 -0
  74. aichs-0.4.9.data/purelib/services/processes.py +420 -0
  75. aichs-0.4.9.data/purelib/services/project_memory.py +237 -0
  76. aichs-0.4.9.data/purelib/services/relative_time.py +38 -0
  77. aichs-0.4.9.data/purelib/services/ripgrep.py +56 -0
  78. aichs-0.4.9.data/purelib/services/shell_tool.py +11 -0
  79. aichs-0.4.9.data/purelib/services/skills.py +112 -0
  80. aichs-0.4.9.data/purelib/services/slash_commands.py +199 -0
  81. aichs-0.4.9.data/purelib/services/subprocess_utils.py +32 -0
  82. aichs-0.4.9.data/purelib/services/terminal_refs.py +121 -0
  83. aichs-0.4.9.data/purelib/services/terminal_session.py +179 -0
  84. aichs-0.4.9.data/purelib/services/text_search.py +305 -0
  85. aichs-0.4.9.data/purelib/services/tool_policy.py +305 -0
  86. aichs-0.4.9.data/purelib/services/tool_registry.py +1995 -0
  87. aichs-0.4.9.data/purelib/services/tools.py +1220 -0
  88. aichs-0.4.9.data/purelib/services/usage.py +112 -0
  89. aichs-0.4.9.data/purelib/services/user_terminal.py +116 -0
  90. aichs-0.4.9.data/purelib/services/workspace.py +84 -0
  91. aichs-0.4.9.data/purelib/services/workspace_snapshot.py +175 -0
  92. aichs-0.4.9.data/purelib/services/yuk.py +781 -0
  93. aichs-0.4.9.data/purelib/storage/__init__.py +0 -0
  94. aichs-0.4.9.data/purelib/storage/agent_canvas.py +316 -0
  95. aichs-0.4.9.data/purelib/storage/repository.py +651 -0
  96. aichs-0.4.9.data/purelib/storage/settings.py +348 -0
  97. aichs-0.4.9.data/purelib/storage/workspace_session.py +121 -0
  98. aichs-0.4.9.data/purelib/ui/__init__.py +0 -0
  99. aichs-0.4.9.data/purelib/ui/avatars.py +123 -0
  100. aichs-0.4.9.data/purelib/ui/main_window.py +1506 -0
  101. aichs-0.4.9.data/purelib/ui/markdown_html.py +74 -0
  102. aichs-0.4.9.data/purelib/ui/performance_monitor.py +39 -0
  103. aichs-0.4.9.data/purelib/ui/theme.py +2675 -0
  104. aichs-0.4.9.data/purelib/ui/widgets/__init__.py +0 -0
  105. aichs-0.4.9.data/purelib/ui/widgets/agent_canvas.py +8880 -0
  106. aichs-0.4.9.data/purelib/ui/widgets/agent_canvas_file_scope.py +64 -0
  107. aichs-0.4.9.data/purelib/ui/widgets/agent_canvas_inspector.py +441 -0
  108. aichs-0.4.9.data/purelib/ui/widgets/agent_canvas_items.py +1008 -0
  109. aichs-0.4.9.data/purelib/ui/widgets/agent_canvas_schema.py +319 -0
  110. aichs-0.4.9.data/purelib/ui/widgets/agent_canvas_view.py +221 -0
  111. aichs-0.4.9.data/purelib/ui/widgets/bubble.py +872 -0
  112. aichs-0.4.9.data/purelib/ui/widgets/chat_panel.py +5394 -0
  113. aichs-0.4.9.data/purelib/ui/widgets/code_card.py +138 -0
  114. aichs-0.4.9.data/purelib/ui/widgets/command_palette.py +152 -0
  115. aichs-0.4.9.data/purelib/ui/widgets/context_breakdown.py +125 -0
  116. aichs-0.4.9.data/purelib/ui/widgets/context_ring.py +95 -0
  117. aichs-0.4.9.data/purelib/ui/widgets/conversation_panel.py +768 -0
  118. aichs-0.4.9.data/purelib/ui/widgets/docs_dialog.py +377 -0
  119. aichs-0.4.9.data/purelib/ui/widgets/extension_contributions.py +198 -0
  120. aichs-0.4.9.data/purelib/ui/widgets/extension_panel_dialog.py +335 -0
  121. aichs-0.4.9.data/purelib/ui/widgets/extensions_dialog.py +1652 -0
  122. aichs-0.4.9.data/purelib/ui/widgets/file_mention_picker.py +107 -0
  123. aichs-0.4.9.data/purelib/ui/widgets/file_search_dialog.py +259 -0
  124. aichs-0.4.9.data/purelib/ui/widgets/file_viewer.py +3496 -0
  125. aichs-0.4.9.data/purelib/ui/widgets/git_changes_list.py +924 -0
  126. aichs-0.4.9.data/purelib/ui/widgets/git_panel.py +1128 -0
  127. aichs-0.4.9.data/purelib/ui/widgets/git_status_icon.py +75 -0
  128. aichs-0.4.9.data/purelib/ui/widgets/git_sync_buttons.py +64 -0
  129. aichs-0.4.9.data/purelib/ui/widgets/left_panel.py +2563 -0
  130. aichs-0.4.9.data/purelib/ui/widgets/markdown_browser.py +108 -0
  131. aichs-0.4.9.data/purelib/ui/widgets/mcp_dialog.py +1045 -0
  132. aichs-0.4.9.data/purelib/ui/widgets/message_input.py +898 -0
  133. aichs-0.4.9.data/purelib/ui/widgets/settings_dialog.py +2903 -0
  134. aichs-0.4.9.data/purelib/ui/widgets/skill_picker.py +121 -0
  135. aichs-0.4.9.data/purelib/ui/widgets/terminal_card.py +469 -0
  136. aichs-0.4.9.data/purelib/ui/widgets/terminal_panel.py +338 -0
  137. aichs-0.4.9.data/purelib/ui/widgets/text_search_dialog.py +284 -0
  138. aichs-0.4.9.data/purelib/ui/widgets/tool_approval_dialog.py +247 -0
  139. aichs-0.4.9.data/purelib/ui/widgets/window_chrome.py +382 -0
  140. aichs-0.4.9.data/purelib/ui/widgets/workbench_context.py +922 -0
  141. aichs-0.4.9.data/purelib/ui/widgets/workspace_dashboard.py +568 -0
  142. aichs-0.4.9.data/purelib/ui/win_caption.py +122 -0
  143. aichs-0.4.9.dist-info/METADATA +157 -0
  144. aichs-0.4.9.dist-info/RECORD +148 -0
  145. aichs-0.4.9.dist-info/WHEEL +5 -0
  146. aichs-0.4.9.dist-info/entry_points.txt +2 -0
  147. aichs-0.4.9.dist-info/licenses/LICENSE +21 -0
  148. aichs-0.4.9.dist-info/top_level.txt +8 -0
@@ -0,0 +1,38 @@
1
+ # Agent Canvas Restriction Model
2
+
3
+ The canvas graph is a planning and run contract, not a free-form diagram. Restrictions should make runs predictable without forcing the graph into artificial complexity.
4
+
5
+ ## Hard Constraints
6
+
7
+ These should fail instead of autocorrecting:
8
+
9
+ - Patch payloads must be valid and atomic.
10
+ - Node kind, title, status, and component details must be valid.
11
+ - Connections must match `connection_rules` exactly, including `source_port`.
12
+ - Scoped graph-agent edits must stay inside the selected goal graph.
13
+ - New nodes in a scoped edit must connect into that selected goal graph.
14
+ - The source goal for the current generation cannot be deleted or given an incoming edge.
15
+ - Directed cycles are blocked because graph runs require an acyclic branch.
16
+ - Files nodes must contain repo-like paths only, one per line.
17
+
18
+ ## Soft Quality Checks
19
+
20
+ These are graph-quality checks. Keep them simple, explain failures clearly, and autocorrect only when the fix is deterministic:
21
+
22
+ - Generated context should feed an action or decision.
23
+ - Generated multi-action plans should carry real graph value, not just a generic task list.
24
+ - Generated multi-action plans with DoD should include expected evidence/proof.
25
+ - Planning, design, research, or spec actions should feed implementation actions directly.
26
+
27
+ ## Current Autocorrections
28
+
29
+ - Missing crew on generated operation nodes defaults from the title/detail:
30
+ - research/survey/investigate/compare -> Scout
31
+ - implement/build/wire/code/engine/state/integration/frontend/backend/parser/evaluator/persist -> Coder
32
+ - design/architecture/plan/spec/requirements/UX/UI/model/strategy -> Architect
33
+ - otherwise -> Coder
34
+ - A patch with exactly one obvious planning/design/research/spec action and exactly one obvious implementation action gets an `operation.implement -> operation` connection when it is missing.
35
+
36
+ ## Do Not Autocorrect
37
+
38
+ Do not autocorrect cycles, scope escapes, invalid connection kinds, protected-goal deletion, incoming edges to the source goal, fake file paths, or ambiguous multi-node handoffs. Those need either a clear tool failure or an `ask_user` question.
@@ -0,0 +1,43 @@
1
+ # Compaction
2
+
3
+ Compaction is only context management. When a conversation grows past the
4
+ context budget, compaction cuts off an older prefix of the chat, asks the model
5
+ for a concise continuation summary, and keeps that summary plus recent verbatim
6
+ messages.
7
+
8
+ The compacted summary is optimized for the next model call: current goal,
9
+ important constraints, relevant files, decisions, tool results, blockers, and
10
+ the next step. It is not a durable archive.
11
+
12
+ ## Raw History
13
+
14
+ Compaction replaces the saved conversation messages with the compacted history.
15
+ The old raw prefix is not kept in the active conversation JSON.
16
+
17
+ Do not automatically save raw compaction archives by default. That would make
18
+ compaction a hidden retention mechanism instead of a straightforward context
19
+ cleanup operation.
20
+
21
+ ## Related State
22
+
23
+ Durable project memory, handoff notes, and large-output retention live outside
24
+ core compaction. Project memory is a separate built-in store with local, global,
25
+ and disabled scopes; see [Project Memory](project-memory.md). Compaction itself
26
+ stays focused on context reduction and resumability.
27
+
28
+ Extensions can still provide their own context-resilience workflows. Extension
29
+ tools, commands, context providers, and hooks receive `ctx.extension_id` and
30
+ `ctx.storage`, so they can share project-scoped state without hand-rolled paths.
31
+
32
+ For extension-owned workflows, use:
33
+
34
+ - JSON state for compact handoff notes, decisions, blockers, and next steps.
35
+ - Text artifacts for bulky tool output or reports via
36
+ `ctx.storage.save_artifact(name, content)`.
37
+ - Context snippets to re-inject only the small current handoff.
38
+ - Runtime compaction/resume directives when a continuation should happen at a
39
+ safe model-request boundary.
40
+
41
+ Artifacts are references, not model context by default. A handoff state entry
42
+ should point to a large artifact path and summarize why it matters instead of
43
+ injecting the full output into every turn.
@@ -0,0 +1,41 @@
1
+ # Configuration
2
+
3
+ By default, settings are stored in `~/.aichs/settings.json` (written by
4
+ **Settings** in the app). Set `AICHS_HOME` before launch to move all app-owned
5
+ user data, including settings, models, skills, conversations, extensions, MCP
6
+ state, and recent workspaces, to another directory.
7
+
8
+ | Key | Description |
9
+ |---|---|
10
+ | `anthropic_api_key` | Fallback if `ANTHROPIC_API_KEY` is unset |
11
+ | `openai_api_key` | Fallback if `OPENAI_API_KEY` is unset |
12
+ | `provider_api_keys` | Per-provider keys for built-in and custom providers |
13
+ | `system_prompt` | Overrides the default system prompt |
14
+ | `file_review_prompt_template` | Replaces the first line of **Ask File** drafts. Supports `{mention}` and `{path}` |
15
+ | `diagnostic_fix_prompt_template` | Replaces only the first line of diagnostic fix drafts. Supports `{mention}`, `{path}`, and `{line}` |
16
+ | `git_fix_prompt_template` | Replaces only the first line of git pull/push failure drafts. Supports `{action}`, `{label}`, `{repo}`, `{command}`, `{exit_code}`, and `{output}` |
17
+ | `compact_resume_prompt` | Default resume message used after compact-and-resume when no extension prompt is supplied |
18
+ | `auto_title_prompt_instructions` | Replaces the title-writing instructions; the first user message is attached automatically |
19
+ | `compaction_summary_guidance` | Optional additive guidance appended to the fixed compaction summary prompt |
20
+ | `project_memory_scope` | Project memory storage scope: `local` (default), `global`, or `disabled` |
21
+ | `archivist_prompt` | Replaces instructions for the built-in `/archivist` slash command; command name and tools stay fixed |
22
+ | `commit_message_prompt_addition` | Optional additive guidance appended to generated commit-message requests |
23
+ | `default_models` | Default model per provider |
24
+ | `theme` | `"dark"` or `"light"` |
25
+ | `font_size` | Chat font size (pt) |
26
+ | `trash_retention_days` | Days to keep deleted chats in Trash before permanent removal (default 14) |
27
+ | `compaction.reserve_tokens` | Optional. Tokens held back for the next reply before auto-compaction (omit to scale from each model's context window) |
28
+ | `compaction.keep_recent_tokens` | Optional. Recent message tokens to keep verbatim when compacting (omit to scale automatically) |
29
+
30
+ API keys can also be set via environment variables or **Settings -> Models** before launch.
31
+
32
+ Project memory defaults to local workspace storage at `.aichs/memory/project-memory.json`.
33
+ Set `project_memory_scope` to `global` to use `AICHS_HOME/memory/global-memory.json`,
34
+ or `disabled` to prevent project-memory reads and writes.
35
+
36
+ MCP servers are configured separately in standard `mcp.json` files; see
37
+ [MCP](mcp.md).
38
+
39
+ Organization governance is configured separately through signed files under
40
+ `AICHS_HOME/organization/`; see [Organization Governance](organization-governance.md)
41
+ for policy format, trust keys, runtime lock behavior, and audit logging.
@@ -0,0 +1,299 @@
1
+ # Custom models
2
+
3
+ aichs ships with Claude and OpenAI models built in. You can add any provider that exposes an **OpenAI-compatible API** by creating `AICHS_HOME/models.json` (default `~/.aichs/models.json`).
4
+
5
+ Custom providers appear automatically in the provider dropdown — no code changes needed.
6
+
7
+ ---
8
+
9
+ ## File format
10
+
11
+ ```json
12
+ {
13
+ "providers": {
14
+ "<provider-id>": {
15
+ "api": "openai-compatible",
16
+ "baseUrl": "https://...",
17
+ "apiKey": "ENV_VAR_NAME | !shell-command | literal-key",
18
+ "models": [
19
+ { "id": "model-id", "name": "Display Name" }
20
+ ]
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ | Field | Required | Description |
27
+ |---|---|---|
28
+ | `api` | yes (new providers) | Always `"openai-compatible"` for now |
29
+ | `baseUrl` | yes (new providers) | API base URL |
30
+ | `apiKey` | yes | Key resolution — see below |
31
+ | `models` | yes (new providers) | List of models to expose |
32
+ | `contextWindow` | no | Context size in **tokens** for compaction and the usage ring (defaults: Claude 180k, OpenAI-compatible 100k) |
33
+ | `temperature` | no | Top-level request temperature, `0.0` to `2.0` |
34
+ | `topK` | no | OpenAI-compatible `extra_body.top_k`, integer `-1` or greater |
35
+ | `minP` | no | OpenAI-compatible `extra_body.min_p`, `0.0` to `1.0` |
36
+
37
+ Generation fields can be set on a provider as defaults or on an individual model as an override. `topK` and `minP` are only sent for OpenAI-compatible requests.
38
+
39
+ ### API key formats
40
+
41
+ | Value | Resolved as |
42
+ |---|---|
43
+ | `"GEMINI_API_KEY"` | Read env var `$GEMINI_API_KEY` |
44
+ | `"!op read op://vault/gemini/key"` | Run shell command, use stdout |
45
+ | `"AIza..."` | Used literally (not recommended — use an env var) |
46
+
47
+ ### Overriding a built-in provider
48
+
49
+ Omit `api` and `models` to only override `baseUrl` or `apiKey` on `claude` / `openai`:
50
+
51
+ ```json
52
+ {
53
+ "providers": {
54
+ "openai": {
55
+ "baseUrl": "https://my-corporate-proxy.example.com/v1"
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Examples
64
+
65
+ ### Google Gemini
66
+
67
+ Google exposes an OpenAI-compatible endpoint for all Gemini models. See [current model IDs](https://ai.google.dev/gemini-api/docs/models) — Gemini 2.0 is deprecated; prefer 3.x.
68
+
69
+ Get an API key at [aistudio.google.com](https://aistudio.google.com).
70
+
71
+ ```json
72
+ {
73
+ "providers": {
74
+ "google": {
75
+ "api": "openai-compatible",
76
+ "baseUrl": "https://generativelanguage.googleapis.com/v1beta/openai/",
77
+ "apiKey": "GEMINI_API_KEY",
78
+ "models": [
79
+ { "id": "gemini-3.5-flash", "name": "Gemini 3.5 Flash" },
80
+ { "id": "gemini-3.1-pro-preview", "name": "Gemini 3.1 Pro" },
81
+ { "id": "gemini-3-flash-preview", "name": "Gemini 3 Flash" },
82
+ { "id": "gemini-3.1-flash-lite", "name": "Gemini 3.1 Flash Lite" }
83
+ ]
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ ```bash
90
+ export GEMINI_API_KEY=AIza...
91
+ ```
92
+
93
+ ---
94
+
95
+ ### Ollama (local models)
96
+
97
+ [Ollama](https://ollama.com) runs models on your machine with no API key or internet connection required.
98
+
99
+ **1. Install Ollama**
100
+
101
+ ```bash
102
+ # macOS
103
+ brew install ollama
104
+
105
+ # Linux
106
+ curl -fsSL https://ollama.com/install.sh | sh
107
+
108
+ # Windows — download the installer from https://ollama.com/download
109
+ ```
110
+
111
+ **2. Pull models**
112
+
113
+ ```bash
114
+ ollama pull llama3.1:8b # general purpose, fast
115
+ ollama pull qwen2.5-coder:7b # coding-focused, recommended
116
+ ollama pull qwen2.5-coder:32b # better quality, needs ~20 GB RAM
117
+ ollama pull deepseek-coder-v2 # strong at code, ~8 GB RAM
118
+ ```
119
+
120
+ Browse all available models at [ollama.com/library](https://ollama.com/library).
121
+
122
+ **3. Start the server** (runs automatically on macOS after install; on Linux run manually)
123
+
124
+ ```bash
125
+ ollama serve
126
+ ```
127
+
128
+ Ollama listens on `http://localhost:11434` by default.
129
+
130
+ **4. Add to `AICHS_HOME/models.json`**
131
+
132
+ ```json
133
+ {
134
+ "providers": {
135
+ "ollama": {
136
+ "api": "openai-compatible",
137
+ "baseUrl": "http://localhost:11434/v1",
138
+ "apiKey": "ollama",
139
+ "contextWindow": 32768,
140
+ "models": [
141
+ { "id": "llama3.1:8b", "name": "Llama 3.1 8B" },
142
+ { "id": "llama3.1:70b", "name": "Llama 3.1 70B" },
143
+ { "id": "qwen2.5-coder:7b", "name": "Qwen 2.5 Coder 7B" },
144
+ { "id": "qwen2.5-coder:32b", "name": "Qwen 2.5 Coder 32B" },
145
+ { "id": "mistral:7b", "name": "Mistral 7B" },
146
+ { "id": "deepseek-coder-v2", "name": "DeepSeek Coder V2" }
147
+ ]
148
+ }
149
+ }
150
+ }
151
+ ```
152
+
153
+ No API key needed — `"ollama"` is a placeholder the server ignores.
154
+
155
+ Set `contextWindow` to the size you configured in Ollama (or in **Settings → Models → Edit provider**). Without it, aichs assumes 100k like cloud OpenAI models.
156
+
157
+ > **Tip:** Only list models you have already pulled. Selecting an unpulled model will return an error from the Ollama server.
158
+
159
+ **Verify it works**
160
+
161
+ ```bash
162
+ curl http://localhost:11434/v1/models
163
+ ```
164
+
165
+ Should return a JSON list of your pulled models.
166
+
167
+ ---
168
+
169
+ ### DeepSeek
170
+
171
+ ```json
172
+ {
173
+ "providers": {
174
+ "deepseek": {
175
+ "api": "openai-compatible",
176
+ "baseUrl": "https://api.deepseek.com/v1",
177
+ "apiKey": "DEEPSEEK_API_KEY",
178
+ "models": [
179
+ { "id": "deepseek-chat", "name": "DeepSeek V3" },
180
+ { "id": "deepseek-reasoner", "name": "DeepSeek R1" }
181
+ ]
182
+ }
183
+ }
184
+ }
185
+ ```
186
+
187
+ ```bash
188
+ export DEEPSEEK_API_KEY=sk-...
189
+ ```
190
+
191
+ ---
192
+
193
+ ### OpenRouter
194
+
195
+ [OpenRouter](https://openrouter.ai) proxies 100+ models under a single API key.
196
+
197
+ ```json
198
+ {
199
+ "providers": {
200
+ "openrouter": {
201
+ "api": "openai-compatible",
202
+ "baseUrl": "https://openrouter.ai/api/v1",
203
+ "apiKey": "OPENROUTER_API_KEY",
204
+ "models": [
205
+ { "id": "meta-llama/llama-3.3-70b-instruct", "name": "Llama 3.3 70B" },
206
+ { "id": "mistralai/mistral-large", "name": "Mistral Large" },
207
+ { "id": "qwen/qwen-2.5-coder-32b-instruct", "name": "Qwen 2.5 Coder 32B" },
208
+ { "id": "google/gemini-3.1-pro-preview", "name": "Gemini 3.1 Pro (OR)" }
209
+ ]
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ ```bash
216
+ export OPENROUTER_API_KEY=sk-or-...
217
+ ```
218
+
219
+ ---
220
+
221
+ ### Proxy / corporate gateway
222
+
223
+ Route a built-in provider through your own endpoint without changing models:
224
+
225
+ ```json
226
+ {
227
+ "providers": {
228
+ "anthropic": {
229
+ "baseUrl": "https://gateway.corp.example.com/anthropic"
230
+ },
231
+ "openai": {
232
+ "baseUrl": "https://gateway.corp.example.com/openai"
233
+ }
234
+ }
235
+ }
236
+ ```
237
+
238
+ The existing model lists and API keys are preserved; only the base URL changes.
239
+
240
+ ---
241
+
242
+ ### API key from a password manager
243
+
244
+ Use `!command` to fetch keys at runtime instead of storing them in env vars:
245
+
246
+ ```json
247
+ {
248
+ "providers": {
249
+ "google": {
250
+ "api": "openai-compatible",
251
+ "baseUrl": "https://generativelanguage.googleapis.com/v1beta/openai/",
252
+ "apiKey": "!op read op://Personal/Gemini/credential",
253
+ "models": [
254
+ { "id": "gemini-3.5-flash", "name": "Gemini 3.5 Flash" }
255
+ ]
256
+ }
257
+ }
258
+ }
259
+ ```
260
+
261
+ Works with any CLI tool: `op` (1Password), `bw` (Bitwarden), `pass`, `security` (macOS Keychain), etc.
262
+
263
+ ---
264
+
265
+ ## Full example
266
+
267
+ A `AICHS_HOME/models.json` combining multiple providers:
268
+
269
+ ```json
270
+ {
271
+ "providers": {
272
+ "google": {
273
+ "api": "openai-compatible",
274
+ "baseUrl": "https://generativelanguage.googleapis.com/v1beta/openai/",
275
+ "apiKey": "GEMINI_API_KEY",
276
+ "models": [
277
+ { "id": "gemini-3.5-flash", "name": "Gemini 3.5 Flash" },
278
+ { "id": "gemini-3.1-pro-preview", "name": "Gemini 3.1 Pro" }
279
+ ]
280
+ },
281
+ "ollama": {
282
+ "api": "openai-compatible",
283
+ "baseUrl": "http://localhost:11434/v1",
284
+ "apiKey": "ollama",
285
+ "models": [
286
+ { "id": "qwen2.5-coder:32b", "name": "Qwen 2.5 Coder 32B" }
287
+ ]
288
+ },
289
+ "deepseek": {
290
+ "api": "openai-compatible",
291
+ "baseUrl": "https://api.deepseek.com/v1",
292
+ "apiKey": "DEEPSEEK_API_KEY",
293
+ "models": [
294
+ { "id": "deepseek-chat", "name": "DeepSeek V3" }
295
+ ]
296
+ }
297
+ }
298
+ }
299
+ ```