feat(cli): redeploy command-line entry point (deploy/simulate/apply-config/verify/status/snapshot) (#150) - #160
Merged
Merged
Conversation
Adds apps/cli, a dependency-free (node:util parseArgs) CLI wrapping existing library APIs with no new business logic: - deploy / simulate -> @redeploy/core - apply-config -> @redeploy/config - verify (--target deployment|config) -> @redeploy/verify - status / snapshot -> @redeploy/reader Mirrors deploy-server's env contract (RPC_URL, DEPLOYER_PRIVATE_KEY, FOUNDRY_OUT, DEPLOYMENT_DIR, .env precedence) and never echoes secrets (redaction is defense-in-depth on top of never putting the raw/normalized key into any result payload). Supports human-readable and --json output, non-zero exit on failure, and per-command --help. apply-config / verify --target config build the ChainReader/ConfigExecutor required by those libraries' injectable interfaces using foundryArtifactResolver (ABI) + readDeployment (address/contract-name book) + viem (encode/decode, already a core dependency) — no ABI-encoding logic is reinvented beyond that glue. Registers the module in .claude/gates.json. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
buildConfigExecutor's execute() broadcast eth_sendTransaction with no gas/gasPrice fields. jsonRpcProvider() (core/src/provider/jsonRpc.ts) takes the LEGACY signing branch whenever maxFeePerGas is absent, and that branch reads gas/gasPrice verbatim from the params -- with both undefined the signed raw tx serialized gas=0/gasPrice=0, which real nodes reject, so every apply-config step failed on a live chain. Query eth_estimateGas and eth_gasPrice before sending and forward both into the eth_sendTransaction params so the legacy branch has real, non-zero values.
robercano
approved these changes
Jul 21, 2026
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
@redeploy/cli(apps/cli) — a thin command-line entry point wrapping the existing library APIs so reDeploy is usable from a terminal and CI/CD without the studio or hand-written scripts. Introduces the newclimodule (bootstrap: package skeleton +.claude/gates.jsonmodule entry +module:clilabel).Closes #150.
Subcommands (all thin wrappers)
deploy->@redeploy/coredeploy()simulate->@redeploy/coresimulate()apply-config->@redeploy/configapplyConfig()verify->@redeploy/verifyverifyDeployment()/verifyConfig()status->@redeploy/readerreadDeployment()(reader view)snapshot->@redeploy/readerbuildSnapshot()Contract
apps/deploy-server:RPC_URL,DEPLOYER_PRIVATE_KEY,FOUNDRY_OUT,DEPLOYMENT_DIR; real env wins over.env.--jsonoutput modes; non-zero exit on any failure for CI gating.DEPLOYER_PRIVATE_KEYis never printed/logged/echoed — surfaced only as the derived deployer address; all output/errors funnel through a redaction pass. Locked in by tests.node:utilparseArgs); no heavy CLI framework.Bootstrap (root/shared, explicit infra step)
.claude/gates.json: newclimodule entry (apps/cli).module:core(placeholder) ->module:cli(label created).pnpm-lock.yamlupdated as the automatic result of adding the workspace package.Gates
build, typecheck, lint, test, coverage all green. apps/cli coverage ~99% statements / ~95% branches / ~88% functions (threshold 80).
Review
Routed through all four lenses (correctness, tests, security, performance; consensus = all). One correctness blocker was found and fixed in review:
apply-configon-chain txs were broadcast with no gas limit/fee (core'sjsonRpcProviderfills only nonce/chainId), which would fail on a live node — now the executor estimates gas (eth_estimateGas) and sets a legacygasPrice(eth_gasPrice), with a test asserting non-zero gas + fee on the sent params. Re-reviewed and approved by correctness + security.🤖 Generated with Claude Code