expedait-cli 0.2.2__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. expedait_cli-0.4.0/CHANGELOG.md +92 -0
  2. expedait_cli-0.4.0/PKG-INFO +301 -0
  3. expedait_cli-0.4.0/README.md +290 -0
  4. expedait_cli-0.4.0/expedait_cli/client.py +411 -0
  5. expedait_cli-0.4.0/expedait_cli/commands/comments.py +146 -0
  6. expedait_cli-0.4.0/expedait_cli/commands/context_cmd.py +160 -0
  7. expedait_cli-0.4.0/expedait_cli/commands/deliverables.py +524 -0
  8. expedait_cli-0.4.0/expedait_cli/commands/objectives.py +62 -0
  9. expedait_cli-0.4.0/expedait_cli/commands/processes.py +603 -0
  10. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/commands/projects.py +25 -4
  11. expedait_cli-0.4.0/expedait_cli/commands/review.py +81 -0
  12. expedait_cli-0.4.0/expedait_cli/commands/roles.py +196 -0
  13. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/main.py +14 -2
  14. expedait_cli-0.4.0/expedait_cli/ops.py +203 -0
  15. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/pyproject.toml +4 -2
  16. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/test_client.py +60 -2
  17. expedait_cli-0.4.0/tests/test_commands/test_comments.py +122 -0
  18. expedait_cli-0.4.0/tests/test_commands/test_context.py +32 -0
  19. expedait_cli-0.4.0/tests/test_commands/test_context_files.py +140 -0
  20. expedait_cli-0.4.0/tests/test_commands/test_deliverables.py +141 -0
  21. expedait_cli-0.4.0/tests/test_commands/test_deliverables_write.py +203 -0
  22. expedait_cli-0.4.0/tests/test_commands/test_objectives.py +49 -0
  23. expedait_cli-0.4.0/tests/test_commands/test_processes.py +174 -0
  24. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/test_commands/test_projects.py +37 -16
  25. expedait_cli-0.4.0/tests/test_commands/test_review.py +62 -0
  26. expedait_cli-0.4.0/tests/test_commands/test_roles.py +90 -0
  27. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/uv.lock +1 -1
  28. expedait_cli-0.2.2/PKG-INFO +0 -153
  29. expedait_cli-0.2.2/README.md +0 -142
  30. expedait_cli-0.2.2/expedait_cli/client.py +0 -134
  31. expedait_cli-0.2.2/expedait_cli/commands/comments.py +0 -102
  32. expedait_cli-0.2.2/expedait_cli/commands/pages.py +0 -110
  33. expedait_cli-0.2.2/tests/test_commands/test_comments.py +0 -138
  34. expedait_cli-0.2.2/tests/test_commands/test_pages.py +0 -153
  35. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/.github/workflows/ci.yml +0 -0
  36. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/.github/workflows/publish.yml +0 -0
  37. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/.gitignore +0 -0
  38. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/CLAUDE.md +0 -0
  39. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/LICENSE +0 -0
  40. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/__init__.py +0 -0
  41. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/auth.py +0 -0
  42. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/commands/__init__.py +0 -0
  43. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/commands/auth_cmd.py +0 -0
  44. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/commands/init_cmd.py +0 -0
  45. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/config.py +0 -0
  46. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/formatters.py +0 -0
  47. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/expedait_cli/settings.py +0 -0
  48. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/__init__.py +0 -0
  49. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/conftest.py +0 -0
  50. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/test_auth.py +0 -0
  51. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/test_commands/__init__.py +0 -0
  52. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/test_commands/test_auth_cmd.py +0 -0
  53. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/test_commands/test_init_cmd.py +0 -0
  54. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/test_config.py +0 -0
  55. {expedait_cli-0.2.2 → expedait_cli-0.4.0}/tests/test_settings.py +0 -0
