Use the public contree-client library#13
Open
mosquito wants to merge 7 commits into
Open
Conversation
…e sandbox Directory specs now mean a project root: every kind resolves to its project location under it (.claude/skills/contree, .agents/skills/contree, .claude/agents/*.md, ...); paths pointing at a skill artifact stay literal. Codex skills move to .agents/skills (project) and ~/.agents/skills (global), rules remain in CODEX_HOME. Install writes only the files it owns instead of replacing the target directory, remove deletes only those files and prunes empty layout dirs, so installing into a repository can never wipe foreign content. The Codex sandbox section renders the resolved CONTREE_HOME into writable_roots. Subagent frontmatter uses the tools field, the workflow numbering is owned by the template, and stale registry rows are forgotten on remove.
…as POSIX skills_from_spec treated any spec containing a colon as kind:HINT, so C:\path never expanded as a project root. The Codex sandbox rendered CONTREE_HOME with backslashes, which are escape sequences inside TOML basic strings; render with forward slashes instead. Path assertions in the CONTREE_HOME tests no longer assume the pytest tmp dir lives outside the user home.
insomnes
reviewed
Jul 17, 2026
…fing The library yields the body exactly as served with compressed=True and transparently decompressed tar with compressed=False, so the CLI writes the stream as-is and drops the magic-byte passthrough.
There was a problem hiding this comment.
Pull request overview
This PR migrates contree-cli from its internal HTTP/DTO layer to the public contree-client package, and updates CLI semantics, docs, and tests to match the new typed-client surface (including skill install layout changes and new export/build behaviors).
Changes:
- Replace ad-hoc HTTP calls with
contree-clienttyped methods/models and shared runtime helpers (errors, stream decoding, pagination/iterators). - Rework skill install/remove semantics (project-root specs, owned-file writes/removals, Codex layout alignment) and update docs/examples for renamed global flags (
-o/--format/--output, etc.). - Add/expand end-to-end and doc-lint tests (entrypoint lifecycle, export command, documentation example validation).
Reviewed changes
Copilot reviewed 83 out of 84 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_use.py | Update use tests for typed client mocks |
| tests/test_url_fetch.py | Switch URL fetch tests to ensure_file/models |
| tests/test_tag.py | Update tag tests for typed tag APIs/errors |
| tests/test_show.py | Update show tests for typed operation responses |
| tests/test_shell_repl.py | Align shell error handling + -o flag |
| tests/test_shell_parser.py | Update parser tests for -o global flag |
| tests/test_shell_completer.py | Update completion fixtures to typed models |
| tests/test_session.py | Update session path tests to new helper |
| tests/test_session_cmd.py | Add typed operation helpers for session cmd tests |
| tests/test_main.py | New: assert client context-manager lifecycle in main |
| tests/test_ls.py | Update ls tests for typed inspect + raw RequestSpec path |
| tests/test_kill.py | Update cancel/kill tests for typed operations |
| tests/test_export.py | New: coverage for export archive streaming |
| tests/test_doc_examples.py | New: validate documented CLI examples against parser/help |
| tests/test_cp.py | Update cp tests for streaming download API + progress |
| tests/test_config.py | Migrate config tests to library Profile + constants |
| tests/test_cd.py | Update cd validation tests to typed inspect/list errors |
| tests/test_cat.py | Update cat tests to typed download API + call assertions |
| tests/test_auth.py | Update auth tests to typed whoami parsing behavior |
| tests/conftest.py | Replace fake HTTP stack with contree_client.testing client |
| README.md | Update docs for dependencies + -o flag + workflow tweaks |
| pyproject.toml | Add runtime dependency contree-client>=0.1.3 |
| docs/tutorial/workflows.md | Update examples to -o global output flag |
| docs/tutorial/shell.md | Update REPL format flag docs to -o |
| docs/tutorial/installation.md | Note contree-client dependency |
| docs/tutorial/images.md | Update tag delete example to -U |
| docs/tutorial/configuration.md | Update examples to -o global output flag |
| docs/index.md | Update landing page examples + dependency messaging |
| docs/commands/show.md | Update show docs for -o (needs --raw wording fix) |
| docs/commands/shell.md | Update shell docs to -o global output flag |
| docs/commands/ps.md | Fix kind flag example to -k |
| docs/commands/operation.md | Update operation docs to -o global output flag |
| docs/commands/ls.md | Update ls docs to -o global output flag |
| docs/commands/images.md | Update images docs (include untagged via -a, uuid example) |
| docs/commands/file.md | Update file docs to -o global output flag |
| docs/commands/cd.md | Update cd semantics docs (print cwd; validate via inspect API) |
| docs/commands/auth.md | Update auth docs to -o global output flag |
| contree_cli/types.py | Update flag aliases (-o, --output, force -f) + add --decompress |
| contree_cli/skill_body.md | Refresh skill text (sandbox section templated, -o examples) |
| contree_cli/shell/sources.py | Use typed list APIs + server-side tag prefix filtering |
| contree_cli/shell/repl.py | Handle ContreeAPIError + -o/--output format builtin |
| contree_cli/shell/completer.py | Update completion builtins/flags for -o/--output |
| contree_cli/shell/argmap.py | Add completion mapping for export args |
| contree_cli/session.py | Add SessionStore.select_session helper |
| contree_cli/manual.md | Update manual examples to -o global output flag |
| contree_cli/log.py | Mirror CLI log level into contree_client logger |
| contree_cli/docker/url_fetch.py | Use ensure_file; close HTTPError in HEAD helper |
| contree_cli/docker/kw_run.py | Use typed spawn/status helpers + stream decoding from library |
| contree_cli/docker/kw_from.py | Implement multistage sealing + typed import/wait/cancel |
| contree_cli/docker/kw_copy.py | Implement COPY --from via archive export + extraction RUN (bug noted) |
| contree_cli/docker/kw_add.py | Reject unsupported ADD --from explicitly |
| contree_cli/docker/context.py | Update build context typing + stage tracking |
| contree_cli/config.py | Refactor config around contree_client.profiles + session DB helpers |
| contree_cli/cli/use.py | Use client.resolve_image; reuse SessionStore via select_session |
| contree_cli/cli/tag.py | Use typed tag APIs + resolve-on-delete behavior |
| contree_cli/cli/skill.py | Switch to multi-skill spec expansion + registry cleanup on missing |
| contree_cli/cli/show.py | Use typed operation status + terminal-status constants |
| contree_cli/cli/session.py | Use typed polling; raw RequestSpec for session_key filtering |
| contree_cli/cli/operation.py | Switch to typed iterators + typed cancel/status; progress logs |
| contree_cli/cli/ls.py | Use typed inspect list + raw RequestSpec for ?text=1 |
| contree_cli/cli/images.py | Use typed iterators/import helpers + credential model |
| contree_cli/cli/file.py | Use typed streaming download + ensure_file + file iterators |
| contree_cli/cli/export.py | New: export archive streaming command |
| contree_cli/cli/cp.py | Use streaming download API; support DEST directory targets |
| contree_cli/cli/cd.py | Validate dirs via typed inspect/list + typed errors |
| contree_cli/cli/cat.py | Use typed download; preserve cache behavior |
| contree_cli/cli/build.py | Multistage notes; use session_db_path + typed tag update |
| contree_cli/cli/auth.py | Use typed whoami + stricter parsing/error handling |
| contree_cli/arguments.py | Register new export command |
| contree_cli/agent.md | Update agent guide examples and include export |
| contree_cli/main.py | Drive client via context manager using ExitStack |
| contree_cli/init.py | Update contextvar types to contree-client Profile/CliClient |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+199
to
+201
| try: | ||
| for chunk in ctx.client.inspect_image_archive(image_uuid, src): | ||
| buffer.write(chunk) |
Comment on lines
+141
to
+153
| start = time.monotonic() | ||
| try: | ||
| if args.output: | ||
| with Path(args.output).open("wb") as sink: | ||
| written = write_stream(chunks, sink) | ||
| else: | ||
| written = write_stream(chunks, sys.stdout.buffer) | ||
| sys.stdout.buffer.flush() | ||
| except NotFoundError: | ||
| if args.output: | ||
| Path(args.output).unlink(missing_ok=True) | ||
| logger.error("export: %s: not found in image", path) | ||
| return 1 |
Comment on lines
76
to
80
| Nested objects (`metadata`, `result`) are dropped from the flat row | ||
| — use `--raw` for the full server payload, or `-f json` to keep the | ||
| — use `--raw` for the full server payload, or `-o json` to keep the | ||
| flat structured row. | ||
|
|
||
| Pass `--raw` to skip all of the above and print each operation's |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Switches the CLI onto the public contree-client package (
>=0.1.3) and reworks skill installation semantics.contree-client adoption
contree-clientbecomes the only runtime dependency: HTTP transport, typed API methods, models, retries, operation helpers, image reference resolution, profile parsing, and stream decoding now come from the library.client.pyshrinks to CLI-side glue:CliClientannouncing the CLI identity in the User-Agent,client_from_profile()with the CLI retry policy, and version helpers.config.pykeeps only the write side of profile management (atomic 0600 save, switch, delete with session-DB cleanup) on top ofcontree_client.profiles.uv.locknow resolves the package from PyPI instead of an editable sibling checkout; docs and tests updated across the board.skill install/remove rework
.claude/skills/contree,.agents/skills/contree,.claude/agents/*.md, ...). Paths pointing at a skill artifact (SKILL.md inside,contreebasename,.mdsuffix, tool markers) stay literal..agents/skills(project) /~/.agents/skills(global), matching current Codex discovery; rules stay in$CODEX_HOME.CONTREE_HOMEintowritable_roots, so overridden data directories get correct sandbox permissions.toolsfield, agent template uses the documented comma-separated form, and stale registry rows are forgotten on remove.Test plan
make tests(ruff + mypy strict + pytest): 1869 passed, 4 skipped against contree-client 0.1.3 from PyPI.uv run contree skill install codex:PATHlands inPATH/.agents/skills/contree; raw-dir install/remove cycle leaves the project byte-identical.