feat: add chainweaver run CLI subcommand to execute flows from disk (#129)#158
Open
dgenio wants to merge 1 commit into
Open
feat: add chainweaver run CLI subcommand to execute flows from disk (#129)#158dgenio wants to merge 1 commit into
chainweaver run CLI subcommand to execute flows from disk (#129)#158dgenio wants to merge 1 commit into
Conversation
Closes #129. Adds the `chainweaver run` verb so users can execute a flow without writing Python — the most-requested DX gap per the issue body. Usage: chainweaver run flows/etl.flow.yaml --tools my_pkg.tools \ --input '{"date": "2026-05-15"}' Flags: - --tools <module> (repeatable) — Python import path that exposes Tool instances at top level. The CLI imports the module via importlib.import_module and registers every isinstance(obj, Tool) found in vars(module).values(), de-duplicating by Tool.name. - --input <json-string> / --input-file <path> — mutually exclusive; exactly one is required. Initial input must be a JSON object. - --format table|json — table (default, human-readable) shows one row per executed step plus the final_output; json emits the full ExecutionResult.model_dump_json() for machine consumption. - --quiet — suppresses all stdout/stderr; result communicated via exit code only. Exit codes match the existing CLI contract: - 0 — flow succeeded. - 1 — flow execution failed (result.success == False), missing tool, malformed input JSON, or CLI-level error. - 2 — flow file or tools module not found / not importable. On failure, the first failing StepRecord is also surfaced to stderr as 'chainweaver: step N (tool '<name>') failed: <error_message>' so CI/scripts can grep without parsing the table output. Deferred per the issue body ("once that lands"): - --checkpoint <path> — depends on the Checkpointer landing (PR #136). - --cache <path> — depends on StepCache landing (PR #136). - Plugin entry-point fallback — depends on #130. Each of those reads cleanly as a small follow-up once its dependency merges; no half-wired stubs are added now. Tests: 12 new cases in tests/test_cli.py covering happy path (table + JSON), input-file flag, quiet mode, missing flow file (exit 2), unimportable tools module (exit 2), missing tool (exit 1), malformed JSON input, non-object input, missing input flag, --input/--input-file mutual exclusion, and invalid flow file. Verification: $ ruff check chainweaver/ tests/ examples/ # All checks passed $ ruff format --check chainweaver/ tests/ ... # 49 files already formatted $ python -m mypy chainweaver/ tests/ # Success: no issues $ python -m pytest tests/ -q --no-cov # 479 passed in 1.77s Docs: - README gains a 'Command-line interface' section listing all five subcommands and placing `run` first. - docs/v1-release-criteria.md §6 adds `chainweaver run` to the v1 CLI coverage checklist. - chainweaver/cli.py module docstring lists `run` alongside the other verbs. Stacked on top of #157 (CLI scaffolding refactor); base will auto-retarget to main once #157 merges. https://claude.ai/code/session_01QcSJ3NWhe5B4k1EP25Hx3n
8 tasks
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
Adds the
chainweaver runverb so users can execute a flow without writing Python — the most-requested DX gap per the issue body. Stacked on top of #157 (scaffolding refactor); the base auto-retargets tomainonce #157 merges.chainweaver run flows/etl.flow.yaml \ --tools my_pkg.tools \ --input '{"date": "2026-05-15"}'Closes #129.
Changes
chainweaver/cli.py— newrun_command, two private helpers (_import_tools_from,_parse_initial_input),_run_result_to_tablerenderer, module-docstring update listing the verb.tests/test_cli.py—TestRunCommandwith 12 cases (happy path table + JSON,--input-file,--quiet, missing flow file (exit 2), unimportable tools module (exit 2), missing tool (exit 1), malformed JSON input, non-object input, missing--input/--input-file, mutual exclusion, invalid flow file).README.md— new "Command-line interface" section listing all five subcommands withrunfirst.docs/v1-release-criteria.md§6 — addschainweaver runto the v1 CLI checklist.Behavior
--tools <module>(repeatable,-t)Toolinstances are registered, de-duplicated byTool.name.--input <json-string>(-i)initial_input. Mutually exclusive with--input-file.--input-file <path>--format table|json(-f)tableshows step rows +final_output;jsonemitsExecutionResult.model_dump_json().--quiet(-q)Exit codes match the existing contract:
0— flow succeeded.1— execution failed (result.success == False), missing tool, malformed input JSON, or CLI-level error.2— flow file or tools module not found / not importable.On failure, the first failing
StepRecordis also surfaced to stderr aschainweaver: step N (tool '<name>') failed: <error_message>so CI / scripts can grep without parsing table output.Deferred per the issue body
Per the issue's "once that lands" framing:
--checkpoint <path>— depends onCheckpointer(PR Add middleware, caching, checkpointing, streaming, and OTel support #136). Will be added in a small follow-up once that lands.--cache <path>— depends onStepCache(PR Add middleware, caching, checkpointing, streaming, and OTel support #136). Same.No half-wired stubs were added now.
Testing
ruff check chainweaver/ tests/ examples/)ruff format --check chainweaver/ tests/ examples/)python -m mypy chainweaver/ tests/)python -m pytest tests/ -v --no-cov) — 479/479 passed in 1.77s (467 pre-existing + 12 new)Diff stat:
4 files changed, 625 insertions(+), 1 deletion(-)(240 LoC of CLI code + 353 LoC of tests + 31 LoC README + 2 LoC v1 criteria).Related Issues
Closes #129.
Checklist
AGENTS.mdanddocs/agent-context/)run_commandis reachable via thechainweaverconsole script; CLI docstring + README + v1-release-criteria all updatedTradeoffs / risks
importlib.import_moduleruns that module's top-level code. Documented in the issue and in the per-flag help; out-of-scope to sandbox here.--helpconsumers. Easy 1-flag follow-up PRs once AddCheckpointerprotocol for crash-resume of in-flight executions #128 / Add step-result caching layer for deterministic tool outputs #127 / Add Python entry-point discovery for community-contributed tools and flows #130 merge.--input '[1,2,3]'is rejected with exit 1. Justification: everyFlow.input_schemais a PydanticBaseModel, which requires a dict input. Accepting non-objects would force an artificial conversion. Flagged here in case you'd prefer to relax it.Scope notes
Closes #129 only. Adjacent items (cookbook recipe in #146, GH Action wrapper in #149) are intentionally deferred to their own issues.
https://claude.ai/code/session_01QcSJ3NWhe5B4k1EP25Hx3n
Generated by Claude Code