@@ -0,0 +1,92 @@
1
+ # Changelog
2
+
3
+ ## 0.4.0
4
+
5
+ Bring the CLI to parity with the hosted MCP server's write surface — agents can
6
+ now create and adapt content, processes, and roles, not just read them. Every
7
+ new command supports `--format json` and reports a per-op summary.
8
+
9
+ ### Added
10
+ - **Deliverable writes** (mirror MCP `write_deliverable`):
11
+ - `deliverables write --ops @file.json` — ordered batch of `create` / `edit` /
12
+ `rename` / `save_version` / `set_state` ops, chainable with `id="$last"` or
13
+ named refs (`ref="x"` on create, `id="@x"` later). Pre-flight validates op
14
+ shape and reference ordering; ops stop on first failure (rest `skipped`) and
15
+ the command exits non-zero on partial failure.
16
+ - Ergonomic subcommands on top: `deliverables create`, `edit`, `rename`,
17
+ `save-version`, `set-state` (states: Not Started, In Progress, Review,
18
+ Approved, Completed, Final). `--content` / `--instructions` accept `@file`,
19
+ `-` (stdin), or a literal.
20
+ - **`processes` command group** (mirror MCP `list_processes` / `get_process` /
21
+ `write_process`): `processes list`, `processes get PROCESS_ID` (full template
22
+ tree — phases, rows, deliverable-type cards, owner roles, objective
23
+ subprocesses), and `processes write --ops` (create/update/delete process,
24
+ phases, rows, deliverable types; `set_dependencies`; `set_owner_roles`). Named
25
+ refs, optional card layout with auto-placement (`after_type_id` / append),
26
+ role-name resolution, and an in-use delete guard (`confirm_in_use`).
27
+ - **`roles` command group** (mirror MCP `list_roles` / `write_role`):
28
+ `roles list`, `roles create`, `roles update`, `roles delete`, and
29
+ `roles write --ops`.
30
+ - **Context-file management** under the `context` group — manage the uploaded
31
+ files that feed a deliverable's (or objective's) LLM context: `context files`
32
+ (list), `context add` (upload; re-upload by name replaces), `context
33
+ file-content` (parsed text), `context download-file`, `context remove-file`,
34
+ and `context set-file --exclude/--include` (toggle a file in/out of the LLM
35
+ context). External source links remain web-app integration flows.
36
+ - `expedait_cli/ops.py` — shared multi-op engine (`RefResolver`, `run_ops`,
37
+ `render_ops`) behind all three write surfaces, mirroring the MCP server's
38
+ `_common.py` run-ops scaffold.
39
+ - `client.BackendError` + an op-safe request path so per-op failures are
40
+ captured and reported instead of aborting the whole command.
41
+ - `deliverables types` — list deliverable types so you can find the `--type` id
42
+ that `deliverables create` needs.
43
+ - `projects workspace [PROJECT_ID]` — deliverables grouped by phase (mirrors the
44
+ MCP `get_project_workspace` tool); the structure-aware view the flat
45
+ `deliverables list` can't give.
46
+
47
+ ### Fixed
48
+ - `processes write` no longer crashes with an uncaught `KeyError` when an
49
+ `update_phase_row` op omits `position`; it now reports a clean per-op
50
+ `missing_field` error.
51
+ - `--content` / `--instructions` / `--ops` with a missing or unreadable `@file`
52
+ now raise a clear usage error instead of leaking an `OSError` traceback. The
53
+ three duplicate readers were consolidated into one helper (`ops.read_value_arg`).
54
+ - `projects download` no longer crashes. It passed a `fmt=` argument that the
55
+ client method never accepted (a `TypeError` on every run, hidden by a loosely
56
+ mocked test). The backend `/download` endpoint has no format parameter, so the
57
+ dead `--download-format` option was removed; the command always extracts the
58
+ markdown + images ZIP.
59
+
60
+ ## 0.3.0
61
+
62
+ Adapt the CLI to the product's four-primitive domain model (objectives,
63
+ deliverables, context, review).
64
+
65
+ ### Added
66
+ - `deliverables` command group (`list`, `get`, `inspect`, `download`) — the
67
+ rename of `pages`, pointed at `/api/v1/deliverables/...`.
68
+ - `deliverables get --include` — comma-separated section reads (`meta`,
69
+ `content`, `template`, `requirements`, `writer_instructions`, `dependencies`,
70
+ `external_context`, `score`, `comments`, `versions`), defaulting to `content`.
71
+ `meta` surfaces `parent_deliverable_id`.
72
+ - `objectives overview DELIVERABLE_ID` — objective metadata plus its full
73
+ descendant tree.
74
+ - `context get DELIVERABLE_ID` — read-only LLM context snapshot for a
75
+ deliverable.
76
+ - `review` command group: `review issues DELIVERABLE_ID [--state open|muted|all]`
77
+ and `review mute ISSUE_ID [--note TEXT] [--unmute]`.
78
+ - `comments create --agent-run-id` to link a comment to a build run.
79
+ - `expedait-cli` console-script alias so `uvx expedait-cli …` keeps working.
80
+
81
+ ### Changed
82
+ - `comments create` now resolves anchor offsets from the deliverable content;
83
+ only `--text` and `--selected-text` are required. `--start-offset` /
84
+ `--end-offset` remain available as explicit overrides.
85
+ - Renamed `comments create --source-page-id` → `--source-deliverable-id`
86
+ (payload field `source_page_id` → `source_deliverable_id`).
87
+ - `comments resolve` / `comments delete` now use the deliverable-scoped routes
88
+ `/api/v1/deliverables/{id}/comments/{comment_id}`.
89
+
90
+ ### Deprecated
91
+ - The `pages` command group. `expedait pages …` still works for one release
92
+ (warns and forwards to `deliverables`) and will then be removed.
@@ -0,0 +1,301 @@
1
+ Metadata-Version: 2.4
2
+ Name: expedait-cli
3
+ Version: 0.4.0
4
+ Summary: CLI for Expedait project management — read and write deliverables, processes, roles, and comments
5
+ License-Expression: Apache-2.0
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: click>=8.1
9
+ Requires-Dist: httpx>=0.27
10
+ Description-Content-Type: text/markdown
11
+
12
+ # Expedait CLI
13
+
14
+ [![PyPI](https://img.shields.io/pypi/v/expedait-cli)](https://pypi.org/project/expedait-cli/)
15
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
16
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
17
+
18
+ CLI for [Expedait](https://expedait.org) — lets AI coding agents download project specs and post comments via the Expedait API.
19
+
20
+ ## The model
21
+
22
+ Expedait organizes specs around four primitives:
23
+
24
+ - **Objectives** — top-level goals. An objective is itself a deliverable that nests child deliverables beneath it (`parent_deliverable_id`).
25
+ - **Deliverables** — the individual spec documents (formerly "pages").
26
+ - **Context** — the assembled LLM context for one deliverable: dependency deliverables, linked external sources, uploaded files, and aggregate sizes.
27
+ - **Review** — scoring findings raised on a deliverable: severity, description, the criteria that flagged them, and anchor offsets.
28
+
29
+ ## Usage
30
+
31
+ ### Run with `uvx` (recommended)
32
+
33
+ No installation needed — run directly:
34
+
35
+ ```bash
36
+ uvx expedait-cli auth login
37
+ uvx expedait-cli projects list
38
+ uvx expedait-cli projects download 1
39
+ ```
40
+
41
+ ### Add as a dev dependency
42
+
43
+ If your AI agent needs it available in the project environment:
44
+
45
+ ```bash
46
+ uv add --group dev expedait-cli
47
+ ```
48
+
49
+ Then reference it in your agent configuration (e.g. `CLAUDE.md`, `.cursor/rules`, etc.).
50
+
51
+ ## Project Setup
52
+
53
+ After authenticating, run `init` inside your project directory to store your tenant and project settings locally:
54
+
55
+ ```bash
56
+ uvx expedait-cli init
57
+ ```
58
+
59
+ This creates `.expedait/settings.json` with your `tenant_id` and `project_id`. Add `.expedait/` to your `.gitignore`.
60
+
61
+ Once initialized, commands that need a project ID will resolve it automatically. Downloads default to `.expedait/context/`:
62
+
63
+ ```bash
64
+ expedait projects download # downloads to .expedait/context/
65
+ expedait deliverables list # no --project-id needed
66
+ expedait deliverables download 42 # downloads to .expedait/context/
67
+ ```
68
+
69
+ **Resolution order for tenant/project:** CLI flag > env var > `.expedait/settings.json` > `~/.expedait/config.json`.
70
+
71
+ ## Authentication
72
+
73
+ ### Interactive login
74
+
75
+ ```bash
76
+ uvx expedait-cli auth login
77
+ ```
78
+
79
+ Prompts for login method (SSO or email/password). Stores credentials in `~/.expedait/config.json`.
80
+
81
+ ### Environment variables (CI / agents)
82
+
83
+ ```bash
84
+ export EXPEDAIT_TOKEN="your-jwt-token"
85
+ export EXPEDAIT_API_URL="https://your-instance.expedait.org"
86
+ export EXPEDAIT_TENANT_ID=1
87
+ ```
88
+
89
+ **Token resolution order:** `EXPEDAIT_TOKEN` env var > `~/.expedait/config.json` > error.
90
+
91
+ ## Commands
92
+
93
+ ### Auth
94
+
95
+ ```bash
96
+ expedait auth login # Interactive login
97
+ expedait auth status # Show current user and tenant
98
+ expedait auth logout # Clear stored credentials
99
+ ```
100
+
101
+ ### Projects
102
+
103
+ ```bash
104
+ expedait projects list # List all projects
105
+ expedait projects get PROJECT_ID # Get project details
106
+ expedait projects workspace PROJECT_ID # Deliverables grouped by phase (structure-aware view)
107
+ expedait projects download PROJECT_ID # Extract all deliverables to .expedait/context/
108
+ expedait projects download PROJECT_ID --output-dir ./specs # Extract to a custom directory
109
+ ```
110
+
111
+ ### Deliverables
112
+
113
+ ```bash
114
+ expedait deliverables list --project-id PROJECT_ID # List deliverables in a project
115
+ expedait deliverables types # List deliverable types (find the --type ID for create)
116
+ expedait deliverables get DELIVERABLE_ID # Print deliverable markdown content
117
+ expedait deliverables get DELIVERABLE_ID --include meta,content,dependencies,score
118
+ expedait deliverables inspect DELIVERABLE_ID # Full context (content + comments + deps + lock)
119
+ expedait deliverables download DELIVERABLE_ID # Extract to .expedait/context/
120
+ ```
121
+
122
+ `--include` accepts a comma-separated subset of: `meta`, `content`, `template`,
123
+ `requirements`, `writer_instructions`, `dependencies`, `external_context`,
124
+ `score`, `comments`, `versions`. It defaults to `content`. `meta` surfaces
125
+ `parent_deliverable_id` (non-null ⇒ this deliverable is a child nested under an
126
+ objective).
127
+
128
+ #### Writing deliverables
129
+
130
+ Mirrors the MCP `write_deliverable` tool. Ergonomic subcommands cover the common
131
+ cases; `write --ops` applies an ordered batch in one call.
132
+
133
+ ```bash
134
+ expedait deliverables create --project P --type TYPE_ID --title "Vision" \
135
+ [--content @vision.md] [--parent-deliverable-id ID] # create (content: @file, - for stdin, or literal)
136
+ expedait deliverables edit DELIVERABLE_ID --content @body.md # replace content (autosave, no version bump)
137
+ expedait deliverables rename DELIVERABLE_ID --title "New title" # rename without touching content
138
+ expedait deliverables save-version DELIVERABLE_ID --reason "checkpoint" # explicit snapshot
139
+ expedait deliverables set-state DELIVERABLE_ID --state "Review" # transition workflow state
140
+ ```
141
+
142
+ Valid states: `Not Started`, `In Progress`, `Review`, `Approved`, `Completed`,
143
+ `Final`.
144
+
145
+ For multi-step writes, `write --ops` takes a JSON ops array (`@file.json`, `-`
146
+ for stdin, or inline). Each op is one of `create`, `edit`, `rename`,
147
+ `save_version`, `set_state`. Chain ops on a freshly-created deliverable with
148
+ `"id": "$last"` (the previous op's deliverable) or bind a name on create
149
+ (`"ref": "x"`) and reference it later as `"id": "@x"`:
150
+
151
+ ```bash
152
+ expedait deliverables write --ops @ops.json
153
+ # ops.json:
154
+ # [
155
+ # {"op": "create", "ref": "v", "project_id": 1, "deliverable_type_id": 3, "title": "Vision"},
156
+ # {"op": "edit", "id": "@v", "content": "# Product Vision\n..."},
157
+ # {"op": "set_state", "id": "@v", "state": "Review"}
158
+ # ]
159
+ ```
160
+
161
+ Ops run in order and stop on the first failure (the rest report `skipped`); the
162
+ output reports per-op `{status: ok | error | skipped}`, and the command exits
163
+ non-zero if any op failed.
164
+
165
+ ### Objectives
166
+
167
+ ```bash
168
+ expedait objectives overview DELIVERABLE_ID # Objective metadata + full descendant tree
169
+ ```
170
+
171
+ ### Context
172
+
173
+ ```bash
174
+ expedait context get DELIVERABLE_ID # The LLM context snapshot for one deliverable
175
+ ```
176
+
177
+ A deliverable's (or objective's) context is built from dependency deliverables,
178
+ linked external sources, and **uploaded context files**. The CLI manages the
179
+ file half of that surface — attach reference docs an agent should write against,
180
+ and toggle whether each one feeds the LLM context:
181
+
182
+ ```bash
183
+ expedait context files DELIVERABLE_ID # List attached context files
184
+ expedait context add DELIVERABLE_ID ./reference.md # Upload a context file (re-upload by name replaces)
185
+ expedait context file-content FILE_ID # Parsed text the file contributes to context
186
+ expedait context download-file FILE_ID -o ./out.md # Download a file's raw bytes
187
+ expedait context set-file FILE_ID --exclude # Exclude from LLM context (or --include)
188
+ expedait context remove-file FILE_ID # Delete a context file
189
+ ```
190
+
191
+ External source links (Notion, GitHub, etc.) are created through the web app's
192
+ integration flows, not the CLI.
193
+
194
+ ### Review
195
+
196
+ ```bash
197
+ expedait review issues DELIVERABLE_ID # List scoring findings (default: all)
198
+ expedait review issues DELIVERABLE_ID --state open # Only open findings
199
+ expedait review mute ISSUE_ID --note "by design" # Mute a finding
200
+ expedait review mute ISSUE_ID --unmute # Unmute a finding
201
+ ```
202
+
203
+ ### Comments
204
+
205
+ ```bash
206
+ expedait comments list DELIVERABLE_ID # List comments on a deliverable
207
+ expedait comments create DELIVERABLE_ID \ # Create a comment (offsets resolved automatically)
208
+ --text "Comment content" \
209
+ --selected-text "text from the deliverable" \
210
+ --source-deliverable-id 5 # Optional: agent's source deliverable
211
+ expedait comments resolve DELIVERABLE_ID COMMENT_ID # Mark as resolved
212
+ expedait comments delete DELIVERABLE_ID COMMENT_ID # Delete a comment
213
+ ```
214
+
215
+ Only `--text` and `--selected-text` are required; the CLI locates the selected
216
+ text in the deliverable to compute anchor offsets. Pass `--start-offset` and
217
+ `--end-offset` to anchor explicitly (e.g. when the selected text appears more
218
+ than once).
219
+
220
+ ### Processes (Process Designer)
221
+
222
+ A *process* is a project type plus the template tree it owns: phases → rows →
223
+ deliverable-type cards, dependency edges, owner roles, and objective
224
+ subprocesses. Editing it reshapes **every** project instantiated from it.
225
+ Mirrors the MCP `list_processes` / `get_process` / `write_process` tools.
226
+
227
+ ```bash
228
+ expedait processes list # List processes (project types)
229
+ expedait processes get PROCESS_ID # Full template tree (phases, rows, cards, roles)
230
+ expedait processes write --ops @ops.json # Build or adapt a process in one call
231
+ ```
232
+
233
+ `write --ops` ops: `create_process`, `update_process`, `duplicate_process`,
234
+ `delete_process`, `create_phase`, `update_phase`, `delete_phase`,
235
+ `create_phase_row`, `update_phase_row`, `delete_phase_row`,
236
+ `create_deliverable_type`, `update_deliverable_type`, `delete_deliverable_type`,
237
+ `set_dependencies`, `set_owner_roles`. Ops chain via named refs (`"ref": "x"` on
238
+ a create op, `"@x"` later). Card layout is optional — omit `col_position` and
239
+ cards auto-place (append, or just after `after_type_id`). `set_owner_roles`
240
+ accepts role names or ids. Delete ops refuse an in-use template unless the op
241
+ carries `"confirm_in_use": true`.
242
+
243
+ ```jsonc
244
+ // ops.json — build a process end to end in one call
245
+ [
246
+ {"op": "create_process", "ref": "p", "name": "Product Dev"},
247
+ {"op": "create_phase", "ref": "ph", "process_id": "@p", "name": "Discovery"},
248
+ {"op": "create_deliverable_type", "ref": "vision", "phase_id": "@ph", "name": "Vision"},
249
+ {"op": "create_deliverable_type", "ref": "prd", "phase_id": "@ph", "name": "PRD", "after_type_id": "@vision"},
250
+ {"op": "set_dependencies", "type_id": "@prd", "dependency_ids": ["@vision"]},
251
+ {"op": "set_owner_roles", "type_id": "@prd", "role_names": ["Product Manager"]}
252
+ ]
253
+ ```
254
+
255
+ ### Roles
256
+
257
+ A *role* is a workspace project role — the owner-role pool assigned to
258
+ deliverable types. A role's `instructions` is its LLM coaching persona. Mirrors
259
+ the MCP `list_roles` / `write_role` tools.
260
+
261
+ ```bash
262
+ expedait roles list # List project roles
263
+ expedait roles create --name "Product Manager" \ # Create (instructions: @file, -, or literal)
264
+ [--description "owns the roadmap"] [--instructions @pm.md]
265
+ expedait roles update ROLE_ID --name "Lead PM" # Update name/description/instructions
266
+ expedait roles delete ROLE_ID # Delete a role
267
+ expedait roles write --ops @ops.json # Batch (create_role/update_role/delete_role)
268
+ ```
269
+
270
+ ### Global Options
271
+
272
+ ```bash
273
+ expedait --api-url https://host:8000 ... # Override API URL
274
+ expedait --tenant-id 2 ... # Override tenant
275
+ expedait --format json ... # Force JSON output
276
+ expedait --format text ... # Force human-readable output
277
+ expedait --version # Show version
278
+ ```
279
+
280
+ Output format defaults to `text` when connected to a terminal, `json` when piped.
281
+
282
+ > **Migration note:** the `pages` command group has been renamed to
283
+ > `deliverables`. `expedait pages …` still works for one release (it warns and
284
+ > forwards) but will be removed.
285
+
286
+ ## Agent Skills
287
+
288
+ For step-by-step guides on using the CLI from AI coding agents, see [expedait-skills](https://github.com/Expedait/expedait-skills).
289
+
290
+ ## Development
291
+
292
+ ```bash
293
+ git clone https://github.com/Expedait/expedait-cli.git
294
+ cd expedait-cli
295
+ uv sync --group dev
296
+ uv run python -m pytest
297
+ ```
298
+
299
+ ## License
300
+
301
+ [Apache License 2.0](LICENSE)
@@ -0,0 +1,290 @@
1
+ # Expedait CLI
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/expedait-cli)](https://pypi.org/project/expedait-cli/)
4
+ [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
6
+
7
+ CLI for [Expedait](https://expedait.org) — lets AI coding agents download project specs and post comments via the Expedait API.
8
+
9
+ ## The model
10
+
11
+ Expedait organizes specs around four primitives:
12
+
13
+ - **Objectives** — top-level goals. An objective is itself a deliverable that nests child deliverables beneath it (`parent_deliverable_id`).
14
+ - **Deliverables** — the individual spec documents (formerly "pages").
15
+ - **Context** — the assembled LLM context for one deliverable: dependency deliverables, linked external sources, uploaded files, and aggregate sizes.
16
+ - **Review** — scoring findings raised on a deliverable: severity, description, the criteria that flagged them, and anchor offsets.
17
+
18
+ ## Usage
19
+
20
+ ### Run with `uvx` (recommended)
21
+
22
+ No installation needed — run directly:
23
+
24
+ ```bash
25
+ uvx expedait-cli auth login
26
+ uvx expedait-cli projects list
27
+ uvx expedait-cli projects download 1
28
+ ```
29
+
30
+ ### Add as a dev dependency
31
+
32
+ If your AI agent needs it available in the project environment:
33
+
34
+ ```bash
35
+ uv add --group dev expedait-cli
36
+ ```
37
+
38
+ Then reference it in your agent configuration (e.g. `CLAUDE.md`, `.cursor/rules`, etc.).
39
+
40
+ ## Project Setup
41
+
42
+ After authenticating, run `init` inside your project directory to store your tenant and project settings locally:
43
+
44
+ ```bash
45
+ uvx expedait-cli init
46
+ ```
47
+
48
+ This creates `.expedait/settings.json` with your `tenant_id` and `project_id`. Add `.expedait/` to your `.gitignore`.
49
+
50
+ Once initialized, commands that need a project ID will resolve it automatically. Downloads default to `.expedait/context/`:
51
+
52
+ ```bash
53
+ expedait projects download # downloads to .expedait/context/
54
+ expedait deliverables list # no --project-id needed
55
+ expedait deliverables download 42 # downloads to .expedait/context/
56
+ ```
57
+
58
+ **Resolution order for tenant/project:** CLI flag > env var > `.expedait/settings.json` > `~/.expedait/config.json`.
59
+
60
+ ## Authentication
61
+
62
+ ### Interactive login
63
+
64
+ ```bash
65
+ uvx expedait-cli auth login
66
+ ```
67
+
68
+ Prompts for login method (SSO or email/password). Stores credentials in `~/.expedait/config.json`.
69
+
70
+ ### Environment variables (CI / agents)
71
+
72
+ ```bash
73
+ export EXPEDAIT_TOKEN="your-jwt-token"
74
+ export EXPEDAIT_API_URL="https://your-instance.expedait.org"
75
+ export EXPEDAIT_TENANT_ID=1
76
+ ```
77
+
78
+ **Token resolution order:** `EXPEDAIT_TOKEN` env var > `~/.expedait/config.json` > error.
79
+
80
+ ## Commands
81
+
82
+ ### Auth
83
+
84
+ ```bash
85
+ expedait auth login # Interactive login
86
+ expedait auth status # Show current user and tenant
87
+ expedait auth logout # Clear stored credentials
88
+ ```
89
+
90
+ ### Projects
91
+
92
+ ```bash
93
+ expedait projects list # List all projects
94
+ expedait projects get PROJECT_ID # Get project details
95
+ expedait projects workspace PROJECT_ID # Deliverables grouped by phase (structure-aware view)
96
+ expedait projects download PROJECT_ID # Extract all deliverables to .expedait/context/
97
+ expedait projects download PROJECT_ID --output-dir ./specs # Extract to a custom directory
98
+ ```
99
+
100
+ ### Deliverables
101
+
102
+ ```bash
103
+ expedait deliverables list --project-id PROJECT_ID # List deliverables in a project
104
+ expedait deliverables types # List deliverable types (find the --type ID for create)
105
+ expedait deliverables get DELIVERABLE_ID # Print deliverable markdown content
106
+ expedait deliverables get DELIVERABLE_ID --include meta,content,dependencies,score
107
+ expedait deliverables inspect DELIVERABLE_ID # Full context (content + comments + deps + lock)
108
+ expedait deliverables download DELIVERABLE_ID # Extract to .expedait/context/
109
+ ```
110
+
111
+ `--include` accepts a comma-separated subset of: `meta`, `content`, `template`,
112
+ `requirements`, `writer_instructions`, `dependencies`, `external_context`,
113
+ `score`, `comments`, `versions`. It defaults to `content`. `meta` surfaces
114
+ `parent_deliverable_id` (non-null ⇒ this deliverable is a child nested under an
115
+ objective).
116
+
117
+ #### Writing deliverables
118
+
119
+ Mirrors the MCP `write_deliverable` tool. Ergonomic subcommands cover the common
120
+ cases; `write --ops` applies an ordered batch in one call.
121
+
122
+ ```bash
123
+ expedait deliverables create --project P --type TYPE_ID --title "Vision" \
124
+ [--content @vision.md] [--parent-deliverable-id ID] # create (content: @file, - for stdin, or literal)
125
+ expedait deliverables edit DELIVERABLE_ID --content @body.md # replace content (autosave, no version bump)
126
+ expedait deliverables rename DELIVERABLE_ID --title "New title" # rename without touching content
127
+ expedait deliverables save-version DELIVERABLE_ID --reason "checkpoint" # explicit snapshot
128
+ expedait deliverables set-state DELIVERABLE_ID --state "Review" # transition workflow state
129
+ ```
130
+
131
+ Valid states: `Not Started`, `In Progress`, `Review`, `Approved`, `Completed`,
132
+ `Final`.
133
+
134
+ For multi-step writes, `write --ops` takes a JSON ops array (`@file.json`, `-`
135
+ for stdin, or inline). Each op is one of `create`, `edit`, `rename`,
136
+ `save_version`, `set_state`. Chain ops on a freshly-created deliverable with
137
+ `"id": "$last"` (the previous op's deliverable) or bind a name on create
138
+ (`"ref": "x"`) and reference it later as `"id": "@x"`:
139
+
140
+ ```bash
141
+ expedait deliverables write --ops @ops.json
142
+ # ops.json:
143
+ # [
144
+ # {"op": "create", "ref": "v", "project_id": 1, "deliverable_type_id": 3, "title": "Vision"},
145
+ # {"op": "edit", "id": "@v", "content": "# Product Vision\n..."},
146
+ # {"op": "set_state", "id": "@v", "state": "Review"}
147
+ # ]
148
+ ```
149
+
150
+ Ops run in order and stop on the first failure (the rest report `skipped`); the
151
+ output reports per-op `{status: ok | error | skipped}`, and the command exits
152
+ non-zero if any op failed.
153
+
154
+ ### Objectives
155
+
156
+ ```bash
157
+ expedait objectives overview DELIVERABLE_ID # Objective metadata + full descendant tree
158
+ ```
159
+
160
+ ### Context
161
+
162
+ ```bash
163
+ expedait context get DELIVERABLE_ID # The LLM context snapshot for one deliverable
164
+ ```
165
+
166
+ A deliverable's (or objective's) context is built from dependency deliverables,
167
+ linked external sources, and **uploaded context files**. The CLI manages the
168
+ file half of that surface — attach reference docs an agent should write against,
169
+ and toggle whether each one feeds the LLM context:
170
+
171
+ ```bash
172
+ expedait context files DELIVERABLE_ID # List attached context files
173
+ expedait context add DELIVERABLE_ID ./reference.md # Upload a context file (re-upload by name replaces)
174
+ expedait context file-content FILE_ID # Parsed text the file contributes to context
175
+ expedait context download-file FILE_ID -o ./out.md # Download a file's raw bytes
176
+ expedait context set-file FILE_ID --exclude # Exclude from LLM context (or --include)
177
+ expedait context remove-file FILE_ID # Delete a context file
178
+ ```
179
+
180
+ External source links (Notion, GitHub, etc.) are created through the web app's
181
+ integration flows, not the CLI.
182
+
183
+ ### Review
184
+
185
+ ```bash
186
+ expedait review issues DELIVERABLE_ID # List scoring findings (default: all)
187
+ expedait review issues DELIVERABLE_ID --state open # Only open findings
188
+ expedait review mute ISSUE_ID --note "by design" # Mute a finding
189
+ expedait review mute ISSUE_ID --unmute # Unmute a finding
190
+ ```
191
+
192
+ ### Comments
193
+
194
+ ```bash
195
+ expedait comments list DELIVERABLE_ID # List comments on a deliverable
196
+ expedait comments create DELIVERABLE_ID \ # Create a comment (offsets resolved automatically)
197
+ --text "Comment content" \
198
+ --selected-text "text from the deliverable" \
199
+ --source-deliverable-id 5 # Optional: agent's source deliverable
200
+ expedait comments resolve DELIVERABLE_ID COMMENT_ID # Mark as resolved
201
+ expedait comments delete DELIVERABLE_ID COMMENT_ID # Delete a comment
202
+ ```
203
+
204
+ Only `--text` and `--selected-text` are required; the CLI locates the selected
205
+ text in the deliverable to compute anchor offsets. Pass `--start-offset` and
206
+ `--end-offset` to anchor explicitly (e.g. when the selected text appears more
207
+ than once).
208
+
209
+ ### Processes (Process Designer)
210
+
211
+ A *process* is a project type plus the template tree it owns: phases → rows →
212
+ deliverable-type cards, dependency edges, owner roles, and objective
213
+ subprocesses. Editing it reshapes **every** project instantiated from it.
214
+ Mirrors the MCP `list_processes` / `get_process` / `write_process` tools.
215
+
216
+ ```bash
217
+ expedait processes list # List processes (project types)
218
+ expedait processes get PROCESS_ID # Full template tree (phases, rows, cards, roles)
219
+ expedait processes write --ops @ops.json # Build or adapt a process in one call
220
+ ```
221
+
222
+ `write --ops` ops: `create_process`, `update_process`, `duplicate_process`,
223
+ `delete_process`, `create_phase`, `update_phase`, `delete_phase`,
224
+ `create_phase_row`, `update_phase_row`, `delete_phase_row`,
225
+ `create_deliverable_type`, `update_deliverable_type`, `delete_deliverable_type`,
226
+ `set_dependencies`, `set_owner_roles`. Ops chain via named refs (`"ref": "x"` on
227
+ a create op, `"@x"` later). Card layout is optional — omit `col_position` and
228
+ cards auto-place (append, or just after `after_type_id`). `set_owner_roles`
229
+ accepts role names or ids. Delete ops refuse an in-use template unless the op
230
+ carries `"confirm_in_use": true`.
231
+
232
+ ```jsonc
233
+ // ops.json — build a process end to end in one call
234
+ [
235
+ {"op": "create_process", "ref": "p", "name": "Product Dev"},
236
+ {"op": "create_phase", "ref": "ph", "process_id": "@p", "name": "Discovery"},
237
+ {"op": "create_deliverable_type", "ref": "vision", "phase_id": "@ph", "name": "Vision"},
238
+ {"op": "create_deliverable_type", "ref": "prd", "phase_id": "@ph", "name": "PRD", "after_type_id": "@vision"},
239
+ {"op": "set_dependencies", "type_id": "@prd", "dependency_ids": ["@vision"]},
240
+ {"op": "set_owner_roles", "type_id": "@prd", "role_names": ["Product Manager"]}
241
+ ]
242
+ ```
243
+
244
+ ### Roles
245
+
246
+ A *role* is a workspace project role — the owner-role pool assigned to
247
+ deliverable types. A role's `instructions` is its LLM coaching persona. Mirrors
248
+ the MCP `list_roles` / `write_role` tools.
249
+
250
+ ```bash
251
+ expedait roles list # List project roles
252
+ expedait roles create --name "Product Manager" \ # Create (instructions: @file, -, or literal)
253
+ [--description "owns the roadmap"] [--instructions @pm.md]
254
+ expedait roles update ROLE_ID --name "Lead PM" # Update name/description/instructions
255
+ expedait roles delete ROLE_ID # Delete a role
256
+ expedait roles write --ops @ops.json # Batch (create_role/update_role/delete_role)
257
+ ```
258
+
259
+ ### Global Options
260
+
261
+ ```bash
262
+ expedait --api-url https://host:8000 ... # Override API URL
263
+ expedait --tenant-id 2 ... # Override tenant
264
+ expedait --format json ... # Force JSON output
265
+ expedait --format text ... # Force human-readable output
266
+ expedait --version # Show version
267
+ ```
268
+
269
+ Output format defaults to `text` when connected to a terminal, `json` when piped.
270
+
271
+ > **Migration note:** the `pages` command group has been renamed to
272
+ > `deliverables`. `expedait pages …` still works for one release (it warns and
273
+ > forwards) but will be removed.
274
+
275
+ ## Agent Skills
276
+
277
+ For step-by-step guides on using the CLI from AI coding agents, see [expedait-skills](https://github.com/Expedait/expedait-skills).
278
+
279
+ ## Development
280
+
281
+ ```bash
282
+ git clone https://github.com/Expedait/expedait-cli.git
283
+ cd expedait-cli
284
+ uv sync --group dev
285
+ uv run python -m pytest
286
+ ```
287
+
288
+ ## License
289
+
290
+ [Apache License 2.0](LICENSE)