Skip to content

refactor: modularize cli.ts and add architecture docs (#18, #19)#45

Merged
TonyCasey merged 3 commits intomainfrom
18-19
Jan 26, 2026
Merged

refactor: modularize cli.ts and add architecture docs (#18, #19)#45
TonyCasey merged 3 commits intomainfrom
18-19

Conversation

@TonyCasey
Copy link
Copy Markdown
Owner

@TonyCasey TonyCasey commented Jan 23, 2026

Summary

Changes

CLI Modularization (#18)

  • Extract initCommand and helpers to src/lib/commands/init.ts (572 lines)
  • Extract upCommand and downCommand to src/lib/commands/docker.ts
  • Create src/lib/commands/shared/constants.ts for shared constants (TEMPLATE_ROOT, VERSION, etc.)
  • Update src/lib/commands/index.ts to export all command modules
  • Reduce cli.ts from 1582 to 837 lines (47% reduction)

Architecture Documentation (#19)

Create docs/architecture/ with technical documentation:

  • timeouts.md: Timeout values, cancellation patterns, AbortSignal usage
  • mcp-sessions.md: MCP session lifecycle, initialization, connection reuse
  • dal-routing.md: Backend selection strategy, routing rules, fallback behavior
  • transcripts.md: Claude Code transcript discovery, parsing, capture flow

Testing

  • All existing tests pass
  • TypeScript compiles without errors
  • Lint passes

Closes #18, Closes #19

Summary by CodeRabbit

  • Documentation

    • Added extensive architecture docs: system design, multi-backend routing strategy, session management, timeouts, event-driven hooks, and transcript discovery/processing.
  • Refactor

    • Reorganized the CLI into modular commands and shared utilities for clearer structure and maintainability; includes an improved project init flow and dedicated Docker up/down commands and scaffolding enhancements.

✏️ Tip: You can customize this high-level summary in your review settings.

- Create src/lib/commands/shared/constants.ts for shared constants (TEMPLATE_ROOT, VERSION, DEFAULT_ENDPOINT, etc.)
- Extract initCommand and helper functions to src/lib/commands/init.ts (572 lines)
- Extract upCommand and downCommand to src/lib/commands/docker.ts
- Update commands/index.ts to export all command modules
- Reduce cli.ts from 1582 to 837 lines (47% reduction)
- Remove unused imports from cli.ts

Part of Issue #18 - Modularize cli.ts into separate command modules
Create docs/architecture/ with technical documentation for:
- timeouts.md: Timeout values, cancellation patterns, AbortSignal usage
- mcp-sessions.md: MCP session lifecycle, initialization, connection reuse
- dal-routing.md: Backend selection strategy, routing rules, fallback behavior
- transcripts.md: Claude Code transcript discovery, parsing, capture flow

Closes Issue #19 - Document invariants and contracts
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

Adds five architecture documentation files (timeouts, MCP sessions, DAL routing, transcripts, overall architecture) and refactors the CLI by extracting command implementations into a new src/lib/commands/ module tree; src/lib/cli.ts is reduced to re-exports exposing the public CLI API and shared constants.

Changes

Cohort / File(s) Summary
Architecture Documentation
docs/architecture/README.md, docs/architecture/dal-routing.md, docs/architecture/mcp-sessions.md, docs/architecture/timeouts.md, docs/architecture/transcripts.md
Five new docs describing internal architecture, invariants, contracts, routing rules, MCP session lifecycle, timeout semantics, transcript resolution, and event patterns.
CLI Facade
src/lib/cli.ts
Replaced large inline CLI implementations with a slim facade that re-exports command functions and shared constants from the new commands modules.
Commands - Init
src/lib/commands/init.ts
New init command module implementing project scaffolding, symlink/copy fallback, cleanup utilities, interactive prompts, Claude/OpenCode setup, and exported initCommand, cleanupPreviousInstall, and IInitOptions.
Commands - Docker
src/lib/commands/docker.ts
New module exporting upCommand and downCommand and IDockerOptions, invoking services.docker.compose.
Commands - Index / Barrel
src/lib/commands/index.ts
New barrel re-exporting init/docker commands, option types, and shared constants/types for convenient imports.
Commands - Shared Constants
src/lib/commands/shared/constants.ts, src/lib/commands/shared/index.ts
New shared constants and types (TEMPLATE_ROOT, BUNDLED_OPENCODE_ROOT, VERSION, DEFAULT_ENDPOINT, ZEP_CLOUD_ENDPOINT, DEFAULT_GROUP, DeploymentMode, CliSupport, IGraphitiConfig) and getProjectName() utility, plus a barrel file re-exporting them.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

Poem

🐇 I nibbled docs beneath the moonlit stack,

Built routes and sessions, then put code back,
Commands now in burrows, tidy and bright,
Timeouts and transcripts tucked in for the night,
A little rabbit cheers for modular delight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.54% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: CLI modularization and architecture documentation, with explicit issue references.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #18 (CLI modularization into commands/ modules with shared utilities) and #19 (architecture documentation with timeouts, MCP sessions, DAL routing, transcripts, and events).
Out of Scope Changes check ✅ Passed All changes are in-scope: CLI refactoring into modular commands, shared constants extraction, and comprehensive architecture documentation as specified in linked issues.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@docs/architecture/dal-routing.md`:
- Around line 180-213: The fenced ASCII diagram block that documents
RepositoryFactory → RepositoryRouter (showing "RepositoryFactory",
"RepositoryRouter", routing rules and repository maps) is missing a language
identifier for the markdown fence; change the opening fence from ``` to ```text
so markdownlint passes (i.e., update the diagram block containing
"RepositoryFactory" and "RepositoryRouter" to begin with ```text and keep the
rest unchanged).

In `@docs/architecture/README.md`:
- Around line 20-37: The fenced ASCII diagram block in README.md is missing a
language identifier which triggers markdownlint; update the opening
triple-backtick that precedes the diagram (the block containing the ASCII box
with "CLI / Presentation", "Application Layer", "Domain Layer", "Infrastructure
Layer") to include a language identifier such as text (i.e., change ``` to
```text) so the fence is properly labeled.
- Around line 5-13: Create a new docs/architecture/events.md with event-driven
architecture content, then update docs/architecture/README.md: add an "Events"
row linking to ./events.md in the Contents table (the table containing "Timeout
Semantics", "MCP Sessions", etc.), add an "Events" entry in the Related
Documentation section (the block near where other docs are referenced), and add
a root-level link from the project README.md to the docs/architecture/ directory
so the architecture docs are discoverable from the repository root.

In `@docs/architecture/transcripts.md`:
- Around line 33-37: Add the "text" language identifier to the three unlabeled
Markdown code fences in docs/architecture/transcripts.md so they pass MD040;
specifically, update the first path list fence (the
"~/.claude/projects/<project>/transcript.jsonl ..." block), the workflow/diagram
fence (the "Claude Code Stop Hook → ISessionStopInput ..." block), and the
"Transcript Discovery" output fence (the "Search Paths: ✓ ~/.claude/projects
..." block) by changing their opening fences from ``` to ```text and leaving the
closing fences as-is; apply the same change to the other occurrences mentioned
(lines 125-163 and 222-233).
🧹 Nitpick comments (4)
src/lib/commands/shared/constants.ts (2)

5-6: Import order should have Node.js built-ins first.

Per coding guidelines, imports should be organized: Node.js built-ins, then third-party dependencies, then internal modules.

Proposed fix
-import fs from 'fs-extra';
 import path from 'path';
+import fs from 'fs-extra';

44-44: DEFAULT_GROUP evaluated at module load time may cause test brittleness.

getProjectName() is called when this module is imported, which reads from process.cwd(). This could cause unexpected behavior in tests or when the module is imported from a different working directory context.

Consider making this a function call or lazy evaluation if test isolation becomes an issue:

Alternative: lazy evaluation pattern
-export const DEFAULT_GROUP = getProjectName();
+let _defaultGroup: string | undefined;
+export function getDefaultGroup(): string {
+  if (_defaultGroup === undefined) {
+    _defaultGroup = getProjectName();
+  }
+  return _defaultGroup;
+}

Note: If the current behavior is intentional and tests mock process.cwd() appropriately, this can remain as-is.

src/lib/commands/init.ts (2)

8-22: Import order should have Node.js built-ins first.

Per coding guidelines, organize imports: Node.js built-ins, third-party dependencies, then internal modules.

Proposed fix
-import fs from 'fs-extra';
 import path from 'path';
+import fs from 'fs-extra';
 import chalk from 'chalk';

442-442: Consider extracting repeated "remove if exists" pattern to a helper.

This one-liner pattern appears multiple times (lines 442, 460, 503) and reduces readability. Consider extracting to a small helper function:

Proposed helper function
/**
 * Remove a path if it exists, silently ignoring ENOENT.
 */
async function removeIfExists(linkPath: string): Promise<void> {
  try {
    await fs.lstat(linkPath);
    await fs.remove(linkPath);
  } catch (err: unknown) {
    const error = err as NodeJS.ErrnoException;
    if (error.code !== 'ENOENT') {
      throw err;
    }
  }
}

Then usage becomes clearer:

-try { await fs.lstat(skillLink); await fs.remove(skillLink); } catch { /* Doesn't exist */ }
+await removeIfExists(skillLink);

This would also improve error handling by explicitly checking for ENOENT rather than swallowing all errors.

@TonyCasey
Copy link
Copy Markdown
Owner Author

Addressing all review comments from CodeRabbit:

Fixed Issues

Markdown Fence Language Identifiers (MD040)

  • Added text language identifier to ASCII diagram in docs/architecture/dal-routing.md (line 180)
  • Added text language identifier to Clean Architecture diagram in docs/architecture/README.md (line 20)
  • Added text language identifier to 3 code fences in docs/architecture/transcripts.md (lines 33, 125, 222)

Missing events.md Documentation

  • Created docs/architecture/events.md with comprehensive event-driven architecture content
  • Added Events row to the Contents table in README.md
  • Added Events entry to the Related Documentation section

Import Order (Nitpicks)

  • Fixed import order in src/lib/commands/shared/constants.ts - Node.js built-in path now comes before fs-extra
  • Fixed import order in src/lib/commands/init.ts - Node.js built-in path now comes before fs-extra

Notes on Other Nitpicks

  • DEFAULT_GROUP lazy evaluation: Keeping current behavior as it's intentional - tests that need different values can mock process.cwd(). The eager evaluation ensures consistent group ID throughout the application lifecycle.
  • "remove if exists" helper: Good suggestion for future refactoring, but keeping current inline pattern to minimize scope of this PR.

All changes are ready for re-review.

- Add text language identifier to markdown fences in dal-routing.md, README.md, and transcripts.md (MD040)
- Create docs/architecture/events.md with event-driven architecture documentation
- Add events.md to Contents table and Related Documentation in README.md
- Fix import order in constants.ts and init.ts (Node.js built-ins first)
@TonyCasey TonyCasey merged commit 930ab1c into main Jan 26, 2026
2 checks passed
@TonyCasey TonyCasey deleted the 18-19 branch January 26, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document invariants and contracts for core systems Modularize cli.ts into separate command modules

1 participant