@ia-ccun/code-agent-cli 0.0.52-release → 0.0.53

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 (58) hide show
  1. package/config/agent/bin/README.md +102 -0
  2. package/config/agent/bin/fd.exe +0 -0
  3. package/config/agent/bin/rg.exe +0 -0
  4. package/config/agent/extensions/aicode-advisor.ts +13 -0
  5. package/config/agent/extensions/aicode-btw.ts +66 -14
  6. package/config/agent/extensions/aicode-cd.ts +834 -0
  7. package/config/agent/extensions/aicode-grillMe.ts +198 -0
  8. package/config/agent/extensions/aicode-pets.ts +362 -0
  9. package/config/agent/extensions/aicode-safety-guard.ts +552 -0
  10. package/config/agent/extensions/aicode-tips.ts +70 -16
  11. package/config/agent/extensions/aicode-todo-progress.ts +547 -0
  12. package/config/agent/extensions/custom.ts +93 -95
  13. package/config/agent/extensions/error-monitor.ts +1 -18
  14. package/config/agent/extensions/ponytail.ts +441 -0
  15. package/config/agent/extensions/tps.ts +87 -0
  16. package/config/agent/extensions/working-msg.ts +165 -50
  17. package/config/agent/help.md +0 -7
  18. package/config/agent/models.json +7 -7
  19. package/config/agent/settings.json +2 -1
  20. package/config/agent/skills/chroma/LICENSE +21 -0
  21. package/config/agent/skills/chroma/chroma-local/SKILL.md +165 -0
  22. package/config/agent/skills/chroma/chroma-local/cli.md +48 -0
  23. package/config/agent/skills/chroma/chroma-local/data-model.md +103 -0
  24. package/config/agent/skills/chroma/chroma-local/error-handling/python.md +166 -0
  25. package/config/agent/skills/chroma/chroma-local/error-handling/typescript.md +231 -0
  26. package/config/agent/skills/chroma/chroma-local/local-chroma/python.md +95 -0
  27. package/config/agent/skills/chroma/chroma-local/local-chroma/typescript.md +101 -0
  28. package/config/agent/skills/chroma/chroma-local/metadata/python.md +154 -0
  29. package/config/agent/skills/chroma/chroma-local/metadata/typescript.md +153 -0
  30. package/config/agent/skills/chroma/chroma-local/querying/python.md +147 -0
  31. package/config/agent/skills/chroma/chroma-local/querying/typescript.md +157 -0
  32. package/config/agent/skills/chroma/chroma-local/regex/python.md +69 -0
  33. package/config/agent/skills/chroma/chroma-local/regex/typescript.md +71 -0
  34. package/config/agent/skills/chroma/chroma-local/understanding-a-codebase.md +80 -0
  35. package/config/agent/skills/chroma/chroma-local/updating-deleting/python.md +159 -0
  36. package/config/agent/skills/chroma/chroma-local/updating-deleting/typescript.md +228 -0
  37. package/config/agent/skills/milvus-skill/LICENSE +202 -0
  38. package/config/agent/skills/milvus-skill/README.md +37 -0
  39. package/config/agent/skills/milvus-skill/SKILL.md +259 -0
  40. package/config/agent/skills/milvus-skill/references/collection.md +86 -0
  41. package/config/agent/skills/milvus-skill/references/database.md +24 -0
  42. package/config/agent/skills/milvus-skill/references/index.md +69 -0
  43. package/config/agent/skills/milvus-skill/references/partition.md +29 -0
  44. package/config/agent/skills/milvus-skill/references/patterns.md +150 -0
  45. package/config/agent/skills/milvus-skill/references/user-role.md +90 -0
  46. package/config/agent/skills/milvus-skill/references/vector.md +247 -0
  47. package/config/agent/skills/ponytail/SKILL.md +100 -0
  48. package/config/agent/skills/ponytail-audit/SKILL.md +40 -0
  49. package/config/agent/skills/ponytail-debt/SKILL.md +44 -0
  50. package/config/agent/skills/ponytail-help/SKILL.md +68 -0
  51. package/config/agent/skills/ponytail-review/SKILL.md +56 -0
  52. package/config/agent/skills/zread/README.md +115 -0
  53. package/config/agent/skills/zread/SKILL.md +103 -0
  54. package/config/agent/skills/zread/references/stdio-protocol.md +312 -0
  55. package/package.json +6 -5
  56. package/scripts/postinstall.js +58 -1
  57. package/config/agent/dangerous-patterns.json +0 -106
  58. package/config/agent/extensions/bash-check.ts +0 -227
