codeer-cli 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.
@@ -0,0 +1,36 @@
1
+ # Python bytecode and caches
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Python build and packaging output
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .eggs/
11
+
12
+ # Test, type-checker, and linter caches
13
+ .pytest_cache/
14
+ .ruff_cache/
15
+ .mypy_cache/
16
+ .coverage
17
+ htmlcov/
18
+
19
+ # Virtual environments and local environment files
20
+ .venv/
21
+ venv/
22
+ env/
23
+ .env
24
+ .env.*
25
+ !.env.example
26
+ !.env.sample
27
+ session.env
28
+
29
+ # OS and editor local files
30
+ .DS_Store
31
+ Thumbs.db
32
+ *.swp
33
+ *.swo
34
+
35
+ # Local assistant/tool settings
36
+ .claude/settings.local.json
@@ -0,0 +1,431 @@
1
+ # Codeer API reference — CLI maintainers
2
+
3
+ > This file is the request-shape reference for maintaining `codeer-cli`.
4
+
5
+ The 9 stages below mirror the user-docs lifecycle (`agent-creation` →
6
+ `optimization-loop` → `publish`). Every path is under `/api/v1/`. All endpoints
7
+ authenticate via `x-api-key` from `CODEER_API_KEY`.
8
+
9
+ Envelope: successful responses look like
10
+ `{"error_code": 0, "message": "", "pagination": null, "data": <payload>}`.
11
+ The client unwraps `data` automatically; errors raise `CodeerError`.
12
+
13
+ **Environment config split:**
14
+ Auth means `CODEER_API_KEY`; it comes from the process environment only.
15
+ `CODEER_API_BASE` defaults to `https://api.codeer.ai` and is only needed for
16
+ local, beta, or preview. Do not store API keys in repo files or paste them into
17
+ agent chat.
18
+
19
+ Workspace and organization scope come from the workspace API-key virtual user's
20
+ profile (`default_workspace_id` and `default_organization_id`). The CLI does
21
+ not use `--workspace`, `--org`, `CODEER_WORKSPACE_ID`, or
22
+ `CODEER_ORGANIZATION_ID`. `CODEER_AGENT_ID` is still optional for commands that
23
+ need a default agent.
24
+
25
+ **Pagination conventions:**
26
+ - `/histories` uses **`limit` + `offset`** (NOT `page` / `page_size`).
27
+ Default in `histories.list()` is `limit=500`. Backend hard-cap may be
28
+ lower — check the response length.
29
+ - `/agents/{id}/histories`, `/eval/agents/{id}/cases`, `/eval/evaluators` all
30
+ return everything in one shot today (no pagination).
31
+ - `order_by` defaults to `"desc"` (most recent first) on endpoints that
32
+ support it.
33
+
34
+ ## Stage 1 — Author agent
35
+
36
+ | Method & path | Purpose |
37
+ | --- | --- |
38
+ | `POST /agents` | Create a new agent |
39
+ | `GET /agents?wid=<ws>` | List agents in a workspace |
40
+ | `GET /agents/all?wid=<ws>` or `?oid=<org>` | List across workspaces/org |
41
+ | `GET /agents/{id}` | Read current state |
42
+ | `PUT /agents/{id}` | Update — *auto-creates a new AgentHistory version* |
43
+ | `DELETE /agents/{id}` | Delete |
44
+
45
+ `unified_tools[]` fields: `type` ∈
46
+ {`knowledge_base`, `web_search`, `call_agent`, `image_generation`,
47
+ `request_form`, `payment`, `memory`, `http_request`}, plus type-specific fields
48
+ like `knowledge_node_ids`, `domain`, `agent_id`, `http_request` config.
49
+
50
+ Limits: 10 tools per agent, ≤5 `call_agent`, ≤1 `memory`.
51
+
52
+ ## Stage 2 — Knowledge bases
53
+
54
+ Base path: `/organizations/{org_id}/workspaces/{ws_id}/knowledge_bases`
55
+
56
+ | Method & path | Purpose |
57
+ | --- | --- |
58
+ | `GET .../nodes` | List KB/folder/file tree (supply `parent_id` to scope) |
59
+ | `POST .../nodes` | Create a KB (type=`knowledge_base`, no parent) or folder (parent_id set) |
60
+ | `PATCH .../nodes/{node_id}` | Rename a node |
61
+ | `DELETE .../nodes/{node_id}` | Delete a node and its descendants |
62
+ | `POST .../{kb_id}/files/upload` | Upload file (multipart) — kicks off async indexing |
63
+ | `POST .../files/status` | Batch-poll indexing status by node ID |
64
+ | `GET .../{kb_id}/nodes/{node_id}/content` | Read a file's extracted content |
65
+
66
+ Attach KB files to an agent by listing their node IDs in the agent's
67
+ `unified_tools[].knowledge_node_ids`.
68
+
69
+ ## Stage 3 — Live Test on a specific version
70
+
71
+ | Method & path | Purpose |
72
+ | --- | --- |
73
+ | `POST /chats` | Create a new chat session bound to an agent |
74
+ | `POST /chats/{chat_id}/messages` | Send a message; **SSE stream** of tool calls + reasoning + final text |
75
+ | `GET /chats/{chat_id}/messages` | Read historical messages for a chat |
76
+ | `POST /chats/{chat_id}/regenerate` | Re-run the last turn |
77
+ | `POST /chats/{chat_id}/messages/{msg_id}/feedbacks` | Thumbs up/down on a reply |
78
+
79
+ `POST /chats/.../messages` requires `agent_history_id` — this is the key hook
80
+ for the apply → test → publish workflow. Pass the draft `AgentHistory.id` from
81
+ `PUT /agents/{id}` to test an unpublished version.
82
+
83
+ ## Stage 4 — Version management
84
+
85
+ | Method & path | Purpose |
86
+ | --- | --- |
87
+ | `GET /agents/{id}/histories` | List every AgentHistory version, with `was_published` flags |
88
+ | `GET /agents/{id}/histories/{history_id}` | Read a specific version |
89
+ | `GET /agents/{id}/impact` | List downstream agents that `call_agent` this one |
90
+
91
+ ## Stage 5 — Evaluation
92
+
93
+ | Method & path | Purpose |
94
+ | --- | --- |
95
+ | `POST /eval/cases` | Create case (`input`, `expected_output?`, `rubric?`); rubric = user-docs "Standard" |
96
+ | `GET /eval/agents/{agent_id}/cases` | List cases for an agent |
97
+ | `GET /eval/cases/{case_id}` | Read one |
98
+ | `PUT /eval/cases/{case_id}` | Update |
99
+ | `DELETE /eval/cases/{case_id}` | Delete |
100
+ | `POST /eval/cases/upload-csv` | Bulk import |
101
+ | `POST /eval/cases/bulk` | Bulk delete |
102
+ | `POST /eval/evaluators` | Create evaluator (LLM-judge via `system_prompt_template`) |
103
+ | `GET /eval/evaluators?wid=<ws>` | List evaluators |
104
+ | `PUT /eval/evaluators/{id}` | Update |
105
+ | `DELETE /eval/evaluators/{id}` | Delete |
106
+ | `POST /eval/trigger` | Run a set of cases with evaluators, optionally pinned to `agent_history_id` |
107
+ | `POST /eval/stop` | Cancel running case+evaluator combo |
108
+ | `POST /eval/rubric` | Set/override the rubric for one (case, evaluator) — write-only |
109
+ | `POST /eval/rubrics/batch` | **Read** rubrics for a batch of (case, evaluator) pairs |
110
+
111
+ ## Stage 6 — Diagnose + update
112
+
113
+ | Method & path | Purpose |
114
+ | --- | --- |
115
+ | `POST /eval/results/batch` | Read per-case scores + `reason` + generated `output` + persisted tool trace for one `agent_history_id` |
116
+ | `PUT /agents/{id}` | Apply the fix — creates the next AgentHistory draft |
117
+
118
+ Iterate: trigger → results → PUT → trigger again, staying on drafts.
119
+
120
+ `POST /eval/results/batch` body shape:
121
+
122
+ ```json
123
+ {
124
+ "agent_history_id": "<uuid>",
125
+ "workspace_id": "<uuid>",
126
+ "case_ids": ["<uuid>", ...],
127
+ "evaluator_id": "<uuid>", // singular — NOT evaluator_ids
128
+ "include_output": true, // optional, default true
129
+ "include_reasoning_steps": true // include persisted tool args/results/timing
130
+ }
131
+ ```
132
+
133
+ Both `agent_history_id` and `workspace_id` are required at the body level
134
+ (passing `wid=...` as a query param doesn't count). Cases that haven't been
135
+ evaluated yet on that history come back with `score=null` rather than being
136
+ omitted, so use `null`-checks instead of length comparisons.
137
+
138
+ Pass `include_reasoning_steps=true` to include persisted tool/reasoning steps.
139
+ The rows then include `reasoning_steps[]` with `id`, `type`, `args`, `result`,
140
+ `start_at`, and `end_at` when available. The skill preserves these as
141
+ normalized `tool_calls`, `tool_calls_summary`, and `tool_total_duration_ms`;
142
+ `codeer eval export` also writes `tool_calls_json` and keeps untouched rows
143
+ in `eval_table_full.json`. Per-tool time is computed from `start_at/end_at`.
144
+
145
+ **`evaluator_id` is singular — one call returns results for one evaluator
146
+ only.** To see the full picture for a case, you must call this endpoint
147
+ once per evaluator. A case might score 1.0 on Style/Tone but 0.3 on
148
+ Content Compliance — checking only one evaluator hides the other failure.
149
+ Always iterate all evaluators in the workspace (or at least all evaluators
150
+ the agent's cases are judged by). `codeer eval run` and `codeer eval rubrics`
151
+ handle this automatically; if calling the API directly, loop over
152
+ `eval_mod.list_evaluators(workspace_id)` and call `get_results()` for each.
153
+
154
+ Regression workflow (apply prompt change → re-run all cases → spot side
155
+ effects): `codeer eval run --agent <agent_id>` runs the latest AgentHistory
156
+ by default. Review the full result set against the previous run summary.
157
+
158
+ ## Stage 7 — Publish
159
+
160
+ | Method & path | Purpose |
161
+ | --- | --- |
162
+ | `POST /agents/{id}/publish-history` | Make a specific AgentHistory version the public one (also used for rollback) |
163
+ | `POST /agents/{id}/publish` | Change `publish_state` (`private` / `in_organization` / `public`) |
164
+ | `GET /agents/{id}/impact` | Always worth running first if other agents `call_agent` this one |
165
+
166
+ ## Stage 8 — Post-release analysis
167
+
168
+ | Method & path | Purpose |
169
+ | --- | --- |
170
+ | `GET /histories?agent_id=X&feedback_filter=improve_feedback&external_user_id=…` | List conversations with filters |
171
+ | `GET /histories/{id}` | Read one history's metadata |
172
+ | `GET /histories/{id}/conversations` | Full conversation turns incl. tool calls |
173
+ | `POST /histories/{hid}/conversations/{cid}/feedbacks` | Leave freeform improvement feedback |
174
+ | `POST /histories/{hid}/conversations/{cid}/score` | Numeric score |
175
+
176
+ `feedback_filter` accepts the `FeedbackFilterType` enum values:
177
+ `no_feedback`, `with_feedback`, `helpful_feedback`, `improve_feedback`.
178
+
179
+ No built-in filter for "histories where tool X was called" — walk the
180
+ conversations and inspect tool-call messages yourself.
181
+
182
+ ## Stage 9 — Rollback
183
+
184
+ Reuse `POST /agents/{id}/publish-history` with an older `history_id`.
185
+ Non-destructive: older versions stay in `GET /agents/{id}/histories`.
186
+
187
+ ## Other useful endpoints
188
+
189
+ | Method & path | Purpose |
190
+ | --- | --- |
191
+ | `GET /accounts/me` | Sanity-check session, read workspace_organization_map |
192
+ | `GET /organizations` | List orgs visible to the user |
193
+ | `GET /llm/models` | List available LLM model IDs to use as `llm_model` |
194
+ | `GET /retrieval/...` | Shared retrieval helpers (file upload for attachments, markdown conversion) |
195
+
196
+ ---
197
+
198
+ ## Gotchas (read this before your first dogfood run)
199
+
200
+ These are traps we hit in practice; `codeer-cli/src/codeer_cli/_validate.py`
201
+ catches most of them client-side, but they're worth knowing when you're
202
+ writing payloads by hand.
203
+
204
+ ### 1. `/agents` returns published only; `/agents/all` returns drafts too
205
+
206
+ `GET /agents?wid=<ws>` filters to **published** agents. While iterating on a
207
+ draft, use `GET /agents/all?wid=<ws>&oid=<org>` — **both** params are required,
208
+ or the server returns `400 Organization ID is required`. Map workspace → org via
209
+ `/accounts/me` → `profile.workspace_organization_map`.
210
+
211
+ ### 2. Form field `type` has a fixed enum — backend doesn't enforce it
212
+
213
+ Valid values:
214
+ `shortText`, `longText`, `number`, `dropdown`, `radio`, `checkbox`, `date`.
215
+
216
+ There is **no** `"text" | "email" | "select"`. The backend validator accepts
217
+ anything (`extra="allow"`) so the agent saves, but the form builder renders
218
+ blank fields because none of the renderers match. Use:
219
+
220
+ - `"email"` → `shortText` + `placeholder`/`helpText` hint
221
+ - `"text"` → `shortText` (single-line) or `longText` (multi-line)
222
+ - `"select"` → `dropdown` with `options: [{value, label}]`
223
+
224
+ Every field also requires `id`, `type`, `name`, `label`, `question`, `required`
225
+ all present and non-empty. `name` is the submission key, `label` is the
226
+ analytics/column name, `question` is the user-facing prompt.
227
+
228
+ ### 3. The `Standard` shown in Test Suite is a per-(case, evaluator) rubric
229
+
230
+ `POST /eval/cases` has a `rubric` field — this is NOT what the Test Suite's
231
+ `Standard` column reads. That column is populated by `POST /eval/rubric` keyed
232
+ on `(evaluation_case_id, evaluator_id)`. Set it explicitly for each
233
+ (case, evaluator) pair after creating the case, or use the eval helpers in
234
+ `codeer-cli/src/codeer_cli/eval_.py` which do both in one call.
235
+
236
+ To **read** rubrics back, use `POST /eval/rubrics/batch` with
237
+ `{case_ids: [...], evaluator_id}` — it returns the raw rubric strings out of
238
+ `CaseEvaluatorInfo`, no `agent_history_id` required since rubrics are
239
+ version-independent. Don't try to scrape rubrics out of past
240
+ `/eval/results/batch` `reason` text: the judge paraphrases them, and a case
241
+ with a rubric set but never evaluated is indistinguishable from one with no
242
+ rubric. Use the eval helpers in `codeer-cli/src/codeer_cli/eval_.py`.
243
+
244
+ Different evaluators should usually get differently-worded rubrics: a
245
+ Style/Tone evaluator should judge **how** the agent responded (language,
246
+ tone, format), while a Content Compliance evaluator should judge **what** it
247
+ said (scope, factuality, tool-use rules).
248
+
249
+ ### 4. Agent version pinning works everywhere — use it
250
+
251
+ Both `POST /chats/{id}/messages` (`agent_history_id` required) and
252
+ `POST /eval/trigger` (`agent_history_id` optional, null = live state) accept
253
+ the draft history id. The apply-→-test-→-publish loop:
254
+
255
+ 1. `PUT /agents/{id}` with your change → new `AgentHistory` with status=`draft`.
256
+ 2. Find its id in the response (`latest_version_number` + `histories`).
257
+ 3. Live-test and/or eval against that draft id.
258
+ 4. Only `POST /agents/{id}/publish-history` when you're happy.
259
+
260
+ Never test a change on the currently-published version by mutating it — every
261
+ PUT already forks a new version for you.
262
+
263
+ ### 5. API-key auth is required for every request
264
+
265
+ The `codeer` wrapper sends `CODEER_API_KEY` as `x-api-key`. If you curl by
266
+ hand, include that header and never print or paste the key into agent-visible
267
+ logs.
268
+
269
+ ### 6. KB `POST /nodes` has no `type` field — and only ever creates folders
270
+
271
+ `CreateNodeSchema` is `{parent_id?, name, description?}`. There's no `type` /
272
+ `node_type` field; the server infers **KB root** when `parent_id` is null and
273
+ **folder** when it's set. This endpoint **cannot create files** — files only
274
+ come through `/files/upload`. Backend is lenient (`extra="allow"`), so a
275
+ `type: "knowledge_base"` or `type: "folder"` field gets silently dropped —
276
+ misleading but harmless.
277
+
278
+ Prefer `kb.create_kb()` / `kb.create_folder()` in new code over the generic
279
+ `create_node()`.
280
+
281
+ ### 7. KB upload form is a single JSON-encoded field named `form`
282
+
283
+ Django Ninja serializes a `Schema`-typed form param as one form field whose
284
+ value is the JSON-stringified body — it is NOT flattened into top-level form
285
+ fields. So the multipart body looks like:
286
+
287
+ ```
288
+ form: {"parent_id": "<folder-or-kb-root-id>"}
289
+ files: <file-1>
290
+ files: <file-2>
291
+ ```
292
+
293
+ Sending `parent_id=...` as a top-level form field returns HTTP 422 with
294
+ `{"loc": ("body","form"), "msg": "Field required"}`. `kb.upload_file()` /
295
+ `kb.upload_files()` handle this; if you roll your own, replicate the shape.
296
+
297
+ ### 8. KB upload needs an explicit `Content-Type` per file
298
+
299
+ `common/files.py :: validate_uploaded_file` rejects when `file.content_type`
300
+ is missing or unrecognized — and httpx's default for multipart uploads is
301
+ `application/octet-stream`, which is unrecognized. The response comes back
302
+ with `status: "FAILED"` and `node_id: null` with no `error_message`
303
+ populated, making this hard to debug.
304
+
305
+ Always pass `(name, file_handle, content_type)` as a 3-tuple. The helper uses
306
+ `mimetypes.guess_type` with overrides for `.md`/`.txt`/`.csv` (the stdlib
307
+ returns `None` for those on older systems). Accepted MIMEs: any `text/*`,
308
+ plus `application/pdf`, DOCX/DOC/PPTX, Google Docs/Slides, and HTML.
309
+ **Image files (JPEG, PNG, GIF, WEBP) are NOT accepted for KB uploads** —
310
+ the upload endpoint explicitly rejects them with "Image files are not
311
+ supported in knowledge base", even though `BASE_ALLOWED_CONTENT_TYPES`
312
+ includes image MIMEs (that set is shared with other upload paths like
313
+ eval-case attachments, where images are allowed).
314
+
315
+ ### 9. KB upload response shape + enum casing
316
+
317
+ - Response envelope: `{"nodes": [{"node_id": "...", "status": "PENDING", "original_name": "...", ...}]}` — NOT `{files: [...]}` or a flat list.
318
+ - `node_type` in list responses is **uppercase** (`FOLDER`, `FILE`); the frontend / ingestion code often uses lowercase. Normalize with `.upper()` before comparing.
319
+ - Indexing status transitions: `PENDING` → `INDEXING` → `READY`, or `FAILED` / `ERROR`. Poll `/files/status` with `{"node_ids": [...]}` until terminal. Small text files usually hit `READY` within 1–2 polls.
320
+
321
+ ### 12. Eval-case attachments come from `/retrieval/upload-file`; the id is `data.uuid`
322
+
323
+ To attach an image / PDF to an eval case (e.g. "owner uploaded a cat selfie
324
+ instead of a report"):
325
+
326
+ 1. **Upload** via `POST /retrieval/upload-file` (multipart):
327
+ ```
328
+ file: (filename, bytes, content_type)
329
+ data: {"workspace_id": "...", "scope": "persistent", "is_evaluation_context": true}
330
+ ```
331
+ `data` must be a **JSON-encoded string** (same Django Ninja quirk as KB
332
+ upload — see Gotcha #7).
333
+
334
+ 2. **Response**:
335
+ ```json
336
+ {"data": {
337
+ "original_name": "cat.jpg", "content_type": "image/jpeg", "size": 43853,
338
+ "file_url": "https://codeer-media.s3.amazonaws.com/.../cat.jpg?...",
339
+ "uuid": "ab155432-5119-4070-bc12-65794ecef970",
340
+ "scope": "persistent"
341
+ }}
342
+ ```
343
+ **The attachment id is `data.uuid`** — there is no `data.attachment_id`
344
+ or `data.id` field. Looking up either of those wastes a debugging round.
345
+
346
+ 3. **Attach** to the case:
347
+ ```python
348
+ eval_mod.update_case(c, case_id, attachment_ids=[uuid])
349
+ ```
350
+
351
+ For bulk creation, `codeer eval cases-apply --attachments-dir <dir>` reads
352
+ each case's `attachment_files: ["x.jpg"]` array, uploads, and attaches in one
353
+ pass. Workspace scope is inferred from the API-key virtual user profile.
354
+
355
+ ### 11. Tool args + outputs are NOT persisted in history reads
356
+
357
+ Conversations have only three roles (`OpenAIChatRole = system | user | assistant`)
358
+ — there is no `tool` role row. When you read a history, here's what you can
359
+ and can't recover from each assistant turn:
360
+
361
+ | Recoverable | Where |
362
+ | --- | --- |
363
+ | Tool name + call_id | regex over `content`: `<tool id=call_xxx>name</tool>` |
364
+ | Per-call token usage | `meta.token_usage.tool_calls[]` (positional match to tags) |
365
+ | Sequenced tool order within a turn | the order of `<tool …>` tags in `content` |
366
+ | Retrieved primary sources | top-level `primary_sources[]` on the assistant turn |
367
+ | Final answer text (no tool markers) | `strip_tool_markers(content)` |
368
+
369
+ | NOT recoverable | Why |
370
+ | --- | --- |
371
+ | Tool **arguments** (e.g. the regex passed to `list_kb_files`, the question/keywords passed to `retrieve_context_objs`) | flow over the WebSocket during execution, not stored on Conversation |
372
+ | Tool **outputs** (raw JSON returned by the tool) | same — stored only as derived `primary_sources` for retrieval tools |
373
+ | Reasoning steps mid-turn | `meta.reasoning_steps` is currently always `null` |
374
+
375
+ If you need full tool I/O, capture it at execution time via the chat SSE
376
+ stream (`POST /chats/{id}/messages`), not from history reads. For after-the-
377
+ fact analysis, the persisted shape is sufficient to surface tool-selection
378
+ patterns, token costs, and which sources the agent ended up citing.
379
+
380
+ ### 10. A KB has exactly ONE level of folders — no nesting
381
+
382
+ The file-manager UI only renders a single layer of folders inside a KB:
383
+
384
+ ```
385
+ KB root
386
+ ├── file.md ← files at root are fine
387
+ ├── file2.md
388
+ └── Folder/ ← one level of folders is the max
389
+ ├── another.md ← files inside a folder are fine
390
+ └── one-more.md
391
+ ```
392
+
393
+ The backend will happily accept a folder id as `parent_id` on `POST /nodes`
394
+ and create a grandchild folder, but the UI won't render it and retrieval
395
+ tooling treats KBs as flat. **Always pass the KB root id as `parent_id`
396
+ when creating folders**, not another folder's id.
397
+
398
+ If the user's source tree has deeper nesting, flatten it first with the
399
+ `kb-indexing` skill — it encodes the original path into the filename (e.g.
400
+ `products/a.md` using `/` U+FF0F as separator) so `list_kb_files` regex
401
+ can still recover structure. That skill's docs explain the full flow.
402
+
403
+ ### 13. Eval results and rubrics are **per-evaluator** — always iterate all evaluators
404
+
405
+ Both `POST /eval/results/batch` and `POST /eval/rubrics/batch` take a
406
+ **singular** `evaluator_id`, not a list. Each call returns data for one
407
+ evaluator only. A common mistake is to check results for one evaluator
408
+ (e.g. Content Compliance), see a perfect score, and conclude the case is
409
+ passing — while the other evaluator (e.g. Style/Tone) scored it 0.3.
410
+
411
+ When pulling eval data manually, always:
412
+ 1. List all evaluators: `eval_mod.list_evaluators(workspace_id)`.
413
+ 2. Call `get_results()` or `get_rubrics_batch()` once **per evaluator**.
414
+ 3. Join the results by `case_id` to get the full (case × evaluator) matrix.
415
+
416
+ The CLI commands (`codeer eval run`, `codeer eval rubrics`,
417
+ `codeer eval rubrics-apply`) and the `get_case_rubrics()` helper all handle
418
+ this iteration automatically. Prefer them for normal operations.
419
+
420
+ ---
421
+
422
+ ## Keeping this reference accurate
423
+
424
+ The canonical reference for Codeer's API and capabilities is the public
425
+ documentation at **https://docs.codeer.ai**. When uncertain about an API
426
+ shape, parameter name, or enum value, check docs.codeer.ai first — this
427
+ cheatsheet is a summary that can lag behind.
428
+
429
+ The enums and limits this skill validates against are mirrored in
430
+ `codeer-cli/src/codeer_cli/constants.py`. When a new tool type or field type is
431
+ added, update that file and add a Gotcha note here if behavior is surprising.
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: codeer-cli
3
+ Version: 0.1.0
4
+ Summary: Command line tools for managing Codeer agents over the Codeer API.
5
+ Project-URL: Homepage, https://www.codeer.ai
6
+ Author: Codeer.AI
7
+ License: Proprietary
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Software Development
15
+ Requires-Python: >=3.11
16
+ Requires-Dist: httpx>=0.27
17
+ Description-Content-Type: text/markdown
18
+
19
+ # codeer-cli
20
+
21
+ Standalone CLI for managing Codeer agents over the Codeer API.
22
+
23
+ ## User install
24
+
25
+ After the package is published to PyPI, install the CLI as an isolated command
26
+ line tool:
27
+
28
+ ```bash
29
+ uv tool install codeer-cli
30
+ ```
31
+
32
+ Until the package is published, install directly from this repository:
33
+
34
+ ```bash
35
+ uv tool install 'git+https://github.com/<org>/codeer-skills.git#subdirectory=codeer-cli'
36
+ ```
37
+
38
+ Replace `<org>` with the GitHub organization or user that hosts this repository.
39
+
40
+ Verify that the command is available:
41
+
42
+ ```bash
43
+ codeer --help
44
+ ```
45
+
46
+ ## Credentials
47
+
48
+ The CLI expects credentials to be configured outside any skill workspace. Add a
49
+ named profile, select it, then verify the setup:
50
+
51
+ ```bash
52
+ codeer profile add work
53
+ codeer profile use work
54
+ codeer check
55
+ ```
56
+
57
+ `codeer profile add` prompts for the API key without echoing it. The local
58
+ project stores only the selected profile name in `.codeer/profile`; API keys
59
+ remain in the user-level config file.
60
+
61
+ For a one-off shell session, you can also export an API key directly:
62
+
63
+ ```bash
64
+ export CODEER_API_KEY=<admin-workspace-api-key>
65
+ codeer check
66
+ ```
67
+
68
+ `CODEER_API_BASE` defaults to `https://api.codeer.ai`. Override it only for
69
+ local, beta, or preview environments:
70
+
71
+ ```bash
72
+ export CODEER_API_BASE=http://localhost:8000
73
+ ```
74
+
75
+ The CLI intentionally does not read repo-root credential files or caller CWD
76
+ `.env`, because those files are often visible to LLM workspace context. Do not
77
+ paste the API key into agent chat or commit it to the repository.
78
+
79
+ Workspace and organization scope are inferred from the workspace API-key
80
+ virtual user's profile. `--workspace`, `--org`, `CODEER_WORKSPACE_ID`, and
81
+ `CODEER_ORGANIZATION_ID` are not used by the CLI.
82
+
83
+ Agent scope is optional and can be set as a non-secret environment variable:
84
+
85
+ ```bash
86
+ CODEER_AGENT_ID=<agent-id>
87
+ ```
88
+
89
+ ## Development install
90
+
91
+ Use an editable install while the CLI is changing quickly:
92
+
93
+ ```bash
94
+ cd /path/to/codeer-skills/codeer-cli
95
+ uv tool install --editable .
96
+ ```
97
+
98
+ Reinstall only when dependencies, entry points, or package metadata change:
99
+
100
+ ```bash
101
+ uv tool install --reinstall --editable /path/to/codeer-skills/codeer-cli
102
+ ```
103
+
104
+ Validate setup before API work:
105
+
106
+ ```bash
107
+ codeer check
108
+ ```
@@ -0,0 +1,90 @@
1
+ # codeer-cli
2
+
3
+ Standalone CLI for managing Codeer agents over the Codeer API.
4
+
5
+ ## User install
6
+
7
+ After the package is published to PyPI, install the CLI as an isolated command
8
+ line tool:
9
+
10
+ ```bash
11
+ uv tool install codeer-cli
12
+ ```
13
+
14
+ Until the package is published, install directly from this repository:
15
+
16
+ ```bash
17
+ uv tool install 'git+https://github.com/<org>/codeer-skills.git#subdirectory=codeer-cli'
18
+ ```
19
+
20
+ Replace `<org>` with the GitHub organization or user that hosts this repository.
21
+
22
+ Verify that the command is available:
23
+
24
+ ```bash
25
+ codeer --help
26
+ ```
27
+
28
+ ## Credentials
29
+
30
+ The CLI expects credentials to be configured outside any skill workspace. Add a
31
+ named profile, select it, then verify the setup:
32
+
33
+ ```bash
34
+ codeer profile add work
35
+ codeer profile use work
36
+ codeer check
37
+ ```
38
+
39
+ `codeer profile add` prompts for the API key without echoing it. The local
40
+ project stores only the selected profile name in `.codeer/profile`; API keys
41
+ remain in the user-level config file.
42
+
43
+ For a one-off shell session, you can also export an API key directly:
44
+
45
+ ```bash
46
+ export CODEER_API_KEY=<admin-workspace-api-key>
47
+ codeer check
48
+ ```
49
+
50
+ `CODEER_API_BASE` defaults to `https://api.codeer.ai`. Override it only for
51
+ local, beta, or preview environments:
52
+
53
+ ```bash
54
+ export CODEER_API_BASE=http://localhost:8000
55
+ ```
56
+
57
+ The CLI intentionally does not read repo-root credential files or caller CWD
58
+ `.env`, because those files are often visible to LLM workspace context. Do not
59
+ paste the API key into agent chat or commit it to the repository.
60
+
61
+ Workspace and organization scope are inferred from the workspace API-key
62
+ virtual user's profile. `--workspace`, `--org`, `CODEER_WORKSPACE_ID`, and
63
+ `CODEER_ORGANIZATION_ID` are not used by the CLI.
64
+
65
+ Agent scope is optional and can be set as a non-secret environment variable:
66
+
67
+ ```bash
68
+ CODEER_AGENT_ID=<agent-id>
69
+ ```
70
+
71
+ ## Development install
72
+
73
+ Use an editable install while the CLI is changing quickly:
74
+
75
+ ```bash
76
+ cd /path/to/codeer-skills/codeer-cli
77
+ uv tool install --editable .
78
+ ```
79
+
80
+ Reinstall only when dependencies, entry points, or package metadata change:
81
+
82
+ ```bash
83
+ uv tool install --reinstall --editable /path/to/codeer-skills/codeer-cli
84
+ ```
85
+
86
+ Validate setup before API work:
87
+
88
+ ```bash
89
+ codeer check
90
+ ```