feat: add rocketride init command for terminal#727
feat: add rocketride init command for terminal#727AditM99 wants to merge 6 commits intorocketride-org:developfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds an offline ChangesInit command, packaging, CLI wiring, docs, and tests
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI as "CLI (main.py)"
participant Init as "InitCommand"
participant Detector as "Agent Detector"
participant FS as "File System"
User->>CLI: run `rocketride init [flags]`
CLI->>CLI: parse args, select 'init'
CLI->>Init: execute(client=None)
Init->>Init: resolve templates dir (package or dev fallback)
Init->>Detector: detect agents (env, project markers, home)
Detector-->>Init: detected agents
Init->>Init: apply --agent / --no-agents filters
Init->>FS: write `.rocketride/docs/` files (idempotent / force / no-overwrite)
Init->>FS: merge/install agent stubs (marker-replace or append)
Init->>FS: ensure `.rocketride/` in `.gitignore`
Init-->>CLI: return exit code (0/1)
CLI-->>User: print status
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
No description provided. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/client-python/scripts/tasks.js`:
- Line 257: The wheel build step (client-python:wheel-build) currently only keys
off SRC_DIR changes, so edits to the new init templates (added via
client-python:copy-init-templates) and docs (docs/agents, docs/stubs, README
copy) can be ignored and produce stale wheels; update the
change-detection/fingerprint used by client-python:wheel-build to include the
template/doc sources (at minimum docs/agents, docs/stubs and the README path
used by client-python:copy-readme) alongside SRC_DIR so the wheel rebuilds when
those files change.
In `@packages/client-python/src/rocketride/cli/commands/init.py`:
- Around line 335-339: The code sets home = Path(os.environ.get('USERPROFILE')
or os.environ.get('HOME') or ''), which makes Path('') => '.' and causes the
subsequent checks (home / '.claude').is_dir() and (home / '.cursor').is_dir() to
inspect the current directory; change it so home is None when no env var is
present (e.g. home_env = os.environ.get('USERPROFILE') or
os.environ.get('HOME'); if home_env: home = Path(home_env) else: home = None)
and only run found.add('claude-code') / found.add('cursor') when home is not
None and (home / '.claude').is_dir() / (home / '.cursor').is_dir(); reference
symbols: home, USERPROFILE/HOME env lookups, and the checks (home /
'.claude').is_dir() and (home / '.cursor').is_dir().
- Around line 177-181: The loop over _DOC_FILES in execute() currently prints
and continues on missing templates; change it to collect missing filenames and
cause execute() to fail (return non-zero or raise SystemExit with code 1) if any
required doc is absent, and do the same for the explicit agent-stub template
check (the code that checks the requested agent stub template around the
existing agent-stub handling). Update the flow so missing required templates do
not continue scaffolding (no partial success) and ensure the error message
includes which templates are missing before exiting.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: e83ff455-135e-412b-8dfc-11a0417b5770
📒 Files selected for processing (7)
docs/README-python-client.mdpackages/client-python/pyproject.tomlpackages/client-python/scripts/tasks.jspackages/client-python/src/rocketride/cli/commands/__init__.pypackages/client-python/src/rocketride/cli/commands/init.pypackages/client-python/src/rocketride/cli/main.pypackages/client-python/tests/test_cli_init.py
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/client-python/scripts/tasks.js (1)
110-145:⚠️ Potential issue | 🟠 Major | ⚡ Quick winInclude packaging metadata in the wheel fingerprint.
client-python:wheel-sourcecopies the wholePACKAGE_DIRintoBUILD_DIR, butcomputeWheelInputsHash()only trackssrc/rocketride, the template dirs, and README metadata. Apyproject.toml(or other packaged top-level file) change can alter the wheel while this step still prints “No changes detected” and skips rebuilding, leaving stale artifacts indist.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/client-python/scripts/tasks.js` around lines 110 - 145, computeWheelInputsHash currently fingerprints only SRC_DIR, AGENT_DOCS_SRC, AGENT_STUBS_SRC and README_SRC; add the package-level metadata files/dir so packaging changes trigger rebuilds. Update computeWheelInputsHash to also fingerprint PACKAGE_DIR (or explicitly fingerprint top-level files like pyproject.toml, setup.cfg, and any packaged top-level files) and include those fingerprints in the combined string before hashing; ensure makeWheelBuildAction still compares the same saved SRC_HASH_KEY so the new combined hash is saved via saveSourceHash after a successful build.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/client-python/src/rocketride/cli/commands/init.py`:
- Around line 142-150: The agent stubs loop in execute() currently calls
_install_stub(...) unconditionally, causing existing stub files to be
overwritten even when --no-overwrite or interactive confirmation should prevent
changes; update execute() (the for agent in agents: block) to respect the CLI
overwrite flags and confirmation logic by passing the appropriate
force/no_overwrite boolean into _install_stub or by pre-checking the target_path
for existence and honoring the user's choice (reuse the same confirmation
routine used for docs generation), so that _install_stub only rewrites when
force is true or the user explicitly confirms; ensure the same fix is applied to
the other stub-install call area (lines referenced ~211-224).
---
Outside diff comments:
In `@packages/client-python/scripts/tasks.js`:
- Around line 110-145: computeWheelInputsHash currently fingerprints only
SRC_DIR, AGENT_DOCS_SRC, AGENT_STUBS_SRC and README_SRC; add the package-level
metadata files/dir so packaging changes trigger rebuilds. Update
computeWheelInputsHash to also fingerprint PACKAGE_DIR (or explicitly
fingerprint top-level files like pyproject.toml, setup.cfg, and any packaged
top-level files) and include those fingerprints in the combined string before
hashing; ensure makeWheelBuildAction still compares the same saved SRC_HASH_KEY
so the new combined hash is saved via saveSourceHash after a successful build.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 558954e1-403e-459f-9fc5-bd65bed61552
📒 Files selected for processing (3)
packages/client-python/scripts/tasks.jspackages/client-python/src/rocketride/cli/commands/init.pypackages/client-python/tests/test_cli_init.py
| # Stubs: marker-based merge — already idempotent, no prompt needed. | ||
| for agent in agents: | ||
| stub_src, stub_target_rel = _AGENTS[agent] | ||
| self._install_stub( | ||
| stub_path=templates / 'stubs' / stub_src, | ||
| target_path=target_root / stub_target_rel, | ||
| target_root=target_root, | ||
| agent=agent, | ||
| ) |
There was a problem hiding this comment.
Honor --no-overwrite and confirmation rules for existing stub files.
The overwrite contract is enforced for docs, but not for agent stubs. _install_stub() rewrites any existing target when the merged content changes, and execute() calls it without force / no_overwrite handling. That means rocketride init --no-overwrite still modifies pre-existing CLAUDE.md, AGENTS.md, .github/copilot-instructions.md, etc., and the default rerun path can append a new marked block with no confirmation.
Suggested fix
- self._install_stub(
+ self._install_stub(
stub_path=templates / 'stubs' / stub_src,
target_path=target_root / stub_target_rel,
target_root=target_root,
agent=agent,
+ force=force,
+ no_overwrite=no_overwrite,
)- def _install_stub(self, *, stub_path: Path, target_path: Path, target_root: Path, agent: str) -> None:
+ def _install_stub(self, *, stub_path: Path, target_path: Path, target_root: Path, agent: str, force: bool, no_overwrite: bool) -> None:
"""Merge the stub template into target_path using the marker protocol."""
stub_content = stub_path.read_text(encoding='utf-8')
target_path.parent.mkdir(parents=True, exist_ok=True)
existing = ''
if target_path.exists():
existing = target_path.read_text(encoding='utf-8')
merged = _merge_marked_content(existing, stub_content)
if _normalize_text(merged) == _normalize_text(existing):
return # nothing to do
+ rel = target_path.relative_to(target_root).as_posix()
+ if target_path.exists():
+ if no_overwrite:
+ print(f' - kept {rel} ({agent}, --no-overwrite)')
+ return
+ if not force and not _confirm_overwrite(rel):
+ raise _Aborted('user declined to overwrite')
+
target_path.write_text(merged, encoding='utf-8')
- try:
- rel = target_path.relative_to(target_root).as_posix()
- except ValueError:
- rel = str(target_path)
print(f' + wrote {rel} ({agent})')Also applies to: 211-224
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/client-python/src/rocketride/cli/commands/init.py` around lines 142
- 150, The agent stubs loop in execute() currently calls _install_stub(...)
unconditionally, causing existing stub files to be overwritten even when
--no-overwrite or interactive confirmation should prevent changes; update
execute() (the for agent in agents: block) to respect the CLI overwrite flags
and confirmation logic by passing the appropriate force/no_overwrite boolean
into _install_stub or by pre-checking the target_path for existence and honoring
the user's choice (reuse the same confirmation routine used for docs
generation), so that _install_stub only rewrites when force is true or the user
explicitly confirms; ensure the same fix is applied to the other stub-install
call area (lines referenced ~211-224).
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/client-python/scripts/tasks.js`:
- Around line 79-83: The action callback parameter `ctx` is unused and should
follow the repo convention for unused variables; rename the parameter in the
`run` async function from `ctx` to `_ctx` (i.e., change `run: async (ctx, task)
=> { ... }` to `run: async (_ctx, task) => { ... }`) and ensure there are no
remaining references to `ctx` in the function body so linters pass.
- Around line 137-143: The current early-exit uses exists(DIST_DIR) as proof of
a successful build; instead make the check verify that expected artifacts exist
(e.g., at least one .whl or .tar.gz) before skipping. In the block that computes
hash = computeWheelInputsHash() and reads savedHash = getState(SRC_HASH_KEY),
replace the DIST_DIR existence check with a check for artifact files inside
DIST_DIR (e.g., glob for *.whl and *.tar.gz) and only treat outputExists as true
when such files are present; update the conditional that sets task.output = 'No
changes detected' to require both hash === savedHash and artifact files present.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ab383ba8-9adc-4638-80cd-9d66e611b176
📒 Files selected for processing (1)
packages/client-python/scripts/tasks.js
| run: async (ctx, task) => { | ||
| const docsStats = await syncDir(AGENT_DOCS_SRC, path.join(TEMPLATES_DEST_BASE, 'docs'), { package: true }); | ||
| const stubsStats = await syncDir(AGENT_STUBS_SRC, path.join(TEMPLATES_DEST_BASE, 'stubs'), { package: true }); | ||
| task.output = `docs: ${formatSyncStats(docsStats)} | stubs: ${formatSyncStats(stubsStats)}`; | ||
| }, |
There was a problem hiding this comment.
Prefix the unused action context with _.
ctx is never read in this action, so the new code drifts from the repo’s JS convention for unused variables.
♻️ Proposed fix
- run: async (ctx, task) => {
+ run: async (_ctx, task) => {As per coding guidelines, "Unused variables must be prefixed with underscore (_)."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/client-python/scripts/tasks.js` around lines 79 - 83, The action
callback parameter `ctx` is unused and should follow the repo convention for
unused variables; rename the parameter in the `run` async function from `ctx` to
`_ctx` (i.e., change `run: async (ctx, task) => { ... }` to `run: async (_ctx,
task) => { ... }`) and ensure there are no remaining references to `ctx` in the
function body so linters pass.
asclearuc
left a comment
There was a problem hiding this comment.
Thanks @AditM99 for adding terminal-side init — this closes a real gap and the marker-merge design is well thought out. Requesting changes on a handful of small issues; details inline.
See the inline comments for specifics, and please also address CodeRabbit's feedback (r3165270221 in particular).
| 'events': EventsCommand, | ||
| 'list': ListCommand, | ||
| 'store': StoreCommand, | ||
| 'init': InitCommand, |
There was a problem hiding this comment.
Dead code. The early-return at L573 (if self.args.command == 'init': ...) handles init before this dispatch table is consulted, so this entry is unreachable. Remove it — keeping it implies the command flows through command_map, which it doesn't, and a future contributor will waste time chasing the dual registration.
|
|
||
|
|
||
| def _run(coro): | ||
| return asyncio.get_event_loop().run_until_complete(coro) if False else asyncio.run(coro) |
There was a problem hiding this comment.
The ... run_until_complete(coro) if False else asyncio.run(coro) ternary looks like a debugging leftover — the if False branch is unreachable. Simplify to:
def _run(coro):
return asyncio.run(coro)
| unknown = [a for a in chosen if a not in _AGENTS] | ||
| if unknown: | ||
| raise SystemExit(f'Unknown agent(s): {", ".join(unknown)}. Valid: {", ".join(_AGENTS)} or "all".') | ||
| # Preserve canonical order for deterministic output. |
There was a problem hiding this comment.
This branch (lines 171-173) is unreachable. The argparse parser is configured with choices=['cursor', 'claude-code', 'windsurf', 'copilot', 'claude-md', 'agents-md', 'all'], so any value not in that list is rejected before the command runs. Either drop this check, or drop choices from the argparse declaration — keeping both means the valid-agent list has to be maintained in two places.
Also: if you do keep a runtime check, please match the surrounding style (print('Error: ...'); return 1 from the caller) instead of raise SystemExit(...). SystemExit bypasses the cli.cancel() cleanup in main.py and is the only error path in this command that doesn't go through the int-return convention.
| # ------------------------------------------------------------------ | ||
|
|
||
| def _install_docs(self, source_dir: Path, target_root: Path, *, force: bool, no_overwrite: bool) -> None: | ||
| target_dir = target_root / '.rocketride' / 'docs' |
There was a problem hiding this comment.
The VS Code AgentManager.installDocs (apps/vscode/src/agents/agent-manager.ts) removes files in .rocketride/docs/ that aren't in the canonical _DOC_FILES list, so stale docs get cleaned up on re-install. This CLI version only adds/updates and never deletes.
The module docstring says terminal- and IDE-created workspaces should be "interchangeable" — but a CLI re-init won't clean up an obsolete file that an IDE re-init would. Please either:
- Add the same obsolete-file pruning here, or
- Soften the docstring claim so future readers don't assume parity that doesn't exist.
(1) is preferable since the canonical list is already in _DOC_FILES.
| def _normalized(b: bytes) -> bytes: | ||
| r"""Strip CR so \r\n vs \n doesn't trigger a false rewrite.""" | ||
| return b.replace(b'\r\n', b'\n') | ||
|
|
||
|
|
||
| def _normalize_text(s: str) -> str: | ||
| return s.replace('\r\n', '\n') |
There was a problem hiding this comment.
These two helpers differ only in input type (bytes vs str). _normalized is used in exactly one place (_install_docs); inline it as existing.replace(b'\r\n', b'\n') == new_content.replace(b'\r\n', b'\n') and keep just _normalize_text. Or vice-versa — but two near-identical helpers will drift over time.
|
|
||
| def __init__(self, cli, args): | ||
| """Initialize InitCommand with CLI context and parsed arguments.""" | ||
| super().__init__(cli, args) |
There was a problem hiding this comment.
This __init__ only calls super().__init__(cli, args) — it can be deleted. BaseCommand.__init__ already does the same thing and the docstring doesn't add information beyond what's on the base class.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
packages/client-python/src/rocketride/cli/commands/init.py (1)
138-146:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHonor
--force/--no-overwritefor agent stub files.The overwrite flags are enforced for docs via
_install_docs(), but_install_stub()is called without passingforceorno_overwrite. This means--no-overwritewon't prevent modifications to existing stub files likeCLAUDE.md, and rerunning without--forcecan silently modify them without confirmation.Suggested fix
for agent in agents: stub_src, stub_target_rel = _AGENTS[agent] self._install_stub( stub_path=templates / 'stubs' / stub_src, target_path=target_root / stub_target_rel, target_root=target_root, agent=agent, + force=force, + no_overwrite=no_overwrite, )Then update
_install_stubsignature and add the same guard logic used in_install_docs.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/client-python/src/rocketride/cli/commands/init.py` around lines 138 - 146, The agent stub installation ignores overwrite flags; update calls to _install_stub in init.py to pass the CLI overwrite flags (e.g., force and no_overwrite) the same way _install_docs does, then change the _install_stub function signature to accept those parameters and implement the same guard logic used in _install_docs (check existing target file, skip or overwrite based on force/no_overwrite and surface an appropriate message) so --force and --no-overwrite are honored for stub files like CLAUDE.md.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/client-python/tests/test_cli_init.py`:
- Around line 42-50: Replace the duplicated constant in the test with an import
of the canonical list from the module under test: remove the hard-coded
_DOC_FILE_NAMES tuple and import _DOC_FILES from the package's init module (the
same symbol defined in init.py) so the test uses _DOC_FILES as its source of
truth; update references in the test to use the imported name (e.g., alias to
_DOC_FILE_NAMES if you want the same local name) to avoid drift when the
canonical list changes.
---
Duplicate comments:
In `@packages/client-python/src/rocketride/cli/commands/init.py`:
- Around line 138-146: The agent stub installation ignores overwrite flags;
update calls to _install_stub in init.py to pass the CLI overwrite flags (e.g.,
force and no_overwrite) the same way _install_docs does, then change the
_install_stub function signature to accept those parameters and implement the
same guard logic used in _install_docs (check existing target file, skip or
overwrite based on force/no_overwrite and surface an appropriate message) so
--force and --no-overwrite are honored for stub files like CLAUDE.md.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: de622aa2-5e40-4864-91ca-31575092f624
📒 Files selected for processing (3)
packages/client-python/src/rocketride/cli/commands/init.pypackages/client-python/src/rocketride/cli/main.pypackages/client-python/tests/test_cli_init.py
Summary
Add a rocketride init command to the CLI that initializes a RocketRide project from the terminal, without requiring an IDE.
When the user executes the command a directory is created and populated with everything an agent needs to start building pipelines.
Command is documented under rocketride --help
Type
Feature
Testing
Tests added or updated
Tested locally
./builder testpassesChecklist
Linked Issue
Fixes #656
Summary by CodeRabbit
New Features
rocketride initscaffolds a local workspace: creates docs, installs selectable agent stubs (--agent/--no-agents), supports idempotent merges/overwrites, updates.gitignore, and returns clear success/error codes.Documentation
rocketride initand clarify it runs fully offline.Tests
Chores