@@ -2,11 +2,15 @@
2
2
  * @author: xujianjiang
3
3
  * working-message
4
4
  *
5
- * 自定义工作消息,格式类似 Claude Code: ✶ xxx… (时间 · tokens)
5
+ * 自定义工作消息,格式类似 Claude Code: ✶ xxx… (时间)
6
+ *
7
+ * 改进:使用 dispose 模式防止内存泄漏
8
+ * - 使用明确类型,避免 any
9
+ * - 实现可靠的定时器清理机制
10
+ * - 双重保障确保资源释放
6
11
  */
7
12
 
8
- import type { ExtensionAPI, TurnEndEvent } from "@earendil-works/pi-coding-agent";
9
- import type { AssistantMessage } from "@earendil-works/pi-ai";
13
+ import type { ExtensionAPI, ExtensionContext, TurnEndEvent } from "@earendil-works/pi-coding-agent";
10
14
 
11
15
  // 主题色 #49bccf
12
16
  const accentColor = "\x1b[38;2;73;188;207m";
@@ -44,10 +48,100 @@ const workingMessages = [
44
48
  "Algorithm", "Architecture", "Database", "Cache", "Queue", "Microservice",
45
49
  ];
46
50
 
47
- let intervalId: ReturnType<typeof setInterval> | null = null;
48
- let startTime = 0;
49
- let totalTokens = 0;
51
+ /**
52
+ * 工作消息状态管理器 - 使用 dispose 模式
53
+ * 确保定时器和 UI 引用的生命周期管理,防止内存泄漏
54
+ */
55
+ class WorkingMessageStateManager {
56
+ // ✅ 使用明确类型,避免 any
57
+ private _ui: ExtensionContext['ui'] | null = null;
58
+ private _intervalId: ReturnType<typeof setInterval> | null = null;
59
+ private _startTime: number = 0;
60
+ private _disposed: boolean = false;
61
+
62
+ // Getter 方法
63
+ get ui(): ExtensionContext['ui'] | null {
64
+ return this._ui;
65
+ }
66
+
67
+ get intervalId(): ReturnType<typeof setInterval> | null {
68
+ return this._intervalId;
69
+ }
70
+
71
+ get startTime(): number {
72
+ return this._startTime;
73
+ }
74
+
75
+ isDisposed(): boolean {
76
+ return this._disposed;
77
+ }
78
+
79
+ // Setter 方法(检查 disposed 状态)
80
+ setUI(ui: ExtensionContext['ui'] | null): void {
81
+ if (this._disposed) {
82
+ console.warn('[working-msg] State already disposed, cannot set UI');
83
+ return;
84
+ }
85
+ this._ui = ui;
86
+ }
87
+
88
+ setInterval(intervalId: ReturnType<typeof setInterval> | null): void {
89
+ if (this._disposed) {
90
+ console.warn('[working-msg] State already disposed, cannot set interval');
91
+ return;
92
+ }
93
+ this._intervalId = intervalId;
94
+ }
95
+
96
+ setStartTime(startTime: number): void {
97
+ if (this._disposed) {
98
+ console.warn('[working-msg] State already disposed, cannot set start time');
99
+ return;
100
+ }
101
+ this._startTime = startTime;
102
+ }
103
+
104
+ /**
105
+ * dispose() - 清理所有资源
106
+ * ✅ 双重保障:清理定时器 + 清理 UI 引用
107
+ * ✅ disposed 标记防止重复清理
108
+ */
109
+ dispose(): void {
110
+ if (this._disposed) {
111
+ return; // 防止重复 dispose
112
+ }
50
113
 
114
+ // ✅ 清理定时器(双重保障)
115
+ if (this._intervalId) {
116
+ clearInterval(this._intervalId);
117
+ this._intervalId = null;
118
+ }
119
+
120
+ // ✅ 清理 UI 引用
121
+ if (this._ui) {
122
+ try {
123
+ this._ui.setWorkingMessage(undefined);
124
+ } catch (error) {
125
+ // ✅ 忽略错误,确保清理继续
126
+ console.warn('[working-msg] Error clearing working message:', error);
127
+ }
128
+ this._ui = null;
129
+ }
130
+
131
+ this._disposed = true;
132
+ }
133
+
134
+ /**
135
+ * reset() - 重置状态(用于新的 turn)
136
+ */
137
+ reset(): void {
138
+ this.dispose(); // 先清理旧资源
139
+ this._disposed = false; // 重置 disposed 标记
140
+ this._startTime = 0;
141
+ }
142
+ }
143
+
144
+ // 工具函数
51
145
  function getNextMessage(): string {
52
146
  const randomIndex = Math.floor(Math.random() * workingMessages.length);
53
147
  return workingMessages[randomIndex];
@@ -60,56 +154,77 @@ function formatTime(seconds: number): string {
60
154
  return `${mins} m ${secs} s`;
61
155
  }
62
156
 
63
- function formatTokens(tokens: number): string {
64
- if (tokens < 1000) return `${tokens}`;
65
- return `${(tokens / 1000).toFixed(1)}k`;
157
+ /**
158
+ * ✅ 改进的定时器逻辑
159
+ * - 不依赖 try-catch
160
+ * - 检查 disposed 状态
161
+ * - 使用 state.ui(明确类型)
162
+ */
163
+ function startInterval(state: WorkingMessageStateManager): void {
164
+ if (state.isDisposed() || !state.ui) {
165
+ return;
166
+ }
167
+
168
+ const intervalId = setInterval(() => {
169
+ // ✅ 每次执行前检查 disposed 和 UI 状态
170
+ if (state.isDisposed() || !state.ui) {
171
+ // ✅ 自动清理
172
+ state.dispose();
173
+ return;
174
+ }
175
+
176
+ // ✅ 安全执行(明确类型)
177
+ const elapsed = Math.floor((Date.now() - state.startTime) / 1000);
178
+ const timeStr = formatTime(elapsed);
179
+ const msg = `${accentColor} ✶ ${getNextMessage()}…${reset} (${timeStr})`;
180
+
181
+ try {
182
+ state.ui.setWorkingMessage(msg);
183
+ } catch (error) {
184
+ // ✅ 如果 UI 调用失败,自动清理
185
+ console.warn('[working-msg] UI call failed, disposing:', error);
186
+ state.dispose();
187
+ }
188
+ }, 3000);
189
+
190
+ state.setInterval(intervalId);
66
191
  }
67
192
 
193
+ /**
194
+ * 扩展主函数 - 使用 dispose 模式管理状态
195
+ */
68
196
  export default function workingMessageExtension(pi: ExtensionAPI) {
69
- // turn_start 时开始循环切换消息
197
+ // ✅ 单一状态管理器
198
+ const state = new WorkingMessageStateManager();
199
+
200
+ // ✅ session_shutdown - 清理所有资源
201
+ pi.on("session_shutdown", async (_event, ctx) => {
202
+ state.dispose();
203
+ });
204
+
205
+ // ✅ turn_start - 初始化状态并启动定时器
70
206
  pi.on("turn_start", async (_event, ctx) => {
71
- if (!ctx.ui) return;
72
-
73
- // 记录开始时间
74
- startTime = Date.now();
75
- totalTokens = 0;
76
-
77
- // 立即设置第一条
78
- const updateMessage = () => {
79
- const elapsed = Math.floor((Date.now() - startTime) / 1000);
80
- const timeStr = formatTime(elapsed);
81
- const tokensStr = formatTokens(totalTokens);
82
- // ✶ 和单词显示为主题色
83
- const msg = `${accentColor} ✶ ${getNextMessage()}…${reset} (${timeStr} · ↓ ${tokensStr} tokens)`;
84
- ctx.ui?.setWorkingMessage(msg);
85
- };
86
-
87
- updateMessage();
88
-
89
- // 每3秒更新一次
90
- if (!intervalId) {
91
- intervalId = setInterval(() => {
92
- // 获取当前 tokens 使用量
93
- for (const entry of ctx.sessionManager.getBranch()) {
94
- if (entry.type === "message" && (entry as any).message?.role === "assistant") {
95
- const msg = (entry as any).message as AssistantMessage;
96
- if (msg.usage?.output) {
97
- totalTokens = msg.usage.output;
98
- }
99
- }
100
- }
101
- updateMessage();
102
- }, 3000);
207
+ if (!ctx.ui) {
208
+ return;
103
209
  }
210
+
211
+ // ✅ 重置状态(清理旧资源)
212
+ state.reset();
213
+ state.setUI(ctx.ui); // ✅ 明确类型:ExtensionContext['ui']
214
+ state.setStartTime(Date.now());
215
+
216
+ // 设置第一条消息
217
+ const elapsed = Math.floor((Date.now() - state.startTime) / 1000);
218
+ const timeStr = formatTime(elapsed);
219
+ const msg = `${accentColor} ✶ ${getNextMessage()}…${reset} (${timeStr})`;
220
+ state.ui?.setWorkingMessage(msg);
221
+
222
+ // ✅ 启动定时器
223
+ startInterval(state);
104
224
  });
105
225
 
106
- // turn结束时停止
226
+ // ✅ turn_end - 清理所有资源
107
227
  pi.on("turn_end", async (_event: TurnEndEvent, ctx) => {
108
- if (intervalId) {
109
- clearInterval(intervalId);
110
- intervalId = null;
111
- }
112
- // 恢复默认消息
113
- ctx.ui?.setWorkingMessage(undefined);
228
+ state.dispose();
114
229
  });
115
- }
230
+ }
@@ -470,13 +470,6 @@ aicode-cli --verbose
470
470
  | `--theme <name>` | 指定主题 |
471
471
  | `--model <name>` | 指定模型 |
472
472
  | `--clear` | 启动时清理会话 |
473
-
474
- ### 相关资源
475
-
476
- - **项目仓库**: https://github.com/ia-ccun/code-agent-cli
477
- - **npm 包**: https://www.npmjs.com/package/@ia-ccun/code-agent-cli
478
- - **pi-coding-agent**: 底层 Agent 框架
479
-
480
473
  ---
481
474
 
482
475
  *世界那么哒 · AI 实践落地 @2026*
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "providers": {
3
- "local": {
4
- "name": "local",
3
+ "aicode": {
4
+ "name": "aicode llm",
5
5
  "baseUrl": "https://ai-llm.cc.com/v1",
6
6
  "api": "openai-completions",
7
- "apiKey": "你自己的APIKEY",
7
+ "apiKey": "你自己的APIKEY sk-xxxxxxxxxxxxxxxxxx",
8
8
  "headers": {
9
9
  "User-Agent": "${VERSION}"
10
10
  },
11
11
  "models": [
12
12
  {
13
- "id": "GLM-4.7-W8A8",
14
- "name": "GLM4.7",
15
- "contextWindow": 120000,
13
+ "id": "qwen3.6-35b-a3b",
14
+ "name": "qwen3.6",
15
+ "contextWindow": 128000,
16
16
  "maxTokens": 100000,
17
- "reasoning": true,
17
+ "reasoning": false,
18
18
  "input": ["text"],
19
19
  "cost": {
20
20
  "input": 5,
@@ -10,7 +10,8 @@
10
10
  "~/.aicode-cli/agent/extensions/custom-footer.ts",
11
11
  "~/.aicode-cli/agent/extensions/custom.ts",
12
12
  "~/.aicode-cli/agent/extensions/review.ts",
13
- "~/.aicode-cli/agent/extensions/working-msg.ts"
13
+ "~/.aicode-cli/agent/extensions/working-msg.ts",
14
+ "-extensions/aicode-pets.ts"
14
15
  ],
15
16
  "packages":[
16
17
  "npm:pi-subagents@0.17.1",
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chroma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,165 @@
1
+ ---
2
+ name: chroma-local
3
+ description: Use when the user needs self-hosted or local Chroma for semantic search, including `ChromaClient`, `HttpClient`, or Python `EphemeralClient`, local persistence, Docker or `chroma run`, or OSS Chroma without Chroma Cloud features.
4
+ ---
5
+
6
+ ## Instructions
7
+
8
+ Determine these before writing code. Prefer discovering them from the repo and the user request. Ask only when the choice materially changes the implementation.
9
+
10
+ 1. **Runtime shape**
11
+ - Are they connecting to a running local server, embedding Chroma into tests, or setting up local development from scratch?
12
+ - Decide whether they need `chroma run`, a Docker or service command, `HttpClient` or `ChromaClient`, or Python `EphemeralClient`.
13
+
14
+ 2. **Persistence**
15
+ - Persistent local data: choose an intentional data path.
16
+ - Disposable test data: use defaults or a temp directory.
17
+
18
+ 3. **Embedding model**
19
+ - Reuse the app's existing embedding provider when possible.
20
+ - Otherwise default to `@chroma-core/default-embed` in TypeScript or the standard local default in Python.
21
+ - If the user explicitly wants OpenAI embeddings in TypeScript, install and use `@chroma-core/openai`.
22
+
23
+ 4. **Indexed data shape**
24
+ - Determine what is being indexed, how it should be chunked, and what metadata is needed for filtering and updates.
25
+
26
+ ## Routing
27
+
28
+ - **Existing local server**
29
+ - Confirm host and port before changing client code.
30
+ - Validate the server is reachable before assuming collections are missing.
31
+
32
+ - **Fresh local development**
33
+ - Add a local startup path such as `chroma run` or the repo's existing Docker or service command.
34
+ - Default to `localhost:8000` unless the repo already uses another address.
35
+
36
+ - **Python tests or disposable local workflows**
37
+ - Prefer `EphemeralClient` when persistence is unnecessary.
38
+ - Call out that data is lost when the process exits.
39
+
40
+ - **Persistent local development**
41
+ - Use a stable data path and make persistence explicit in code or config.
42
+ - Do not silently switch between ephemeral and persistent modes.
43
+
44
+ - **Search integration work**
45
+ - Use `getOrCreateCollection()` in TypeScript or `get_or_create_collection()` in Python.
46
+ - Design document IDs and metadata so upserts and deletes are straightforward.
47
+ - Batch writes when syncing large datasets.
48
+
49
+ ## Ask vs proceed
50
+
51
+ **Ask first:**
52
+ - Embedding model choice (cost and quality implications)
53
+ - Whether they need persistent local data
54
+ - How they are starting the local server
55
+ - Multi-tenant data isolation strategy
56
+
57
+ **Proceed with sensible defaults:**
58
+ - Use `getOrCreateCollection()` (TypeScript) / `get_or_create_collection()` (Python)
59
+ - Use cosine similarity (most common)
60
+ - Chunk size under 8KB
61
+ - Store source IDs in metadata for updates/deletes
62
+ - Use a local server on `localhost:8000` unless the repo already configures another address or is using Python `EphemeralClient`
63
+
64
+ ## What to validate
65
+
66
+ - Correct client import (`ChromaClient`, `HttpClient`, or `Client`)
67
+ - Embedding function package is installed (TypeScript)
68
+ - Local server is reachable before assuming collections are missing
69
+ - Local path and persistence mode are intentional
70
+
71
+ ## Implementation notes
72
+
73
+ - Local Chroma is the right default for development, tests, and self-hosted deployments.
74
+ - OSS Chroma does not include Chroma Cloud-only features such as `Schema()` and `Search()`.
75
+ - If the user asks for hybrid dense and sparse retrieval, treat that as a likely Chroma Cloud requirement unless the repo already implements an OSS workaround.
76
+ - For open source Chroma, dense retrieval with a single embedding function is the normal baseline.
77
+
78
+ ## Minimal patterns
79
+
80
+ Start a local Chroma server when the repo needs one:
81
+
82
+ ```bash
83
+ chroma run
84
+ ```
85
+
86
+ Default address: `localhost:8000`.
87
+
88
+ TypeScript local client:
89
+
90
+ ```typescript
91
+ import { ChromaClient } from 'chromadb';
92
+ import { DefaultEmbeddingFunction } from '@chroma-core/default-embed';
93
+
94
+ const client = new ChromaClient();
95
+
96
+ const embeddingFunction = new DefaultEmbeddingFunction();
97
+ const collection = await client.getOrCreateCollection({
98
+ name: 'my_collection',
99
+ embeddingFunction,
100
+ });
101
+
102
+ // Add documents
103
+ await collection.add({
104
+ ids: ['doc1', 'doc2'],
105
+ documents: ['First document text', 'Second document text'],
106
+ });
107
+
108
+ // Query
109
+ const results = await collection.query({
110
+ queryTexts: ['search query'],
111
+ nResults: 5,
112
+ });
113
+ ```
114
+
115
+ Python local client:
116
+
117
+ ```python
118
+ import chromadb
119
+
120
+ client = chromadb.HttpClient(host="localhost", port=8000)
121
+
122
+ collection = client.get_or_create_collection(name="my_collection")
123
+
124
+ # Add documents
125
+ collection.add(
126
+ ids=["doc1", "doc2"] ,
127
+ documents=["First document text", "Second document text"],
128
+ )
129
+
130
+ # Query
131
+ results = collection.query(
132
+ query_texts=["search query"],
133
+ n_results=5,
134
+ )
135
+ ```
136
+
137
+ ## Learn More
138
+
139
+ Fetch Chroma's `llms.txt` only when you need API or product details that are not already in the repo or this skill: https://docs.trychroma.com/llms.txt
140
+
141
+ ## Available Topics
142
+
143
+ ### Typescript
144
+
145
+ - [Chroma Regex Filtering](./regex/typescript.md) - Learn how to use regex filters in Chroma queries
146
+ - [Query and Get](./querying/typescript.md) - Query and Get Data from Chroma Collections
147
+ - [Metadata](./metadata/typescript.md) - Store and query metadata, including filters and array values
148
+ - [Updating and Deleting](./updating-deleting/typescript.md) - Update existing documents and delete data from collections
149
+ - [Error Handling](./error-handling/typescript.md) - Handling errors and failures when working with Chroma
150
+ - [Local Chroma](./local-chroma/typescript.md) - How to run and use local chroma
151
+
152
+ ### Python
153
+
154
+ - [Chroma Regex Filtering](./regex/python.md) - Learn how to use regex filters in Chroma queries
155
+ - [Query and Get](./querying/python.md) - Query and Get Data from Chroma Collections
156
+ - [Metadata](./metadata/python.md) - Store and query metadata, including filters and array values
157
+ - [Updating and Deleting](./updating-deleting/python.md) - Update existing documents and delete data from collections
158
+ - [Error Handling](./error-handling/python.md) - Handling errors and failures when working with Chroma
159
+ - [Local Chroma](./local-chroma/python.md) - How to run and use local chroma
160
+
161
+ ## General
162
+
163
+ - [Data Model](./data-model.md) - An overview of how Chroma stores data
164
+ - [Integrating Chroma into an existing system](./understanding-a-codebase.md) - Guidance for adding Chroma search to an existing application
165
+ - [Chroma CLI](./cli.md) - Starting and managing a local open source Chroma server from the CLI
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: Chroma CLI
3
+ description: Starting and managing a local open source Chroma server from the CLI
4
+ ---
5
+
6
+ ## Chroma CLI
7
+
8
+ The Chroma CLI can also be used for local open source Chroma workflows. This topic focuses on starting and managing a local server, not Chroma Cloud account setup.
9
+
10
+ ### Install
11
+
12
+ ```bash
13
+ pip install chromadb
14
+ ```
15
+
16
+ ### Start a local server
17
+
18
+ Run Chroma locally on the default address:
19
+
20
+ ```bash
21
+ chroma run
22
+ ```
23
+
24
+ This starts a server on `localhost:8000`.
25
+
26
+ ### Choose a persistent data directory
27
+
28
+ Store local data in a specific path instead of the default working directory:
29
+
30
+ ```bash
31
+ chroma run --path ./chroma-data
32
+ ```
33
+
34
+ ### Change the port
35
+
36
+ If another process already uses port `8000`, pick another one:
37
+
38
+ ```bash
39
+ chroma run --port 8001
40
+ ```
41
+
42
+ Update your client code to match the chosen host and port.
43
+
44
+ ### Local workflow tips
45
+
46
+ - Use a dedicated data directory per environment so dev and test data do not mix.
47
+ - In tests, use disposable directories or clear collections between runs.
48
+ - Check that the server is running before debugging client-side collection errors.
@@ -0,0 +1,103 @@
1
+ ---
2
+ name: Data Model
3
+ description: An overview of how Chroma stores data
4
+ ---
5
+
6
+ ## Data Model
7
+
8
+ Use this reference when designing collection layout, chunking, IDs, metadata, and filtering for Chroma.
9
+
10
+ ### Core concepts
11
+
12
+ **Collections** are the top-level containers, similar to tables in a relational database. Each collection has its own embedding configuration and indexes.
13
+
14
+ **Documents** are the searchable units within a collection. Each document has:
15
+ - **ID** - A unique string identifier
16
+ - **Content** - The text that gets embedded and searched
17
+ - **Embedding** - The vector representation
18
+ - **Metadata** - Key-value pairs for filtering
19
+
20
+ ## Chunking
21
+
22
+ Most real-world data is too large to fit in a single document. Chunking splits content into searchable pieces.
23
+
24
+ ### Chunking strategy
25
+
26
+ **Recommended chunk size:** Keep chunks comfortably below product limits and small enough to preserve search precision and context. Generally, 8KB or less is a good default starting point.
27
+
28
+ **Good chunking preserves meaning:**
29
+ - Split at natural boundaries (paragraphs, sentences, sections)
30
+ - Don't cut mid-sentence or mid-word
31
+ - Include enough context for the chunk to be meaningful on its own
32
+
33
+ **Determine from the repo or ask if ambiguous:**
34
+ - What type of content are they indexing?
35
+ - Are there natural boundaries (chapters, sections, records)?
36
+ - How much context does a search result need to be useful?
37
+
38
+ ### Tracking chunks with metadata
39
+
40
+ When a single source document becomes multiple chunks, use metadata to track the relationship:
41
+
42
+ ```
43
+ {
44
+ "source_id": "post-123", // ID in the primary database
45
+ "source_type": "blog_post", // Type of content
46
+ "chunk_index": 0, // Position in sequence
47
+ "total_chunks": 3 // Total chunks from this source
48
+ }
49
+ ```
50
+
51
+ This approach is better than encoding information in the document ID because:
52
+ - IDs can be simple UUIDs
53
+ - Metadata is filterable
54
+ - Updates and deletes are easier (filter by `source_id`)
55
+
56
+ ## Collection organization
57
+
58
+ For multi-tenant applications, separate collections per tenant are a strong default when isolation, deletion, and search quality matter more than minimizing collection count.
59
+
60
+ **Why this works better:**
61
+ - Nearest neighbor search is more accurate with fewer candidates
62
+ - Lower latency with smaller collections
63
+ - Natural isolation between tenants
64
+ - Easy to delete all tenant data by dropping the collection
65
+
66
+ **Example:** A knowledge base SaaS might have collections like `kb_customer_123`, `kb_customer_456`, etc.
67
+
68
+ **Determine from the repo or ask if ambiguous:** What's the smallest logical unit of data isolation in their application?
69
+
70
+ ## Filtering
71
+
72
+ Metadata filtering reduces the candidate set before vector search runs, making queries faster and more precise.
73
+
74
+ ### Filter operators
75
+
76
+ | Operator | Description | Types |
77
+ |----------|-------------|-------|
78
+ | `$eq` | Equal (default) | string, int, bool |
79
+ | `$ne` | Not equal | string, int, bool |
80
+ | `$gt`, `$gte` | Greater than (or equal) | int |
81
+ | `$lt`, `$lte` | Less than (or equal) | int |
82
+ | `$in` | In list | string, int |
83
+ | `$nin` | Not in list | string, int |
84
+ | `$and`, `$or` | Logical combinators | filter arrays |
85
+ | `$contains`, `$not_contains` | Check within arrays | arrays of string, int, bool |
86
+
87
+ ### Document content filtering
88
+
89
+ Beyond metadata, you can filter on the document text itself using `where_document`:
90
+ - `$contains` - Full-text substring search
91
+ - `$regex` - Regular expression matching
92
+
93
+ ## Dense vs sparse vectors
94
+
95
+ **Dense vectors** (default) are produced by neural embedding models. They capture semantic meaning, so "car" and "automobile" will be similar.
96
+
97
+ **Sparse vectors** (BM25, SPLADE) are high-dimensional but mostly zeros. They excel at exact keyword matching.
98
+
99
+ **Hybrid search** combines both, often outperforming either alone. Chroma Cloud supports hybrid search through the Schema and Search APIs.
100
+
101
+ ### Important note
102
+
103
+ When creating collections, `get_or_create_collection()` accepts either an `embedding_function` OR a `schema`, but not both. Use Schema when you need multiple indexes or sparse embeddings.