Skip to content

Conversation

Zeeeepa
Copy link
Owner

@Zeeeepa Zeeeepa commented Sep 12, 2025

User description

Motivation

Content

Testing

Please check the following before marking your PR as ready for review

  • I have added tests for my changes
  • I have updated the documentation or added new documentation as needed

PR Type

Enhancement, Bug fix


Description

  • Add MCP server command and integration

  • Fix pre-commit formatting and linting issues

  • Resolve type checking and import errors

  • Add team roles documentation


Diagram Walkthrough

flowchart LR
  A["CLI Commands"] --> B["MCP Server"]
  A --> C["Code Quality"]
  C --> D["Linting Fixes"]
  C --> E["Type Checking"]
  C --> F["Import Handling"]
  G["Documentation"] --> H["Team Roles"]
Loading

File Walkthrough

Relevant files
Enhancement
3 files
cli.py
Add MCP command to CLI                                                                     
+2/-0     
__init__.py
Create MCP command module                                                               
+1/-0     
main.py
Implement MCP server command                                                         
+13/-0   
Formatting
17 files
claude_log_utils.py
Fix type annotations and imports                                                 
+5/-5     
claude_log_watcher.py
Fix imports and type annotations                                                 
+14/-16 
claude_session_api.py
Reorder imports for consistency                                                   
+2/-1     
quiet_console.py
Fix imports and remove trailing newlines                                 
+1/-1     
telemetry.py
Remove unused imports                                                                       
+0/-3     
__init__.py
Fix missing newline at EOF                                                             
+1/-1     
main.py
Fix string formatting and newlines                                             
+5/-5     
__init__.py
Fix missing newline at EOF                                                             
+1/-1     
api_client.py
Fix import ordering                                                                           
+1/-0     
executor.py
Remove duplicate imports                                                                 
+0/-5     
consent.py
Remove unused imports                                                                       
+0/-3     
exception_logger.py
Fix import ordering                                                                           
+2/-2     
org.py
Remove unused import and fix formatting                                   
+2/-3     
repo.py
Fix type annotations and formatting                                           
+43/-54 
get_logger.py
Fix import ordering                                                                           
+1/-1     
test_top_level_imports.py
Fix formatting and imports                                                             
+25/-26 
codegen_theme.tcss
Fix missing newline at EOF                                                             
+3/-3     
Bug fix
14 files
claude_session_active_hook.py
Fix type annotation for None assignment                                   
+1/-1     
claude_session_hook.py
Fix type annotations and conditional checks                           
+3/-2     
claude_session_stop_hook.py
Fix type annotation for None assignment                                   
+1/-1     
main.py
Change logger.error to logger.exception                                   
+1/-1     
tui.py
Replace unicode character and formatting fixes                     
+42/-54 
main.py
Fix imports and unicode character                                               
+13/-21 
tui.py
Fix formatting and unicode character                                         
+54/-73 
debug_exporter.py
Fix timezone usage for datetime                                                   
+4/-4     
otel_setup.py
Fix type checking assertion                                                           
+3/-2     
agent_detail.py
Fix git operations and imports                                                     
+42/-36 
app.py
Change logger.error to logger.exception                                   
+5/-5     
inplace_print.py
Fix import for collections.abc                                                     
+1/-1     
repo_operator.py
Fix return types and string handling                                         
+7/-3     
repo_config.py
Fix None handling in config                                                           
+4/-2     
Error handling
2 files
language.py
Add import error handling                                                               
+31/-15 
pr_review.py
Add import error handling                                                               
+5/-1     
Tests
2 files
test_agent.py
Add type ignore for test errors                                                   
+1/-1     
test_usage_demo.py
Add type ignore for test errors                                                   
+1/-1     
Documentation
3 files
QUICK_START_LOGGING.md
Fix formatting and code examples                                                 
+53/-66 
docs.json
Add team roles navigation                                                               
+6/-1     
team-roles.mdx
Add comprehensive team roles documentation                             
+111/-0 
Dependencies
1 files
pyproject.toml
Add MCP dependency                                                                             
+1/-0     
Additional files
14 files
__init__.py +0/-1     
README.md [link]   
__init__.py [link]   
prompts.py [link]   
resources.py [link]   
runner.py [link]   
server.py [link]   
__init__.py [link]   
dynamic.py [link]   
static.py [link]   
__init__.py [link]   
test_basic_integration.py [link]   
test_server_startup.py [link]   
test_simple_integration.py [link]   

Summary by CodeRabbit

  • New Features

    • Added “mcp” CLI command to start the MCP server (stdio/http transport with host/port options).
  • Improvements

    • Log outputs now include exception tracebacks in more scenarios.
    • Telemetry debug export timestamps standardized to UTC.
    • Org/Repo selection now preserves existing entries in your .env file.
  • Documentation

    • Added “Team Roles” (MEMBER, MANAGER, ADMIN) page and “Agent Permissions” to Settings.
    • Updated Quick Start Logging examples to concise inline patterns; clarified steps and formatting.
  • Chores

    • Added mcp-python dependency.

codegen-sh bot and others added 7 commits September 11, 2025 17:43
- Create comprehensive team-roles.mdx documentation explaining ADMIN, MANAGER, and MEMBER roles
- Include permission matrix showing what each role can and cannot do
- Add best practices and security considerations for role management
- Update docs.json navigation to include team-roles and agent-permissions pages

Co-authored-by: Jay Hack <[email protected]>
- Fixed ruff formatting issues in multiple files
- Standardized quote usage and formatting
- Fixed ambiguous unicode character in tui.py
- Replace ambiguous ℹ (INFORMATION SOURCE) with 'i' in org and repo TUI files
- Resolves RUF001 linting errors
- Replace ambiguous ℹ (INFORMATION SOURCE) with 'i' in console print statements
- Resolves remaining RUF001 linting errors
- Add timezone import and use UTC timezone for datetime.now() calls
- Resolves DTZ005 linting errors
- Add type ignore comments for intentional test errors in Agent() constructor calls
- Fix callable check for create_claude_session function
- Replace LocalGitRepo method calls with direct git CLI operations in agent_detail.py
- Add try/except blocks around SDK imports with fallback behavior in language.py and pr_review.py

This addresses multiple type checking diagnostics including:
- Missing argument errors in tests
- Call non-callable errors
- Unresolved attribute errors
- Unresolved import errors for SDK modules
- Renamed tests/cli/mcp to tests/cli/mcp_integration to avoid namespace conflict with installed mcp package
- Renamed src/codegen/cli/mcp to src/codegen/cli/mcp_server to avoid namespace conflict
- Updated import paths in src/codegen/cli/commands/mcp/main.py
- Added missing MCP dependencies: fastmcp>=2.9.0 and mcp-python>=0.1.4
- Fixed import resolution issues that were causing test failures
- All MCP integration tests now pass successfully

The issue was that local directories named 'mcp' were shadowing the installed
mcp package, causing ImportError: No module named 'mcp.types' when pytest
tried to import the package. This fix resolves the namespace conflicts while
maintaining all functionality.
Copy link

sourcery-ai bot commented Sep 12, 2025

Reviewer's Guide

This PR refactors import structures and code formatting across multiple CLI and TUI modules, standardizes type hint syntax and environment file update logic, enhances fallback handling and telemetry timestamp consistency, adjusts documentation formatting, and introduces a new team-roles documentation page along with an MCP server command.

Class diagram for updated type hints in ClaudeLogWatcher and Manager

classDiagram
    class ClaudeLogWatcher {
        -session_id: str
        -org_id: int | None
        -poll_interval: float
        -on_log_entry: Callable[[dict[str, Any]], None] | None
        +__init__(session_id: str, org_id: int | None = None, poll_interval: float = 1.0, on_log_entry: Callable[[dict[str, Any]], None] | None = None)
        +_read_new_lines(start_line: int, end_line: int) list[dict[str, Any]]
        +_process_log_entry(log_entry: dict[str, Any])
        +_send_log_entry(log_entry: dict[str, Any])
        +get_stats() dict[str, Any]
    }
    class ClaudeLogWatcherManager {
        -watchers: dict[str, ClaudeLogWatcher]
        +start_watcher(session_id: str, org_id: int | None = None, poll_interval: float = 1.0, on_log_entry: Callable[[dict[str, Any]], None] | None = None) bool
        +get_active_sessions() list[str]
        +get_watcher_stats(session_id: str) dict[str, Any] | None
        +get_all_stats() dict[str, dict[str, Any]]
    }
    ClaudeLogWatcherManager "1" *-- "*" ClaudeLogWatcher
Loading

Class diagram for new MCP command integration

classDiagram
    class mcp {
        +mcp(transport: str = "stdio", host: str = "localhost", port: int = 8000)
    }
    class run_server {
        +run_server(transport: str, host: str, port: int)
    }
    mcp --> run_server
Loading

Class diagram for updated RepoConfig.from_envs fallback logic

classDiagram
    class RepoConfig {
        +from_envs() RepoConfig
    }
    class RepositoryConfig {
        +path: str
        +language: str
        +name: str
        +full_name: str
    }
    RepoConfig ..> RepositoryConfig
Loading

Class diagram for updated repo.py utility functions with new type hints

classDiagram
    class repo_utils {
        +get_repo_env_status() dict[str, str]
        +get_repo_display_info() list[dict[str, str]]
        +fetch_repositories_for_org(org_id: int) list[dict[str, Any]]
        +get_mock_repositories() list[dict[str, Any]]
        +ensure_repositories_cached(org_id: int | None = None) list[dict[str, Any]]
    }
Loading

Class diagram for AgentDetailTUI and JSONViewerTUI with updated type hints

classDiagram
    class AgentDetailTUI {
        +__init__(agent_run: dict[str, Any], org_id: int | None = None)
        -agent_run: dict[str, Any]
        -agent_data: dict[str, Any] | None
    }
    class JSONViewerTUI {
        +__init__(data: dict[str, Any])
        -data: dict[str, Any]
    }
    AgentDetailTUI --> JSONViewerTUI
Loading

File-Level Changes

Change Details Files
TUI modules cleanup and import consolidation
  • Removed unused imports and consolidated utility imports
  • Standardized whitespace and string quoting in compose and action methods
  • Unified exit notifications and .env update messaging
src/codegen/cli/commands/repo/tui.py
src/codegen/cli/commands/org/tui.py
src/codegen/cli/tui/app.py
Environment file update logic unification
  • Harmonized newline handling and file write operations
  • Simplified update_env_file and update_env_file_with_repo functions
  • Standardized notification output for persistence instructions
src/codegen/cli/commands/repo/tui.py
src/codegen/cli/utils/repo.py
src/codegen/cli/commands/org/tui.py
Type hint normalization
  • Replaced Dict/List typing with dict and list generics
  • Aligned function signatures to use consistent typing style
  • Updated imports for collections.abc Iterable
src/codegen/cli/utils/repo.py
src/codegen/cli/commands/claude/claude_log_utils.py
src/codegen/cli/utils/inplace_print.py
Fallback import handling in language utilities
  • Wrapped SDK imports in try/except to provide default extension lists
  • Ensured GLOBAL_FILE_IGNORE_LIST defaults on import failure
src/codegen/git/utils/language.py
Telemetry timestamp and exception logging improvements
  • Switched to timezone.utc for debug exporter timestamps
  • Replaced logger.error with logger.exception for full tracebacks
  • Reordered imports for exception_logger
src/codegen/cli/telemetry/debug_exporter.py
src/codegen/cli/telemetry/exception_logger.py
Quick start logging documentation formatting
  • Corrected list numbering and indentation
  • Collapsed multi-line code blocks into concise logging patterns
  • Fixed inconsistent blank lines
QUICK_START_LOGGING.md
CLI entrypoint and command enhancements
  • Added new ‘mcp’ top-level command and dependency
  • Reordered and cleaned imports in repo and org main commands
  • Updated console output icons and instructions
src/codegen/cli/cli.py
src/codegen/cli/commands/repo/main.py
pyproject.toml
New team roles documentation and MCP server module
  • Added detailed roles.md with hierarchy, matrix, and best practices
  • Introduced mcp command module and server runner integration
docs/settings/team-roles.mdx
src/codegen/cli/commands/mcp/main.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

coderabbitai bot commented Sep 12, 2025

Walkthrough

Documentation updates, new MCP CLI command and server bootstrap, type-hint standardization, improved Claude log watcher with thread-based loop and stats, TUI enhancements (agent details, repo/org persistence), telemetry timestamp changes to UTC, minor import/format cleanups, tests adjusted for typing, and small API tweaks in git repo operator and schemas.

Changes

Cohort / File(s) Summary of changes
Docs updates
QUICK_START_LOGGING.md, docs/docs.json, docs/settings/team-roles.mdx
Logging examples inlined; navigation adds team-roles and agent-permissions; new Team Roles page with role matrix and guidance.
MCP CLI & server
pyproject.toml, src/codegen/cli/cli.py, src/codegen/cli/commands/mcp/__init__.py, src/codegen/cli/commands/mcp/main.py, src/codegen/cli/mcp_server/api_client.py, src/codegen/cli/mcp_server/tools/executor.py
Adds dependency mcp-python>=0.1.4; registers new codegen mcp Typer command; implements mcp options (transport/host/port) delegating to run_server; minor formatting in server modules.
Claude CLI/logging utilities
src/codegen/cli/commands/claude/...
Switch to builtin generics (dict/list) in types; adds ClaudeLogWatcher.start() with thread watch loop, error/backoff, stats; import/order/annotation tweaks; use logger.exception in error paths; whitespace tidy-ups.
Org/Repo selectors and env persistence
src/codegen/cli/commands/org/main.py, src/codegen/cli/commands/org/tui.py, src/codegen/cli/commands/repo/main.py, src/codegen/cli/commands/repo/tui.py, src/codegen/cli/commands/org/__init__.py, src/codegen/cli/commands/repo/__init__.py
Better .env update: preserve existing vars while setting CODEGEN_ORG_ID/REPO_ID; text/formatting adjustments; simplified imports; TUI close behavior refined; minor messages normalized.
TUI enhancements
src/codegen/cli/tui/agent_detail.py, src/codegen/cli/tui/app.py, src/codegen/cli/tui/codegen_theme.tcss
Agent detail: improved API error handling, PR branches display, git operations via git_cli (create/fetch/checkout); constructors use dict[...] typing; multiple logger.exception usages; stylesheet whitespace cleanup.
Telemetry
src/codegen/cli/telemetry/debug_exporter.py, src/codegen/cli/telemetry/otel_setup.py, src/codegen/cli/telemetry/exception_logger.py, src/codegen/cli/commands/config/telemetry.py, src/codegen/cli/telemetry/consent.py
Timestamps now UTC; shutdown uses local alias with assertion; import cleanups; unused imports removed.
CLI utils typing and cleanup
src/codegen/cli/utils/repo.py, src/codegen/cli/utils/org.py, src/codegen/cli/utils/inplace_print.py
Public API annotations moved to builtin generics; minor file I/O normalizations; removed unused import; Iterable moved to collections.abc.
Git operations and language detection
src/codegen/git/repo_operator/repo_operator.py, src/codegen/git/schemas/repo_config.py, src/codegen/git/utils/language.py, src/codegen/git/utils/pr_review.py
API tweaks: get_file -> str
Shared logging
src/codegen/shared/logging/get_logger.py
Adjusted import order inside telemetry config getter.
Tests
tests/unit/codegen/agents/test_agent.py, tests/unit/codegen/agents/test_usage_demo.py, tests/unit/codegen/test_top_level_imports.py
Type-ignore for missing-argument on Agent(); verify Agent alias identity; removed unused import; standardized strings.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant CLI as codegen (Typer)
  participant CMD as mcp.main.mcp
  participant SVR as run_server
  U->>CLI: codegen mcp --transport ... --host ... --port ...
  CLI->>CMD: Invoke command with options
  CMD->>SVR: run_server(transport, host, port)
  alt transport==stdio
    SVR-->>U: Start MCP server over stdio
  else transport==http
    SVR-->>U: Start MCP server on http://host:port
  end
Loading
sequenceDiagram
  autonumber
  participant C as Caller
  participant W as ClaudeLogWatcher
  participant T as Watch Thread
  participant F as File
  participant API as send_claude_session_log
  C->>W: start()
  W->>T: spawn daemon _watch_loop()
  loop poll interval
    T->>F: read new lines
    alt read ok
      T->>T: validate + format
      opt on_log_entry callback
        T-->>C: on_log_entry(log_entry)
      end
      T->>API: send entry
      API-->>T: success/failure
    else read error
      T->>T: warn + backoff
    end
  end
  C->>W: stop()
  W-->>C: stats (counts, success_rate)
Loading
sequenceDiagram
  autonumber
  participant U as User
  participant UI as AgentDetailTUI
  participant G as git_cli
  U->>UI: Pull PR branch
  UI->>UI: Pre-check remotes
  alt no "codegen-pr" remote
    UI->>G: add remote codegen-pr
  end
  UI->>G: fetch codegen-pr
  alt branch not local
    UI->>G: create from remote
  else exists
    UI->>G: checkout existing
  end
  UI-->>U: Status message
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The PR includes the repository's template headings (Motivation, Content, Testing) but those template sections are left empty while other free-form sections later provide details; the required template fields are therefore incomplete. The Testing section contains no concrete test steps or CI status and the checklist items remain unchecked, so the description does not satisfy the repository's template requirements. Because required template information is missing or incomplete, the description check fails. Please populate the template fields: add a clear "Motivation" explaining why these changes are needed, fill "Content" with a concise summary of the main changes (call out high-impact items like the new MCP CLI command, docs/settings/team-roles.mdx, pyproject dependency, and any public API signature changes), and complete "Testing" with how the changes were validated (unit/CI results, manual test steps, and any added tests). Update the checklist to reflect added tests or document why tests are not applicable, and consider splitting or clarifying the PR if it covers multiple distinct concerns so reviewers can focus more easily.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Codegen bot/add team roles documentation 1757612602" explicitly names the added team-roles documentation (docs/settings/team-roles.mdx), which is a real and prominent change in the diff, so it is specific and not generic or misleading. It does include noisy auto-generated elements ("Codegen bot/" prefix and numeric suffix) that could be trimmed for readability, but those do not make the title incorrect. Overall, the title is related and sufficiently descriptive of a key change in this PR.
Docstring Coverage ✅ Passed Docstring coverage is 94.23% which is sufficient. The required threshold is 80.00%.

Poem

A bunny taps the keys—thump-thump!—so spry,
Spinning up MCP with a carrot-high-five.
Logs now hop in threads, with traces that fly,
UTC moon clocks keep the sessions alive.
Repos and orgs nest snug in .env burrows—
Ship it, and watch the green meadows! 🥕🐇

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @Zeeeepa, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the Codegen CLI by introducing detailed documentation for team member roles, clarifying permissions and management. It also integrates a new mcp command, backed by a new dependency and a refactored internal structure, to manage the MCP server. Alongside these functional additions, the PR includes substantial code quality improvements, such as modernizing Python type hints, enhancing error logging with more comprehensive stack traces, and refining the user experience in the Text User Interface (TUI) for various commands.

Highlights

  • Team Roles Documentation: Introduced comprehensive documentation for team member roles (ADMIN, MANAGER, MEMBER), detailing their hierarchical permissions, management processes, and best practices within the Codegen organization.
  • New MCP CLI Command: Added a new mcp command to the Codegen CLI, along with a new mcp-python dependency, to facilitate starting the Codegen MCP server. Related files were refactored into a dedicated mcp_server directory.
  • Code Modernization and Robustness: Updated Python type hints from Dict[str, Any] to dict[str, Any] across multiple files for modern syntax. Implemented fallback mechanisms for SDK imports in various utilities to improve robustness when SDK modules are not available.
  • Logging and Telemetry Enhancements: Improved error logging by switching from logger.error to logger.exception in several TUI components, providing more detailed stack traces. Session logging now uses UTC timestamps for consistency.
  • TUI and Git Operation Improvements: Refined the Text User Interface (TUI) for organization and repository selection, and agent run details. Git operations within the TUI were updated to use git_cli directly for better control when pulling branches.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Potential Bug

The create_pr_comment method now returns None when PR is not found, but the return type annotation still suggests it always returns an IssueComment. This could lead to unexpected behavior if callers don't handle the None case.

def create_pr_comment(self, pr_number: int, body: str) -> IssueComment | None:
    """Create a general comment on a pull request.

    Args:
        pr_number (int): The PR number to comment on
        body (str): The comment text
    """
    pr = self.remote_git_repo.get_pull_safe(pr_number)
    if pr:
        comment = self.remote_git_repo.create_issue_comment(pr, body)
        return comment
    return None
Notification Format

The notification message uses a string formatting placeholder {repo_id} but the variable is not being interpolated in the f-string, which would display the literal {repo_id} text instead of the actual repository ID.

self.notify("i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")

Copy link

PR Code Suggestions ✨

No code suggestions found for the PR.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/codegen/cli/commands/mcp/main.py:7` </location>
<code_context>
+from codegen.cli.mcp_server.runner import run_server
+
+
+def mcp(
+    transport: str = typer.Option("stdio", help="Transport type (stdio, http)"),
+    host: str = typer.Option("localhost", help="Host to bind to (for http transport)"),
+    port: int = typer.Option(8000, help="Port to bind to (for http transport)"),
+):
+    """Start the Codegen MCP server."""
+    run_server(transport=transport, host=host, port=port)
</code_context>

<issue_to_address>
Introduced new MCP command entrypoint.

Please verify that error handling and user feedback in this command match the standards set by other CLI commands.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +7 to +13
def mcp(
transport: str = typer.Option("stdio", help="Transport type (stdio, http)"),
host: str = typer.Option("localhost", help="Host to bind to (for http transport)"),
port: int = typer.Option(8000, help="Port to bind to (for http transport)"),
):
"""Start the Codegen MCP server."""
run_server(transport=transport, host=host, port=port)
Copy link

Choose a reason for hiding this comment

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

suggestion: Introduced new MCP command entrypoint.

Please verify that error handling and user feedback in this command match the standards set by other CLI commands.


except Exception as e:
console.print(f"[red]Error:[/red] Failed to clear repository configuration: {e}")
raise typer.Exit(1)
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Explicitly raise from a previous error (raise-from-previous-error)

Suggested change
raise typer.Exit(1)
raise typer.Exit(1) from e


def _run_repo_selector_tui() -> None:
"""Launch the repository selector TUI."""
try:
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): Explicitly raise from a previous error [×2] (raise-from-previous-error)


def _update_info_with_detailed_data(self) -> None:
"""Update the info table with detailed data from the API."""
if not self.agent_data:
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): We've found these issues:

Comment on lines 134 to +136
for var_name, value in env_status.items():
info.append({
"label": f"{var_name}",
"value": value,
"status": "active" if value != "Not set" else "inactive"
})

info.append({"label": f"{var_name}", "value": value, "status": "active" if value != "Not set" else "inactive"})

Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Replace a for append loop with list extend (for-append-to-extend)

Suggested change
for var_name, value in env_status.items():
info.append({
"label": f"{var_name}",
"value": value,
"status": "active" if value != "Not set" else "inactive"
})
info.append({"label": f"{var_name}", "value": value, "status": "active" if value != "Not set" else "inactive"})
info.extend(
{
"label": f"{var_name}",
"value": value,
"status": "active" if value != "Not set" else "inactive",
}
for var_name, value in env_status.items()
)

def ensure_repositories_cached(org_id: int | None = None) -> list[dict[str, Any]]:
"""Ensure repositories are cached for the given organization.
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): Use named expression to simplify assignment and conditional [×2] (use-named-expression)

return _telemetry_config

_telemetry_config_checked = True

Copy link

Choose a reason for hiding this comment

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

issue (code-quality): We've found these issues:

Copy link

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

User Message Bug

Notifications show a placeholder instead of the actual repository ID because the string with {repo_id} is not an f-string; the value won’t interpolate. Consider using an f-string or format to display the real ID.

self.notify(f"✓ Set repository: {repo_name} (ID: {repo_id})")
self.notify("i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
User Message Bug

Notifications show a placeholder instead of the actual organization ID because the string with {org_id} is not an f-string; the value won’t interpolate. Consider using an f-string or format to display the real ID.

self.notify(f"✓ Set organization: {org_name} (ID: {org_id})")
self.notify("i  Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
User Message Bug

Console output includes {repo_id} literally instead of the actual value; the string isn’t formatted as an f-string. Update to format the ID into the message.

console.print(f"[green]✓[/green] Set repository ID to: [cyan]{repo_id}[/cyan]")
console.print("[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new mcp command, adds documentation for team roles, and implements a wide range of refactorings and improvements across the CLI and TUI. Key enhancements include unifying environment file handling, adopting modern Python type hints, making imports more robust with fallbacks, standardizing on UTC timestamps for telemetry, and improving exception logging. The changes are generally positive, improving code quality and robustness. My review focuses on correcting some documentation formatting, fixing a potentially broken link, and suggesting improvements to exception handling and user interface consistency.

Comment on lines 5 to +7
1. **Import the logger**: `from codegen.shared.logging.get_logger import get_logger`
2. **Add `extra={}` to your log calls**: `logger.info("message", extra={"key": "value"})`
3. **Enable telemetry**: `codegen config telemetry enable`
1. **Add `extra={}` to your log calls**: `logger.info("message", extra={"key": "value"})`
1. **Enable telemetry**: `codegen config telemetry enable`

Choose a reason for hiding this comment

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

medium

The numbered list for the "3 Step Process" is incorrect. All items are numbered as 1.. For a correctly rendered ordered list, they should be numbered sequentially (1., 2., 3.).

Suggested change
1. **Import the logger**: `from codegen.shared.logging.get_logger import get_logger`
2. **Add `extra={}` to your log calls**: `logger.info("message", extra={"key": "value"})`
3. **Enable telemetry**: `codegen config telemetry enable`
1. **Add `extra={}` to your log calls**: `logger.info("message", extra={"key": "value"})`
1. **Enable telemetry**: `codegen config telemetry enable`
1. **Import the logger**: `from codegen.shared.logging.get_logger import get_logger`
2. **Add `extra={}` to your log calls**: `logger.info("message", extra={"key": "value"})`
3. **Enable telemetry**: `codegen config telemetry enable`

Comment on lines 58 to +62
# At start of function
logger.info("Operation started", extra={
"operation": "command.subcommand",
"user_input": relevant_input
})

# At end of function
logger.info("Operation completed", extra={
"operation": "command.subcommand",
"success": True
})
logger.info("Operation started", extra={"operation": "command.subcommand", "user_input": relevant_input})

# At end of function
logger.info("Operation completed", extra={"operation": "command.subcommand", "success": True})

Choose a reason for hiding this comment

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

medium

The logger calls in this example have been condensed to a single line. For calls with multiple parameters in the extra dictionary, the previous multi-line format was more readable and is used in other examples within this same file (e.g., lines 25-32). For consistency and improved readability, consider reverting to the multi-line format for these examples.

Suggested change
# At start of function
logger.info("Operation started", extra={
"operation": "command.subcommand",
"user_input": relevant_input
})
# At end of function
logger.info("Operation completed", extra={
"operation": "command.subcommand",
"success": True
})
logger.info("Operation started", extra={"operation": "command.subcommand", "user_input": relevant_input})
# At end of function
logger.info("Operation completed", extra={"operation": "command.subcommand", "success": True})
# At start of function
logger.info("Operation started", extra={
"operation": "command.subcommand",
"user_input": relevant_input
})
# At end of function
logger.info("Operation completed", extra={
"operation": "command.subcommand",
"success": True
})

Comment on lines 190 to +193
1. **Run the command**: Execute your enhanced CLI command
2. **Check telemetry status**: `codegen config telemetry status`
3. **Look for logs in Grafana Cloud**: Search for your operation names
4. **Test with telemetry disabled**: `codegen config telemetry disable` - should still work normally
1. **Check telemetry status**: `codegen config telemetry status`
1. **Look for logs in Grafana Cloud**: Search for your operation names
1. **Test with telemetry disabled**: `codegen config telemetry disable` - should still work normally

Choose a reason for hiding this comment

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

medium

The numbered list under the "Verification" section is incorrect. All items are numbered as 1., which will not render as a sequential list.

Suggested change
1. **Run the command**: Execute your enhanced CLI command
2. **Check telemetry status**: `codegen config telemetry status`
3. **Look for logs in Grafana Cloud**: Search for your operation names
4. **Test with telemetry disabled**: `codegen config telemetry disable` - should still work normally
1. **Check telemetry status**: `codegen config telemetry status`
1. **Look for logs in Grafana Cloud**: Search for your operation names
1. **Test with telemetry disabled**: `codegen config telemetry disable` - should still work normally
1. **Run the command**: Execute your enhanced CLI command
2. **Check telemetry status**: `codegen config telemetry status`
3. **Look for logs in Grafana Cloud**: Search for your operation names
4. **Test with telemetry disabled**: `codegen config telemetry disable` - should still work normally

## Related Documentation

- [Agent Permissions](/settings/agent-permissions) - Configure what actions agents can perform
- [Organization Rules](/settings/organization-rules) - Set organization-wide rules

Choose a reason for hiding this comment

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

medium

The link to [Organization Rules](/settings/organization-rules) appears to be broken. The docs/docs.json file does not list an organization-rules page under settings, but it does list repo-rules. Please verify the correct link target.

- [Repository Rules](/settings/repo-rules) - Configure repository-specific behavior

else:
console.print(f"[green]✓[/green] Set repository ID to: [cyan]{repo_id}[/cyan]")
console.print("[yellow][/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
console.print("[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")

Choose a reason for hiding this comment

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

medium

The informational icon has been replaced with a lowercase i. While this change is consistent across the pull request, the standard Unicode info icon () is more universally recognized and provides better visual clarity for users. Consider reverting to the standard icon to improve the user experience.

Suggested change
console.print("[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
console.print("[yellow][/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")

Comment on lines 234 to 238
try:
current_repo.add_remote(remote_name, repo_clone_url)
git_cli.create_remote(remote_name, repo_clone_url)
except Exception:
# Remote might already exist
pass

Choose a reason for hiding this comment

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

medium

Catching a broad Exception can hide underlying issues and make debugging more difficult. It's better to catch a more specific exception or check for the condition preemptively. In this case, you can check if the remote already exists before attempting to create it.

            if remote_name not in [remote.name for remote in git_cli.remotes]:
                git_cli.create_remote(remote_name, repo_clone_url)

Copy link

@korbit-ai korbit-ai bot left a comment

Choose a reason for hiding this comment

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

Review by Korbit AI

Korbit automatically attempts to detect when you fix issues in new commits.
Category Issue Status
Documentation Vague ADMIN role assignment criteria ▹ view
Error Handling Silent ImportError handling ▹ view
Readability Duplicate Integration Management Permission ▹ view
Functionality Ambiguous Organization Settings Access ▹ view
Design Interface Segregation Violation in Server Configuration ▹ view
Documentation Unclear module docstring ▹ view
Documentation Missing parameter impact documentation ▹ view
Security Unrestricted Host Binding ▹ view
Functionality Missing Transport Type Validation ▹ view
Functionality Missing Port Range Validation ▹ view
Files scanned

Due to the exceptionally large size of this PR, I've limited my review to the following files:

File Path Reviewed
src/codegen/cli/commands/mcp/init.py
src/codegen/cli/commands/claude/init.py
src/codegen/cli/commands/org/init.py
src/codegen/cli/commands/repo/init.py
src/codegen/cli/commands/mcp/main.py
src/codegen/cli/commands/claude/quiet_console.py
src/codegen/cli/utils/inplace_print.py
src/codegen/cli/mcp_server/tools/executor.py
src/codegen/cli/mcp_server/api_client.py
src/codegen/git/schemas/repo_config.py
src/codegen/cli/telemetry/consent.py
src/codegen/cli/commands/claude/claude_log_utils.py
src/codegen/shared/logging/get_logger.py
src/codegen/cli/utils/org.py
src/codegen/cli/cli.py
src/codegen/cli/commands/org/main.py
src/codegen/git/utils/pr_review.py
src/codegen/cli/telemetry/debug_exporter.py
src/codegen/cli/telemetry/exception_logger.py
docs/settings/team-roles.mdx
src/codegen/cli/commands/claude/claude_session_api.py
src/codegen/cli/commands/repo/main.py
src/codegen/git/utils/language.py
src/codegen/cli/telemetry/otel_setup.py
src/codegen/cli/utils/repo.py
src/codegen/cli/commands/claude/claude_log_watcher.py
src/codegen/cli/commands/claude/main.py
src/codegen/cli/tui/agent_detail.py
src/codegen/cli/commands/org/tui.py
src/codegen/cli/commands/repo/tui.py
src/codegen/git/repo_operator/repo_operator.py
src/codegen/cli/tui/app.py

Explore our documentation to understand the languages and file types we support and the files we ignore.

Check out our docs on how you can make Korbit work best for you and your team.

Loving Korbit!? Share us on LinkedIn Reddit and X

Comment on lines +98 to +99
- **MANAGER**: Team leads, project managers, or senior developers who need to manage integrations
- **ADMIN**: Organization owners, DevOps engineers, or senior leadership who need full control
Copy link

Choose a reason for hiding this comment

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

Vague ADMIN role assignment criteria category Documentation

Tell me more
What is the issue?

The Role Assignment Guidelines lack specifics about when to grant ADMIN access, which could lead to overprivileged accounts.

Why this matters

Overly broad ADMIN role assignments increase security risks and complicate access management.

Suggested change ∙ Feature Preview
  • MANAGER: Team leads, project managers, or senior developers who need to manage integrations
  • ADMIN: Organization owners or designated security leads - limit to 2-3 trusted individuals per organization
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

Comment on lines +132 to +136
try:
from codegen.sdk.core.file import SourceFile
except ImportError:
# If SDK is not available, return empty list
return []
Copy link

Choose a reason for hiding this comment

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

Silent ImportError handling category Error Handling

Tell me more
What is the issue?

The ImportError catch block silently returns an empty list without logging the error or providing context about the missing SDK dependency.

Why this matters

Silent failure masks the root cause of missing dependencies, making it harder to diagnose why the modified_symbols property is returning empty results.

Suggested change ∙ Feature Preview
try:
    from codegen.sdk.core.file import SourceFile
except ImportError as e:
    logging.warning(f"SDK dependency not available, modified_symbols will return empty list: {e}")
    return []
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

Comment on lines +33 to +34
- **Manage integrations** (GitHub, Linear, Slack, etc.)
- **View and manage organization integrations**
Copy link

Choose a reason for hiding this comment

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

Duplicate Integration Management Permission category Readability

Tell me more
What is the issue?

Redundant permission listed for Manager role. 'Manage integrations' and 'View and manage organization integrations' describe the same functionality.

Why this matters

Listing the same permission twice in different words can cause confusion about whether these are distinct capabilities, potentially leading to misunderstandings about the role's actual permissions.

Suggested change ∙ Feature Preview

Remove one of the redundant entries. Keep only:

- **Manage integrations** (GitHub, Linear, Slack, etc.)
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

| Delete repositories ||||
| Access billing ||||
| Change user roles ||||
| Organization settings | Limited | Limited | Full |
Copy link

Choose a reason for hiding this comment

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

Ambiguous Organization Settings Access category Functionality

Tell me more
What is the issue?

The permission matrix shows 'Limited' access for both Member and Manager roles without specifying what 'Limited' means.

Why this matters

Without clear definition of 'Limited' access, users won't understand what organization settings they can actually access, potentially leading to confusion or access-related issues.

Suggested change ∙ Feature Preview

Either define what 'Limited' means or be specific about the exact permissions in the matrix:

| Organization settings | View Only | View & Edit Basic | Full |
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

Comment on lines +7 to +11
def mcp(
transport: str = typer.Option("stdio", help="Transport type (stdio, http)"),
host: str = typer.Option("localhost", help="Host to bind to (for http transport)"),
port: int = typer.Option(8000, help="Port to bind to (for http transport)"),
):
Copy link

Choose a reason for hiding this comment

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

Interface Segregation Violation in Server Configuration category Design

Tell me more
What is the issue?

The MCP command function combines transport options for different server types (stdio and http) into a single interface, violating the Interface Segregation Principle.

Why this matters

This design forces clients using stdio transport to deal with irrelevant http-specific parameters (host, port), making the interface less maintainable and more prone to misuse.

Suggested change ∙ Feature Preview

Split the command into separate interfaces for different transport types:

def mcp_stdio():
    run_server(transport="stdio")

def mcp_http(
    host: str = typer.Option("localhost", help="Host to bind to"),
    port: int = typer.Option(8000, help="Port to bind to")
):
    run_server(transport="http", host=host, port=port)
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

@@ -0,0 +1,13 @@
"""MCP command implementation."""
Copy link

Choose a reason for hiding this comment

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

Unclear module docstring category Documentation

Tell me more
What is the issue?

The module docstring is too vague and doesn't explain what MCP means or its purpose.

Why this matters

Without understanding what MCP means and does, developers will struggle to maintain or use this module effectively.

Suggested change ∙ Feature Preview

"""Module containing the MCP (Master Control Program) server command implementation.

This module provides the CLI interface for starting and configuring the Codegen MCP server,
which handles code generation coordination and communication."""

Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

host: str = typer.Option("localhost", help="Host to bind to (for http transport)"),
port: int = typer.Option(8000, help="Port to bind to (for http transport)"),
):
"""Start the Codegen MCP server."""
Copy link

Choose a reason for hiding this comment

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

Missing parameter impact documentation category Documentation

Tell me more
What is the issue?

The function docstring doesn't describe the configuration options or their impact.

Why this matters

Users won't understand how different transport options affect server behavior without reading the code.

Suggested change ∙ Feature Preview

"""Start the Codegen MCP server with the specified transport configuration.

The server can run using either stdio for direct process communication
or HTTP for network-based communication."""

Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.


def mcp(
transport: str = typer.Option("stdio", help="Transport type (stdio, http)"),
host: str = typer.Option("localhost", help="Host to bind to (for http transport)"),
Copy link

Choose a reason for hiding this comment

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

Unrestricted Host Binding category Security

Tell me more
What is the issue?

Default host binding to localhost without input validation could allow unintended network exposure if changed to '0.0.0.0' or other insecure values.

Why this matters

Without validation, binding to unsafe host values could expose the server to unauthorized network access from external sources.

Suggested change ∙ Feature Preview

Add input validation to restrict host values to safe options:

def validate_host(value: str) -> str:
    allowed_hosts = ['localhost', '127.0.0.1']
    if value not in allowed_hosts:
        raise typer.BadParameter(f'Host must be one of: {allowed_hosts}')
    return value

host: str = typer.Option(
    "localhost",
    help="Host to bind to (for http transport)",
    callback=validate_host
)
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.



def mcp(
transport: str = typer.Option("stdio", help="Transport type (stdio, http)"),
Copy link

Choose a reason for hiding this comment

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

Missing Transport Type Validation category Functionality

Tell me more
What is the issue?

The transport parameter lacks input validation to ensure only valid transport types ('stdio' or 'http') are accepted.

Why this matters

Invalid transport types could cause unexpected behavior or crashes when passed to run_server().

Suggested change ∙ Feature Preview

Add validation for transport parameter using a callback function in typer:

def validate_transport(value: str) -> str:
    if value not in ["stdio", "http"]:
        raise typer.BadParameter("Transport must be either 'stdio' or 'http'")
    return value

def mcp(
    transport: str = typer.Option(
        "stdio",
        help="Transport type (stdio, http)",
        callback=validate_transport
    ),
    # ... rest of the parameters
):
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

def mcp(
transport: str = typer.Option("stdio", help="Transport type (stdio, http)"),
host: str = typer.Option("localhost", help="Host to bind to (for http transport)"),
port: int = typer.Option(8000, help="Port to bind to (for http transport)"),
Copy link

Choose a reason for hiding this comment

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

Missing Port Range Validation category Functionality

Tell me more
What is the issue?

The port parameter lacks validation for a valid port range (typically 1-65535).

Why this matters

Invalid port numbers could cause network binding failures or security issues.

Suggested change ∙ Feature Preview

Add validation for port parameter using a callback function:

def validate_port(value: int) -> int:
    if not (1 <= value <= 65535):
        raise typer.BadParameter("Port must be between 1 and 65535")
    return value

def mcp(
    # ... other parameters
    port: int = typer.Option(
        8000,
        help="Port to bind to (for http transport)",
        callback=validate_port
    ),
):
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Guard missing MCP server import

Import the server lazily and guard against missing implementation to prevent the
CLI from crashing when runner.run_server is absent. Provide a clear error
message and non-zero exit so users know how to proceed.

src/codegen/cli/commands/mcp/main.py [1-13]

 """MCP command implementation."""
 
 import typer
-from codegen.cli.mcp_server.runner import run_server
 
 
 def mcp(
     transport: str = typer.Option("stdio", help="Transport type (stdio, http)"),
     host: str = typer.Option("localhost", help="Host to bind to (for http transport)"),
     port: int = typer.Option(8000, help="Port to bind to (for http transport)"),
 ):
     """Start the Codegen MCP server."""
+    try:
+        from codegen.cli.mcp_server import runner as _runner
+        run_server = getattr(_runner, "run_server")
+    except Exception as e:
+        typer.echo(f"Error: MCP server is not available ({e})")
+        raise typer.Exit(1)
+
     run_server(transport=transport, host=host, port=port)
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly proposes to lazily import the run_server function and wrap it in a try-except block, which improves the CLI's robustness against missing optional components.

Low
General
Fix missing f-string formatting

The message prints the literal {repo_id} instead of the actual value. Use an
f-string to include the repository ID in the output.

src/codegen/cli/commands/repo/main.py [117]

-console.print("[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
+console.print(f"[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies a bug where a user-facing message would print a literal {repo_id} instead of its value, and the proposed fix of using an f-string is accurate.

Low
Correct repo ID interpolation

These notifications show {repo_id} literally. Convert them to f-strings so the
selected repository ID is shown to the user.

src/codegen/cli/commands/repo/tui.py [102-245]

-self.notify("i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
+self.notify(f"i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
 ...
-self.notify("i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
+self.notify(f"i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies a bug in two separate TUI notifications where {repo_id} would be displayed literally, and the proposed fix of using f-strings is correct.

Low
Interpolate organization ID correctly

The notifications print the placeholder {org_id} instead of the actual ID. Use
f-strings so users see the resolved organization ID.

src/codegen/cli/commands/org/tui.py [112-268]

-self.notify("i  Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
+self.notify(f"i  Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
 ...
-self.notify("i  Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
+self.notify(f"i  Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies a bug in two separate TUI notifications where {org_id} would be displayed literally, and the proposed fix of using f-strings is correct.

Low
  • More

Copy link

@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: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/codegen/git/repo_operator/repo_operator.py (1)

569-584: Skip unreadable files in iter_files and use logging — don’t yield None

get_file returns str | None but iter_files is annotated Generator[tuple[str, str]] and yields content unfiltered; callers can receive None and crash.

  • In src/codegen/git/repo_operator/repo_operator.py, inside iter_files before yielding:
content = self.get_file(filepath)
if content is None:
    logger.warning(f"Skipping unreadable/undecodable file: {filepath}")
    continue
yield rel_filepath, content
  • Replace the print in get_file with structured logging:
-                print(f"Warning: Unable to decode file {file_path}. Skipping.")
+                logger.warning(f"Unable to decode file {file_path}. Skipping.")

Locations: get_file (≈ lines 569–584), iter_files (≈ lines 635–671).

src/codegen/cli/tui/app.py (1)

170-188: Add timeouts to API calls in recent-runs loader (prevent TUI hangs).

These requests.get calls run in the UI’s background loop; without timeouts the TUI can stall on slow networks.

-            user_response = requests.get(f"{API_ENDPOINT.rstrip('/')}/v1/users/me", headers=headers)
+            user_response = requests.get(f"{API_ENDPOINT.rstrip('/')}/v1/users/me", headers=headers, timeout=10)
...
-            response = requests.get(url, headers=headers, params=params)
+            response = requests.get(url, headers=headers, params=params, timeout=10)

Also applies to: 185-188

src/codegen/cli/commands/claude/main.py (1)

76-79: Add a timeout to the background run API call

This external POST can hang indefinitely without a timeout.

Apply:

-        response = requests.post(url, headers=headers, json=payload)
+        response = requests.post(url, headers=headers, json=payload, timeout=30)
🧹 Nitpick comments (31)
tests/unit/codegen/agents/test_usage_demo.py (1)

42-42: Align ignore code with mypy or make it tool-agnostic

Use call-arg for mypy or plain type: ignore if you want cross-checker compatibility.

-        Agent()  # type: ignore[missing-argument] # No token provided
+        Agent()  # type: ignore[call-arg]  # No token provided
tests/unit/codegen/test_top_level_imports.py (2)

37-42: Replace constant getattr calls with direct attribute access (Ruff B009)

Direct access is clearer and satisfies the linter.

-        assert hasattr(Agent, "run")
-        assert hasattr(Agent, "get_status")
-        assert callable(getattr(Agent, "run"))
-        assert callable(getattr(Agent, "get_status"))
+        assert hasattr(Agent, "run")
+        assert hasattr(Agent, "get_status")
+        assert callable(Agent.run)
+        assert callable(Agent.get_status)

46-47: Trim redundant hasattr before attribute assertion

You already assert the value on the next line; the hasattr is redundant.

-        assert hasattr(agent, "token")
         assert agent.token is None
pyproject.toml (2)

28-28: Constrain mcp-python to a minor range to avoid unexpected breaks.
Pre-1.0 packages can introduce breaking changes on minor bumps. Suggest adding an upper bound.

Apply:

-  "mcp-python>=0.1.4",
+  "mcp-python>=0.1.4,<0.2.0",

28-28: Optionally make MCP deps extra-installable.
If the MCP CLI is optional for most users, consider moving mcp-python (and any MCP-only deps) to an extra (e.g., [project.optional-dependencies].mcp) to reduce base footprint.

Happy to draft the extra + guards in CLI wiring if you’d like.

src/codegen/cli/commands/mcp/__init__.py (1)

1-1: Add explicit export for consistency with org/repo modules.
Keeps public surface predictable for importers.

Apply:

 """MCP command module."""
+from .main import mcp
+
+__all__ = ["mcp"]
src/codegen/git/utils/pr_review.py (1)

132-136: Good: graceful fallback when SDK is missing; add a one-time debug log.
Helps diagnose why modified_symbols is empty without spamming stdout.

Apply:

-        except ImportError:
-            # If SDK is not available, return empty list
-            return []
+        except ImportError:
+            # If SDK is not available, return empty list
+            import logging
+            logging.getLogger(__name__).debug("codegen.sdk not available; modified_symbols=[]")
+            return []
src/codegen/cli/mcp_server/api_client.py (1)

36-38: Normalize base URL regardless of source.
Trim trailing slashes for both env and default to avoid accidental double slashes.

Apply:

-        base_url = os.getenv("CODEGEN_API_BASE_URL", API_ENDPOINT.rstrip("/"))
+        base_url = (os.getenv("CODEGEN_API_BASE_URL") or API_ENDPOINT).rstrip("/")
src/codegen/cli/commands/claude/config/claude_session_active_hook.py (1)

22-22: Fix incorrect type annotation for fallback symbol

Annotate as an optional callable; current : None makes the symbol non-callable for type checkers.

-except ImportError:
-    update_claude_session_status: None = None
+except ImportError:
+    update_claude_session_status: Callable[[str, str, int | None], bool] | None = None

Add import near the top:

from collections.abc import Callable
src/codegen/cli/telemetry/otel_setup.py (1)

296-302: Minor: simplify shutdown guard and ensure reset in finally

The local alias is fine; the assert is redundant. Consider a guard plus finally to always clear the global.

-        try:
-            # Type checker workaround: assert that provider is not None after the check
-            provider = _logger_provider
-            assert provider is not None
-            provider.shutdown()
-        except Exception:
-            pass  # Ignore shutdown errors
-        _logger_provider = None
+        try:
+            provider = _logger_provider
+            if provider is not None:
+                provider.shutdown()
+        except Exception:
+            pass  # Ignore shutdown errors
+        finally:
+            _logger_provider = None
src/codegen/cli/commands/claude/config/claude_session_stop_hook.py (1)

22-22: Type the ImportError fallback as Optional[Callable], not None

Annotating the symbol with None defeats static checking. Use an Optional[Callable] matching the real signature.

Apply within this hunk:

-except ImportError:
-    update_claude_session_status: None = None
+except ImportError:
+    update_claude_session_status: Optional[Callable[[str, str, Optional[int]], bool]] = None

Add this import near the top:

from typing import Callable, Optional
src/codegen/cli/commands/mcp/main.py (1)

8-11: Constrain transport to allowed values; clarify http fallback

Validate at the CLI boundary to prevent typos, and make the http fallback explicit in help.

-from codegen.cli.mcp_server.runner import run_server
+from codegen.cli.mcp_server.runner import run_server
+from typing import Literal
@@
-def mcp(
-    transport: str = typer.Option("stdio", help="Transport type (stdio, http)"),
-    host: str = typer.Option("localhost", help="Host to bind to (for http transport)"),
-    port: int = typer.Option(8000, help="Port to bind to (for http transport)"),
-):
+def mcp(
+    transport: Literal["stdio", "http"] = typer.Option("stdio", help="Transport type: 'stdio' (default) or 'http' (not yet implemented; falls back to stdio)."),
+    host: str = typer.Option("localhost", help="Host (http transport only)"),
+    port: int = typer.Option(8000, help="Port (http transport only)"),
+):

Optionally echo a one-line warning when transport=="http" before calling run_server(...).

src/codegen/cli/commands/org/tui.py (2)

152-153: Avoid blanket except Exception in file update

Catching all exceptions hides real errors (e.g., permission issues). Prefer narrowing to OSError and log the error.


273-305: DRY: duplicate .env update logic across two classes

Both classes implement nearly identical _update_env_file. Extract a shared helper (or reuse the one in org/main.py) to reduce divergence.

docs/settings/team-roles.mdx (1)

33-35: Minor duplication in Manager capabilities

“Manage integrations” appears twice (lines 33–34). Consider removing one.

src/codegen/cli/tui/app.py (2)

604-607: Use error level with explicit traceback for non-zero Typer exits (reduce noise).

logger.exception implies an unhandled crash; here it's a controlled failure path. Prefer logger.error(..., exc_info=True) to keep the traceback without elevating severity.

-                logger.exception(
+                logger.error(
                     "Local pull failed via typer exit",
                     extra={"operation": "tui.pull_branch", "agent_id": agent_id, "org_id": self.org_id, "duration_ms": duration_ms, "exit_code": e.exit_code, "success": False},
-                )
+                , exc_info=True)

611-614: Treat invalid user input as warning, not exception.

ValueError on agent_id is user error; logging a full traceback is unnecessary and noisy.

-            logger.exception(
+            logger.warning(
                 "Invalid agent ID for pull",
                 extra={"operation": "tui.pull_branch", "agent_id": agent_id, "org_id": getattr(self, "org_id", None), "duration_ms": duration_ms, "error_type": "invalid_agent_id"},
-            )
+            )
src/codegen/cli/commands/org/main.py (1)

129-129: Chain the original exception when exiting to aid diagnostics.

Adopt Ruff B904 guidance so the root cause isn’t lost in tooling/logs.

-        raise typer.Exit(1)
+        raise typer.Exit(1) from e
src/codegen/git/utils/language.py (5)

49-63: Solid SDK import fallback; normalize extensions to lowercase.

Prevents case-sensitivity mismatches on files like “.PY” or “.TSX”.

         EXTENSIONS = {
             ProgrammingLanguage.PYTHON: PyFile.get_extensions(),
             ProgrammingLanguage.TYPESCRIPT: TSFile.get_extensions(),
         }
+        # Normalize to lowercase for case-insensitive suffix checks
+        EXTENSIONS = {lang: {ext.lower() for ext in exts} for lang, exts in EXTENSIONS.items()}

And mirror the same normalization in the fallback block:

         EXTENSIONS = {
             ProgrammingLanguage.PYTHON: [".py", ".pyx", ".pyi"],
             ProgrammingLanguage.TYPESCRIPT: [".ts", ".tsx", ".js", ".jsx"],
         }
+        EXTENSIONS = {lang: {ext.lower() for ext in exts} for lang, exts in EXTENSIONS.items()}

86-89: Make the suffix comparison case-insensitive.

-            if file_path.suffix in exts:
+            if file_path.suffix.lower() in exts:
                 language_counts[language] += 1

120-135: Mirror lowercase-extension normalization in git strategy.

         EXTENSIONS = {
             ProgrammingLanguage.PYTHON: PyFile.get_extensions(),
             ProgrammingLanguage.TYPESCRIPT: TSFile.get_extensions(),
         }
+        EXTENSIONS = {lang: {ext.lower() for ext in exts} for lang, exts in EXTENSIONS.items()}

And in the fallback:

         EXTENSIONS = {
             ProgrammingLanguage.PYTHON: [".py", ".pyx", ".pyi"],
             ProgrammingLanguage.TYPESCRIPT: [".ts", ".tsx", ".js", ".jsx"],
         }
+        EXTENSIONS = {lang: {ext.lower() for ext in exts} for lang, exts in EXTENSIONS.items()}

163-165: Case-insensitive suffix match here as well.

-            if file_path.suffix in exts:
+            if file_path.suffix.lower() in exts:
                 language_counts[language] += 1

90-97: Docstring mismatch: function returns OTHER, not None.

Update the docstring to reflect actual behavior.

src/codegen/cli/utils/repo.py (1)

172-174: Narrow broad exception to network errors (keep mock fallback).

Prevents masking programming errors while preserving UX fallback.

-    except Exception:
+    except requests.RequestException:
         # If API fails, return mock data
         return get_mock_repositories()
src/codegen/cli/tui/agent_detail.py (3)

42-43: Remove unused variable.

summary is assigned but not used.

-        summary = self.agent_run.get("summary", "No summary available")

233-238: Avoid broad try/except when creating remote; check first.

Don’t swallow real errors; create remote only if missing.

-            try:
-                git_cli.create_remote(remote_name, repo_clone_url)
-            except Exception:
-                # Remote might already exist
-                pass
+            if remote_name not in [r.name for r in git_cli.remotes]:
+                git_cli.create_remote(remote_name, repo_clone_url)

241-247: Consider narrowing checkout exception handling.

Catching all Exceptions may hide unrelated errors; prefer GitPython’s GitCommandError if available.

src/codegen/cli/commands/claude/config/claude_session_hook.py (1)

23-24: Type the ImportError fallbacks as Optional[Callable]

Annotating with None-only types hinders static checking; prefer Optional[Callable].

Apply:

-    create_claude_session: None = None
-    resolve_org_id: None = None
+    create_claude_session: Optional[Callable[[str, Optional[int]], Optional[str]]] = None
+    resolve_org_id: Optional[Callable[[Optional[int]], Optional[int]]] = None

Also add at the top (near other imports):

from typing import Callable, Optional
src/codegen/cli/commands/claude/claude_log_watcher.py (3)

39-57: Use an Event to control thread shutdown

Replacing the boolean with threading.Event avoids races and spurious wake-ups.

Example patch:

-        self.is_running = True
-        self.watcher_thread = threading.Thread(target=self._watch_loop, daemon=True)
+        self._stop = threading.Event()
+        self.watcher_thread = threading.Thread(target=self._watch_loop, daemon=True)
         self.watcher_thread.start()

And in stop():

-        self.is_running = False
+        if hasattr(self, "_stop"):
+            self._stop.set()

And in _watch_loop():

-        while self.is_running:
+        while not getattr(self, "_stop", None) or not self._stop.is_set():
             try:
-                self._check_for_new_entries()
-                time.sleep(self.poll_interval)
+                self._check_for_new_entries()
+                # Wait with timeout so stop() is responsive
+                if self._stop.wait(self.poll_interval):
+                    break

119-133: Avoid O(n) re-reads for large logs

Reading all lines on every poll scales poorly; consider tracking a byte offset and using incremental reads.

If staying line-based, cache lines[start_line:end_line] without reading twice (you call read_existing_log_lines then readlines()).


171-175: Gate verbose per-entry prints behind a debug flag

Frequent prints can flood terminals; make this conditional on an env var or a verbosity flag.

Example:

-                console.print(f"📤 Sent log entry: {log_entry.get('type', 'unknown')}", style="dim")
+                if os.environ.get("CODEGEN_VERBOSE_LOGS") == "1":
+                    console.print(f"📤 Sent log entry: {log_entry.get('type', 'unknown')}", style="dim")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1b64892 and 0f44339.

📒 Files selected for processing (43)
  • QUICK_START_LOGGING.md (6 hunks)
  • docs/docs.json (1 hunks)
  • docs/settings/team-roles.mdx (1 hunks)
  • pyproject.toml (1 hunks)
  • src/codegen/cli/cli.py (2 hunks)
  • src/codegen/cli/commands/claude/__init__.py (0 hunks)
  • src/codegen/cli/commands/claude/claude_log_utils.py (4 hunks)
  • src/codegen/cli/commands/claude/claude_log_watcher.py (9 hunks)
  • src/codegen/cli/commands/claude/claude_session_api.py (1 hunks)
  • src/codegen/cli/commands/claude/config/claude_session_active_hook.py (1 hunks)
  • src/codegen/cli/commands/claude/config/claude_session_hook.py (2 hunks)
  • src/codegen/cli/commands/claude/config/claude_session_stop_hook.py (1 hunks)
  • src/codegen/cli/commands/claude/main.py (1 hunks)
  • src/codegen/cli/commands/claude/quiet_console.py (1 hunks)
  • src/codegen/cli/commands/config/telemetry.py (0 hunks)
  • src/codegen/cli/commands/mcp/__init__.py (1 hunks)
  • src/codegen/cli/commands/mcp/main.py (1 hunks)
  • src/codegen/cli/commands/org/__init__.py (1 hunks)
  • src/codegen/cli/commands/org/main.py (3 hunks)
  • src/codegen/cli/commands/org/tui.py (11 hunks)
  • src/codegen/cli/commands/repo/__init__.py (1 hunks)
  • src/codegen/cli/commands/repo/main.py (7 hunks)
  • src/codegen/cli/commands/repo/tui.py (8 hunks)
  • src/codegen/cli/mcp_server/api_client.py (1 hunks)
  • src/codegen/cli/mcp_server/tools/executor.py (0 hunks)
  • src/codegen/cli/telemetry/consent.py (0 hunks)
  • src/codegen/cli/telemetry/debug_exporter.py (4 hunks)
  • src/codegen/cli/telemetry/exception_logger.py (1 hunks)
  • src/codegen/cli/telemetry/otel_setup.py (1 hunks)
  • src/codegen/cli/tui/agent_detail.py (12 hunks)
  • src/codegen/cli/tui/app.py (4 hunks)
  • src/codegen/cli/tui/codegen_theme.tcss (2 hunks)
  • src/codegen/cli/utils/inplace_print.py (1 hunks)
  • src/codegen/cli/utils/org.py (1 hunks)
  • src/codegen/cli/utils/repo.py (6 hunks)
  • src/codegen/git/repo_operator/repo_operator.py (4 hunks)
  • src/codegen/git/schemas/repo_config.py (1 hunks)
  • src/codegen/git/utils/language.py (2 hunks)
  • src/codegen/git/utils/pr_review.py (1 hunks)
  • src/codegen/shared/logging/get_logger.py (1 hunks)
  • tests/unit/codegen/agents/test_agent.py (1 hunks)
  • tests/unit/codegen/agents/test_usage_demo.py (1 hunks)
  • tests/unit/codegen/test_top_level_imports.py (1 hunks)
💤 Files with no reviewable changes (4)
  • src/codegen/cli/commands/config/telemetry.py
  • src/codegen/cli/telemetry/consent.py
  • src/codegen/cli/mcp_server/tools/executor.py
  • src/codegen/cli/commands/claude/init.py
🧰 Additional context used
🧬 Code graph analysis (21)
tests/unit/codegen/agents/test_agent.py (1)
src/codegen/agents/agent.py (1)
  • Agent (46-100)
src/codegen/cli/commands/claude/config/claude_session_active_hook.py (1)
src/codegen/cli/commands/claude/claude_session_api.py (1)
  • update_claude_session_status (88-140)
src/codegen/shared/logging/get_logger.py (1)
src/codegen/configs/models/telemetry.py (1)
  • TelemetryConfig (6-29)
tests/unit/codegen/agents/test_usage_demo.py (1)
src/codegen/agents/agent.py (1)
  • Agent (46-100)
src/codegen/cli/commands/mcp/main.py (1)
src/codegen/cli/mcp_server/runner.py (1)
  • run_server (10-43)
src/codegen/git/utils/language.py (1)
src/codegen/shared/enums/programming_language.py (1)
  • ProgrammingLanguage (4-8)
src/codegen/cli/commands/repo/main.py (1)
src/codegen/cli/utils/repo.py (6)
  • clear_repo_env_variables (76-81)
  • ensure_repositories_cached (195-225)
  • get_current_repo_id (45-47)
  • get_repo_env_status (50-55)
  • set_repo_env_variable (58-73)
  • update_env_file_with_repo (84-117)
src/codegen/cli/telemetry/exception_logger.py (2)
src/codegen/cli/telemetry/otel_setup.py (2)
  • get_otel_logging_handler (262-276)
  • get_session_uuid (279-286)
src/codegen/shared/logging/get_logger.py (1)
  • get_logger (103-106)
src/codegen/cli/commands/claude/config/claude_session_hook.py (2)
src/codegen/cli/commands/claude/claude_session_api.py (1)
  • create_claude_session (27-85)
src/codegen/cli/utils/org.py (1)
  • resolve_org_id (22-116)
src/codegen/cli/commands/claude/config/claude_session_stop_hook.py (1)
src/codegen/cli/commands/claude/claude_session_api.py (1)
  • update_claude_session_status (88-140)
src/codegen/cli/telemetry/otel_setup.py (1)
src/codegen/cli/telemetry/debug_exporter.py (2)
  • shutdown (104-119)
  • shutdown (164-166)
src/codegen/cli/commands/org/main.py (2)
src/codegen/cli/commands/org/tui.py (2)
  • _update_env_file (117-153)
  • _update_env_file (273-309)
src/codegen/cli/commands/repo/tui.py (2)
  • _update_env_file (107-141)
  • _update_env_file (250-284)
src/codegen/git/schemas/repo_config.py (2)
src/codegen/configs/models/repository.py (1)
  • base_dir (28-29)
src/codegen/shared/enums/programming_language.py (1)
  • ProgrammingLanguage (4-8)
src/codegen/cli/utils/org.py (2)
src/codegen/cli/auth/token_manager.py (2)
  • get_cached_organizations (177-189)
  • get_cached_organizations (324-331)
src/codegen/cli/commands/org/main.py (1)
  • org (14-42)
src/codegen/cli/utils/repo.py (2)
src/codegen/cli/auth/token_manager.py (3)
  • get_current_token (263-301)
  • cache_repositories (386-403)
  • get_cached_repositories (373-383)
src/codegen/cli/utils/org.py (1)
  • resolve_org_id (22-116)
src/codegen/cli/commands/org/tui.py (3)
src/codegen/cli/utils/org.py (1)
  • resolve_org_id (22-116)
src/codegen/cli/commands/org/main.py (2)
  • org (14-42)
  • _update_env_file (89-119)
src/codegen/cli/commands/repo/tui.py (4)
  • _update_env_file (107-141)
  • _update_env_file (250-284)
  • _close_screen (143-148)
  • action_quit (150-152)
tests/unit/codegen/test_top_level_imports.py (1)
src/codegen/agents/agent.py (1)
  • Agent (46-100)
src/codegen/cli/cli.py (1)
src/codegen/cli/commands/mcp/main.py (1)
  • mcp (7-13)
src/codegen/cli/tui/agent_detail.py (3)
src/codegen/cli/utils/org.py (1)
  • resolve_org_id (22-116)
src/codegen/git/repo_operator/local_git_repo.py (1)
  • LocalGitRepo (15-84)
src/codegen/git/repo_operator/repo_operator.py (1)
  • create_remote (345-350)
src/codegen/cli/commands/claude/claude_log_watcher.py (2)
src/codegen/cli/commands/claude/claude_log_utils.py (5)
  • format_log_for_api (115-126)
  • get_claude_session_log_path (24-39)
  • parse_jsonl_line (42-58)
  • read_existing_log_lines (75-91)
  • validate_log_entry (94-112)
src/codegen/cli/commands/claude/claude_session_api.py (1)
  • send_claude_session_log (143-193)
src/codegen/cli/commands/repo/tui.py (3)
src/codegen/cli/utils/repo.py (2)
  • ensure_repositories_cached (195-225)
  • get_current_repo_id (45-47)
src/codegen/cli/commands/org/tui.py (2)
  • _update_env_file (117-153)
  • _update_env_file (273-309)
src/codegen/cli/commands/org/main.py (1)
  • _update_env_file (89-119)
🪛 Ruff (0.12.2)
src/codegen/cli/commands/repo/main.py

148-148: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


149-149: Do not catch blind exception: Exception

(BLE001)


151-151: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

src/codegen/cli/commands/org/main.py

129-129: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

src/codegen/cli/utils/repo.py

113-113: Consider moving this statement to an else block

(TRY300)


115-115: Do not catch blind exception: Exception

(BLE001)


163-163: Probable use of requests call without timeout

(S113)


172-172: Do not catch blind exception: Exception

(BLE001)

src/codegen/cli/commands/org/tui.py

150-150: Consider moving this statement to an else block

(TRY300)


306-306: Consider moving this statement to an else block

(TRY300)


308-308: Do not catch blind exception: Exception

(BLE001)

tests/unit/codegen/test_top_level_imports.py

40-40: Do not call getattr with a constant attribute value. It is not any safer than normal property access.

Replace getattr with attribute access

(B009)


41-41: Do not call getattr with a constant attribute value. It is not any safer than normal property access.

Replace getattr with attribute access

(B009)

src/codegen/cli/tui/agent_detail.py

42-42: Local variable summary is assigned to but never used

Remove assignment to unused variable summary

(F841)


128-128: Probable use of requests call without timeout

(S113)


236-238: try-except-pass detected, consider logging the exception

(S110)


236-236: Do not catch blind exception: Exception

(BLE001)


244-244: Do not catch blind exception: Exception

(BLE001)


308-308: Do not catch blind exception: Exception

(BLE001)

src/codegen/cli/commands/repo/tui.py

138-138: Consider moving this statement to an else block

(TRY300)


140-140: Do not catch blind exception: Exception

(BLE001)


281-281: Consider moving this statement to an else block

(TRY300)


283-283: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Sourcery review
🔇 Additional comments (38)
tests/unit/codegen/agents/test_agent.py (1)

76-76: Cannot verify — ripgrep skipped files; re-run these checks

'missing-argument' is not a mypy code. Use 'call-arg' (mypy) or remove the tool-specific ignore.

-            Agent()  # type: ignore[missing-argument] # Missing required token parameter
+            Agent()  # type: ignore[call-arg]  # Missing required token parameter

Run these and paste results:

# find type: ignore[...] occurrences (avoid glob filters that skip files)
rg -n "type:\s*ignore\[[^\]]+\]" || true

# check for pyright config
fd -a pyrightconfig.json || true

# check for mypy config sections
rg -n "^\s*\[tool\.mypy\]" pyproject.toml setup.cfg mypy.ini 2>/dev/null || true
tests/unit/codegen/test_top_level_imports.py (2)

10-20: Top-level alias identity check looks good

Verifies the public facade matches the submodule export. No issues.


26-31: all visibility checks are appropriate

Good guardrails to keep the package surface stable.

src/codegen/cli/commands/repo/__init__.py (1)

5-5: LGTM: consistent export and trailing newline.
Matches org/repo pattern and keeps API unchanged.

pyproject.toml (1)

28-28: No change required — [email protected] is current and compatible with fastmcp.
PyPI shows mcp-python 0.1.4 (uploaded Jan 8, 2025); there are no newer releases or breaking changes to compare, and fastmcp is a separate package that can coexist.

src/codegen/cli/commands/org/__init__.py (1)

5-5: LGTM: consistent export and trailing newline.
No behavioral changes; consistent with repo/init.py.

src/codegen/cli/commands/claude/quiet_console.py (1)

11-11: LGTM: harmless whitespace tidy-up.
No runtime changes; module behavior intact.

src/codegen/cli/utils/inplace_print.py (1)

2-2: LGTM: switch to collections.abc.Iterable for 3.12+.
Correct modern typing; no behavior change.

src/codegen/shared/logging/get_logger.py (1)

67-67: LGTM: import reordering is safe

Keeps telemetry config import within the guarded block; no behavior change.

src/codegen/cli/utils/org.py (1)

36-50: LGTM: cache validation path reads cleanly

Whitespace tidy-up is fine; the “not in cache” message with available orgs improves UX.

src/codegen/cli/telemetry/exception_logger.py (1)

12-14: LGTM: import order

Reordering otel setup imports ahead of logger helps avoid cycles; behavior unchanged.

src/codegen/cli/tui/codegen_theme.tcss (1)

3-7: LGTM: formatting only

Comment header cleanup and EOF newline; no semantic changes.

Also applies to: 185-185

src/codegen/cli/telemetry/debug_exporter.py (1)

10-10: LGTM: timestamps moved to UTC

Using datetime.now(timezone.utc) for session id and markers improves consistency across environments.

Also applies to: 36-36, 45-46, 113-113

docs/docs.json (1)

62-67: Ensure new nav entries resolve (avoid 404s)

Both pages are present and listed in navigation: docs/settings/team-roles.mdx and docs/settings/agent-permissions.mdx (asset: docs/images/agent-permissions.png).

src/codegen/cli/cli.py (2)

15-15: LGTM: command wiring

Importing and exposing the new mcp subcommand is correct.


69-69: LGTM: user-facing help

Help text is clear and consistent with other commands.

src/codegen/cli/commands/org/tui.py (3)

33-35: LGTM: clear no-org warning

Good UX: actionable message when cache is empty.


55-56: LGTM: helpful persistence hint

The post-table hint about updating CODEGEN_ORG_ID is concise and useful.


130-134: LGTM: newline normalization

Ensuring every line ends with \n avoids accidental concatenation on writeback.

src/codegen/git/repo_operator/repo_operator.py (1)

760-772: Log a warning when PR not found in create_pr_comment

When get_pull_safe(pr_number) returns None, log a concise warning to aid debugging; docstring already marks the return Optional. Repo search found no internal callers; absence of matches isn't proof—ensure external consumers handle None.

Location: src/codegen/git/repo_operator/repo_operator.py:760-772

         pr = self.remote_git_repo.get_pull_safe(pr_number)
         if pr:
             comment = self.remote_git_repo.create_issue_comment(pr, body)
             return comment
-        return None
+        logger.warning(f"PR not found; cannot create comment (pr_number={pr_number})")
+        return None
src/codegen/cli/tui/app.py (3)

888-889: Good switch to logger.exception for unexpected browser errors.

Keeps the traceback for diagnostics while preserving user feedback.


985-986: Good: preserve traceback when failing to open PR.

The exception context will help diagnose platform/browser issues.


998-999: Good: preserve traceback when failing to open trace.

Consistent with the PR’s logging intent.

src/codegen/cli/commands/org/main.py (1)

101-105: EOF newline normalization looks good.

Ensures robust round-tripping of .env content.

src/codegen/cli/commands/claude/claude_log_utils.py (4)

42-59: Typing update LGTM.

Optional[dict[str, Any]] for parsed JSON lines is appropriate; error handling is conservative.


88-89: File open change LGTM.

Dropping explicit mode while adding encoding is fine.


94-113: Validation signature and logic LGTM.

Straightforward checks and future-proof for stricter schemas.


115-126: Pass-through formatter LGTM.

Keeps surface compatible while allowing future transforms.

src/codegen/cli/utils/repo.py (3)

50-55: Typing modernization LGTM.

Return-type switch to built-in generics is consistent with PEP 585.


91-95: Safe read of .env LGTM.

Keeps behavior consistent with other modules.


195-226: Caching flow LGTM.

Reasonable fallback to mock data and cache population.

src/codegen/cli/tui/agent_detail.py (2)

32-37: Constructor typing and state init LGTM.

Aligns with built-in generics and optional org resolution.


266-268: Open-in-browser flow LGTM.

Good user feedback via notifications.

src/codegen/cli/commands/claude/claude_session_api.py (1)

13-14: Import move is fine

Reordering the console import below resolve_org_id is harmless here. No functional impact.

src/codegen/cli/commands/claude/main.py (1)

298-301: Good switch to logger.exception

Using logger.exception(...) preserves the stack trace for FileNotFoundError paths.

src/codegen/cli/commands/claude/config/claude_session_hook.py (1)

68-70: Guarded API call is correct

The create_claude_session check prevents calling a missing symbol when the import fails.

src/codegen/cli/commands/repo/tui.py (2)

11-12: Scoped imports look good

Using only ensure_repositories_cached and get_current_repo_id tightens dependencies.


32-34: Clear “no repositories” message

Concise single-line container is fine.

Comment on lines +109 to +111
- [Agent Permissions](/settings/agent-permissions) - Configure what actions agents can perform
- [Organization Rules](/settings/organization-rules) - Set organization-wide rules
- [Repository Rules](/settings/repo-rules) - Configure repository-specific behavior
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Broken/undeclared link: Organization Rules

/settings/organization-rules isn’t in docs.json navigation. Either add the page to docs/docs.json or update the link to an existing page.

Run:


🏁 Script executed:

#!/bin/bash
fd -a 'organization-rules.*' docs || true
jq -r '.navigation.tabs[0].groups[]?|select(.group=="Settings")|.pages' docs/docs.json

Length of output: 174


Add missing navigation entry: Organization Rules

docs/settings/team-roles.mdx (lines 109–111) links to /settings/organization-rules; docs/settings/organization-rules.mdx exists but "settings/organization-rules" is not listed in docs/docs.json (navigation.tabs[0].groups[] where group == "Settings"). Add "settings/organization-rules" to that pages array or update the link to an existing page.

🤖 Prompt for AI Agents
In docs/settings/team-roles.mdx around lines 109 to 111 the page links to
/settings/organization-rules but the route "settings/organization-rules" is
missing from the documentation navigation; open docs/docs.json, locate
navigation.tabs[0].groups[] item where group == "Settings" and add
"settings/organization-rules" to that group's pages array (or alternatively
change the link in team-roles.mdx to an existing listed page); ensure the path
string matches the existing routing format used elsewhere in docs.json.

Comment on lines 79 to 84
# Before API call
logger.info("Making API request", extra={
"operation": "api.request",
"endpoint": "agent/run",
"org_id": org_id
})
logger.info("Making API request", extra={"operation": "api.request", "endpoint": "agent/run", "org_id": org_id})

# After successful API call
logger.info("API request successful", extra={
"operation": "api.request",
"endpoint": "agent/run",
"response_id": response.get("id"),
"status_code": response.status_code
})
logger.info("API request successful", extra={"operation": "api.request", "endpoint": "agent/run", "response_id": response.get("id"), "status_code": response.status_code})
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix incorrect Response usage in example

requests.Response doesn’t support .get(...). Use response.json().get(...) or the parsed dict.

-logger.info("API request successful", extra={"operation": "api.request", "endpoint": "agent/run", "response_id": response.get("id"), "status_code": response.status_code})
+logger.info(
+    "API request successful",
+    extra={
+        "operation": "api.request",
+        "endpoint": "agent/run",
+        "response_id": response.json().get("id"),
+        "status_code": response.status_code,
+    },
+)

Optionally align this with the agent example that assigns agent_run_data = response.json().

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Before API call
logger.info("Making API request", extra={
"operation": "api.request",
"endpoint": "agent/run",
"org_id": org_id
})
logger.info("Making API request", extra={"operation": "api.request", "endpoint": "agent/run", "org_id": org_id})
# After successful API call
logger.info("API request successful", extra={
"operation": "api.request",
"endpoint": "agent/run",
"response_id": response.get("id"),
"status_code": response.status_code
})
logger.info("API request successful", extra={"operation": "api.request", "endpoint": "agent/run", "response_id": response.get("id"), "status_code": response.status_code})
```
# Before API call
logger.info("Making API request", extra={"operation": "api.request", "endpoint": "agent/run", "org_id": org_id})
# After successful API call
logger.info(
"API request successful",
extra={
"operation": "api.request",
"endpoint": "agent/run",
"response_id": response.json().get("id"),
"status_code": response.status_code,
},
)
🤖 Prompt for AI Agents
In QUICK_START_LOGGING.md around lines 79 to 84, the example incorrectly calls
response.get(...) on a requests.Response object; parse the JSON first (e.g.,
agent_run_data = response.json()) or call response.json().get(...) and then use
that parsed dict for response_id and any other fields so the logging example
uses a dict (response_id = agent_run_data.get("id")) instead of
response.get(...).

Comment on lines +112 to +113
self.notify("i Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix f-string bug: literal {org_id} shown to users

self.notify("...{org_id}...") should be an f-string; currently prints the braces verbatim.

-            self.notify("i  Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
+            self.notify(f"i  Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
self.notify("i Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
self.notify(f"i Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
🤖 Prompt for AI Agents
In src/codegen/cli/commands/org/tui.py around lines 112 to 113, the notify call
uses a plain string with "{org_id}" so the literal braces are printed; change it
to an f-string that interpolates the org_id variable (e.g., prefix the string
with f and include {org_id} in the message) so the actual organization ID is
shown to users.

Comment on lines +268 to +269
self.notify("i Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix f-string bug (duplicate occurrence)

Same issue as above in OrgSelectorApp.

-            self.notify("i  Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
+            self.notify(f"i  Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
self.notify("i Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
self.notify(f"i Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
🤖 Prompt for AI Agents
In src/codegen/cli/commands/org/tui.py around lines 268-269, the notification
string incorrectly uses a literal "{org_id}" (or a duplicated formatting)
instead of interpolating the org_id; change the message to use a single f-string
that injects the org_id (e.g. prefix the string with f and include {org_id}
once) so the notification shows the actual org id and remove any
duplicate/incorrect formatting.

Comment on lines +117 to 118
console.print("[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix missing interpolation in user message

{repo_id} won’t interpolate without an f-string.

Apply:

-            console.print("[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
+            console.print(f"[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.print("[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
console.print(f"[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
🤖 Prompt for AI Agents
In src/codegen/cli/commands/repo/main.py around lines 117-118 the console.print
message uses a literal "{repo_id}" so the repository id won't be interpolated;
update the call to use an f-string (or .format) to inject the repo_id variable
(e.g. console.print(f"...{repo_id}...")) so the actual ID appears in the
message.

Comment on lines 101 to +103
self.notify(f"✓ Set repository: {repo_name} (ID: {repo_id})")
self.notify(" Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
self.notify("i Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix missing interpolation in TUI notification

{repo_id} is not formatted.

Apply:

-            self.notify("i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
+            self.notify(f"i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
self.notify(f"✓ Set repository: {repo_name} (ID: {repo_id})")
self.notify("ℹ Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
self.notify("i Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
self.notify(f"✓ Set repository: {repo_name} (ID: {repo_id})")
self.notify(f"i Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
🤖 Prompt for AI Agents
In src/codegen/cli/commands/repo/tui.py around lines 101 to 103, the
notification message that instructs adding CODEGEN_REPO_ID to the shell contains
a literal "{repo_id}" instead of inserting the repo_id value; change the call to
use string interpolation (e.g., an f-string or .format) so the actual repo_id is
included in the message, ensuring the notify call outputs the correct value for
persistence instructions.

Comment on lines +245 to +246
self.notify("i Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix missing interpolation in App notification

Same formatting issue in App variant.

Apply:

-            self.notify("i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
+            self.notify(f"i  Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
self.notify("i Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
self.notify(f"i Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
🤖 Prompt for AI Agents
In src/codegen/cli/commands/repo/tui.py around lines 245-246, the notify call
prints a literal "{repo_id}" instead of the variable's value; update the string
to interpolate the repo_id (e.g., use an f-string or .format) so the actual
repository id is inserted into "Add 'export CODEGEN_REPO_ID=...' to your shell
for persistence" before calling self.notify.

Comment on lines 128 to +131
response = requests.get(url, headers=headers)
response.raise_for_status()
self.agent_data = response.json()

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add timeout to detail fetch.

Prevents TUI from hanging on network issues.

-            response = requests.get(url, headers=headers)
+            response = requests.get(url, headers=headers, timeout=10)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
response = requests.get(url, headers=headers)
response.raise_for_status()
self.agent_data = response.json()
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
self.agent_data = response.json()
🧰 Tools
🪛 Ruff (0.12.2)

128-128: Probable use of requests call without timeout

(S113)

🤖 Prompt for AI Agents
In src/codegen/cli/tui/agent_detail.py around lines 128 to 131, the requests.get
call that fetches agent details has no timeout and can hang on network issues;
add a timeout argument (e.g. timeout=5 or configurable) to requests.get and
handle potential timeout/RequestException by catching it, logging or showing a
user-friendly error in the TUI, and ensuring the code still calls
response.raise_for_status()/response.json() only when a response was
successfully returned.

Comment on lines 163 to 170
response = requests.get(url, headers=headers)

if response.status_code == 200:
data = response.json()
return data.get("items", [])
else:
# API endpoint doesn't exist yet, return mock data for demo
return get_mock_repositories()
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add timeout to repository API call.

Avoids CLI stalls on slow networks.

-        response = requests.get(url, headers=headers)
+        response = requests.get(url, headers=headers, timeout=10)
🧰 Tools
🪛 Ruff (0.12.2)

163-163: Probable use of requests call without timeout

(S113)

🤖 Prompt for AI Agents
In src/codegen/cli/utils/repo.py around lines 163-170, the requests.get call
needs a timeout to prevent CLI stalls; change the code to call requests.get(url,
headers=headers, timeout=10) (or another sensible timeout), wrap the request in
a try/except catching requests.exceptions.RequestException, and on exception
return get_mock_repositories() (and optionally log a warning); keep the existing
behavior for non-200 responses.

Comment on lines +34 to 41
path = default_repo_config.path or os.getcwd()
language = default_repo_config.language or "python"
return RepoConfig(
name=default_repo_config.name,
full_name=default_repo_config.full_name,
base_dir=os.path.dirname(default_repo_config.path),
language=ProgrammingLanguage(default_repo_config.language.upper()),
base_dir=os.path.dirname(path),
language=ProgrammingLanguage(language.upper()),
)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Harden enum construction to avoid ValueError on unknown language

ProgrammingLanguage(language.upper()) will raise if an unexpected value is present. Guard and default to OTHER.

-        path = default_repo_config.path or os.getcwd()
-        language = default_repo_config.language or "python"
+        path = default_repo_config.path or os.getcwd()
+        language_str = (default_repo_config.language or "python").upper()
+        try:
+            language_enum = ProgrammingLanguage(language_str)
+        except ValueError:
+            logger.warning("Unknown language '%s'; defaulting to OTHER", language_str)
+            language_enum = ProgrammingLanguage.OTHER
         return RepoConfig(
             name=default_repo_config.name,
             full_name=default_repo_config.full_name,
-            base_dir=os.path.dirname(path),
-            language=ProgrammingLanguage(language.upper()),
+            base_dir=os.path.dirname(path),
+            language=language_enum,
         )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
path = default_repo_config.path or os.getcwd()
language = default_repo_config.language or "python"
return RepoConfig(
name=default_repo_config.name,
full_name=default_repo_config.full_name,
base_dir=os.path.dirname(default_repo_config.path),
language=ProgrammingLanguage(default_repo_config.language.upper()),
base_dir=os.path.dirname(path),
language=ProgrammingLanguage(language.upper()),
)
path = default_repo_config.path or os.getcwd()
language_str = (default_repo_config.language or "python").upper()
try:
language_enum = ProgrammingLanguage(language_str)
except ValueError:
logger.warning("Unknown language '%s'; defaulting to OTHER", language_str)
language_enum = ProgrammingLanguage.OTHER
return RepoConfig(
name=default_repo_config.name,
full_name=default_repo_config.full_name,
base_dir=os.path.dirname(path),
language=language_enum,
)
🤖 Prompt for AI Agents
In src/codegen/git/schemas/repo_config.py around lines 34 to 41, constructing
the enum with ProgrammingLanguage(language.upper()) can raise ValueError for
unknown values; change this to a safe mapping that falls back to
ProgrammingLanguage.OTHER (e.g., check if language.upper() is a valid member
name via ProgrammingLanguage.__members__ or use a try/except around the enum
construction and set to ProgrammingLanguage.OTHER on failure) so unknown/invalid
language strings do not crash the code.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

11 issues found across 56 files

Prompt for AI agents (all 11 issues)

Understand the root cause of the following 11 issues and fix them.


<file name="src/codegen/cli/commands/repo/tui.py">

<violation number="1" location="src/codegen/cli/commands/repo/tui.py:102">
User message does not interpolate repo_id; string lacks f prefix, so the placeholder is shown literally.</violation>
</file>

<file name="src/codegen/cli/commands/claude/config/claude_session_active_hook.py">

<violation number="1" location="src/codegen/cli/commands/claude/config/claude_session_active_hook.py:22">
Type annotation constrains update_claude_session_status to None, conflicting with callable import path and likely breaking static type checking; remove or correct the annotation.</violation>
</file>

<file name="src/codegen/cli/commands/org/tui.py">

<violation number="1" location="src/codegen/cli/commands/org/tui.py:112">
The message shows {org_id} literally because the string is not formatted; use an f-string to interpolate the org_id.</violation>
</file>

<file name="src/codegen/git/utils/pr_review.py">

<violation number="1" location="src/codegen/git/utils/pr_review.py:134">
Catching ImportError is too broad for this intent and can mask missing/renamed symbol errors; catch ModuleNotFoundError to only handle a missing SDK package.</violation>
</file>

<file name="src/codegen/cli/utils/repo.py">

<violation number="1" location="src/codegen/cli/utils/repo.py:135">
Empty string environment variables are treated as active; mark empty values as inactive for accurate status.</violation>
</file>

<file name="src/codegen/cli/commands/claude/claude_log_utils.py">

<violation number="1" location="src/codegen/cli/commands/claude/claude_log_utils.py:42">
Function can return non-dict JSON from json.loads, but annotation specifies Optional[dict[str, Any]]; adjust the annotation or enforce dict-only returns.</violation>
</file>

<file name="src/codegen/cli/commands/claude/config/claude_session_hook.py">

<violation number="1" location="src/codegen/cli/commands/claude/config/claude_session_hook.py:23">
Variable is annotated as type None but used as a callable, which can confuse or break static type checking; remove the incorrect annotation.</violation>

<violation number="2" location="src/codegen/cli/commands/claude/config/claude_session_hook.py:24">
Variable is annotated as type None but intended to refer to a callable; remove the incorrect annotation to avoid type-checking confusion.</violation>
</file>

<file name="src/codegen/cli/commands/claude/config/claude_session_stop_hook.py">

<violation number="1" location="src/codegen/cli/commands/claude/config/claude_session_stop_hook.py:22">
Incorrect type annotation narrows update_claude_session_status to None instead of Optional[Callable], conflicting with its callable usage and likely breaking type checking.</violation>
</file>

<file name="QUICK_START_LOGGING.md">

<violation number="1" location="QUICK_START_LOGGING.md:83">
response.get(...) conflicts with response.status_code; use response.json().get(&quot;id&quot;) to access the JSON id from a requests.Response</violation>
</file>

<file name="src/codegen/cli/commands/repo/main.py">

<violation number="1" location="src/codegen/cli/commands/repo/main.py:117">
The message shows {repo_id} literally; without an f-string the export command won&#39;t include the actual repository ID.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

self.notify(f"✓ Set repository: {repo_name} (ID: {repo_id})")
self.notify(" Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
self.notify("i Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

User message does not interpolate repo_id; string lacks f prefix, so the placeholder is shown literally.

Prompt for AI agents
Address the following comment on src/codegen/cli/commands/repo/tui.py at line 102:

<comment>User message does not interpolate repo_id; string lacks f prefix, so the placeholder is shown literally.</comment>

<file context>
@@ -103,59 +90,59 @@ def _set_repository(self, repo_id: int, repo_name: str) -&gt; None:
             self.notify(f&quot;✓ Set repository: {repo_name} (ID: {repo_id})&quot;)
-            self.notify(&quot;ℹ  Add &#39;export CODEGEN_REPO_ID={repo_id}&#39; to your shell for persistence&quot;)
-        
+            self.notify(&quot;i  Add &#39;export CODEGEN_REPO_ID={repo_id}&#39; to your shell for persistence&quot;)
+
         # Wait a moment for user to see the notifications, then exit
</file context>
Suggested change
self.notify("i Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
self.notify(f"i Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
Fix with Cubic

from codegen.cli.commands.claude.claude_session_api import update_claude_session_status
except ImportError:
update_claude_session_status = None
update_claude_session_status: None = None
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

Type annotation constrains update_claude_session_status to None, conflicting with callable import path and likely breaking static type checking; remove or correct the annotation.

Prompt for AI agents
Address the following comment on src/codegen/cli/commands/claude/config/claude_session_active_hook.py at line 22:

<comment>Type annotation constrains update_claude_session_status to None, conflicting with callable import path and likely breaking static type checking; remove or correct the annotation.</comment>

<file context>
@@ -19,7 +19,7 @@
     from codegen.cli.commands.claude.claude_session_api import update_claude_session_status
 except ImportError:
-    update_claude_session_status = None
+    update_claude_session_status: None = None
 
 
</file context>
Suggested change
update_claude_session_status: None = None
update_claude_session_status = None
Fix with Cubic

self.notify(f"✓ Set organization: {org_name} (ID: {org_id})")
self.notify(" Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
self.notify("i Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

The message shows {org_id} literally because the string is not formatted; use an f-string to interpolate the org_id.

Prompt for AI agents
Address the following comment on src/codegen/cli/commands/org/tui.py at line 112:

<comment>The message shows {org_id} literally because the string is not formatted; use an f-string to interpolate the org_id.</comment>

<file context>
@@ -106,24 +100,24 @@ def _set_organization(self, org_id: int, org_name: str) -&gt; None:
             self.notify(f&quot;✓ Set organization: {org_name} (ID: {org_id})&quot;)
-            self.notify(&quot;ℹ  Add &#39;export CODEGEN_ORG_ID={org_id}&#39; to your shell for persistence&quot;)
-        
+            self.notify(&quot;i  Add &#39;export CODEGEN_ORG_ID={org_id}&#39; to your shell for persistence&quot;)
+
         # Wait a moment for user to see the notifications, then close
</file context>
Suggested change
self.notify("i Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
self.notify(f"i Add 'export CODEGEN_ORG_ID={org_id}' to your shell for persistence")
Fix with Cubic

from codegen.sdk.core.file import SourceFile
try:
from codegen.sdk.core.file import SourceFile
except ImportError:
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

Catching ImportError is too broad for this intent and can mask missing/renamed symbol errors; catch ModuleNotFoundError to only handle a missing SDK package.

Prompt for AI agents
Address the following comment on src/codegen/git/utils/pr_review.py at line 134:

<comment>Catching ImportError is too broad for this intent and can mask missing/renamed symbol errors; catch ModuleNotFoundError to only handle a missing SDK package.</comment>

<file context>
@@ -129,7 +129,11 @@ def is_modified(self, editable: &quot;Editable&quot;) -&gt; bool:
-        from codegen.sdk.core.file import SourceFile
+        try:
+            from codegen.sdk.core.file import SourceFile
+        except ImportError:
+            # If SDK is not available, return empty list
+            return []
</file context>
Suggested change
except ImportError:
except ModuleNotFoundError:
Fix with Cubic

"status": "active" if value != "Not set" else "inactive"
})

info.append({"label": f"{var_name}", "value": value, "status": "active" if value != "Not set" else "inactive"})
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

Empty string environment variables are treated as active; mark empty values as inactive for accurate status.

Prompt for AI agents
Address the following comment on src/codegen/cli/utils/repo.py at line 135:

<comment>Empty string environment variables are treated as active; mark empty values as inactive for accurate status.</comment>

<file context>
@@ -87,107 +87,96 @@ def update_env_file_with_repo(repo_id: int, env_file_path: str = &quot;.env&quot;) -&gt; bool
-            &quot;status&quot;: &quot;active&quot; if value != &quot;Not set&quot; else &quot;inactive&quot;
-        })
-    
+        info.append({&quot;label&quot;: f&quot;{var_name}&quot;, &quot;value&quot;: value, &quot;status&quot;: &quot;active&quot; if value != &quot;Not set&quot; else &quot;inactive&quot;})
+
     return info
</file context>
Suggested change
info.append({"label": f"{var_name}", "value": value, "status": "active" if value != "Not set" else "inactive"})
info.append({"label": f"{var_name}", "value": value, "status": "active" if value not in ("", "Not set") else "inactive"})
Fix with Cubic

except ImportError:
create_claude_session = None
create_claude_session: None = None
resolve_org_id: None = None
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

Variable is annotated as type None but intended to refer to a callable; remove the incorrect annotation to avoid type-checking confusion.

Prompt for AI agents
Address the following comment on src/codegen/cli/commands/claude/config/claude_session_hook.py at line 24:

<comment>Variable is annotated as type None but intended to refer to a callable; remove the incorrect annotation to avoid type-checking confusion.</comment>

<file context>
@@ -20,7 +20,8 @@
 except ImportError:
-    create_claude_session = None
+    create_claude_session: None = None
+    resolve_org_id: None = None
 
 
</file context>
Suggested change
resolve_org_id: None = None
resolve_org_id = None
Fix with Cubic

from codegen.cli.utils.org import resolve_org_id
except ImportError:
create_claude_session = None
create_claude_session: None = None
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

Variable is annotated as type None but used as a callable, which can confuse or break static type checking; remove the incorrect annotation.

Prompt for AI agents
Address the following comment on src/codegen/cli/commands/claude/config/claude_session_hook.py at line 23:

<comment>Variable is annotated as type None but used as a callable, which can confuse or break static type checking; remove the incorrect annotation.</comment>

<file context>
@@ -20,7 +20,8 @@
     from codegen.cli.utils.org import resolve_org_id
 except ImportError:
-    create_claude_session = None
+    create_claude_session: None = None
+    resolve_org_id: None = None
 
</file context>
Suggested change
create_claude_session: None = None
create_claude_session = None
Fix with Cubic

from codegen.cli.commands.claude.claude_session_api import update_claude_session_status
except ImportError:
update_claude_session_status = None
update_claude_session_status: None = None
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

Incorrect type annotation narrows update_claude_session_status to None instead of Optional[Callable], conflicting with its callable usage and likely breaking type checking.

Prompt for AI agents
Address the following comment on src/codegen/cli/commands/claude/config/claude_session_stop_hook.py at line 22:

<comment>Incorrect type annotation narrows update_claude_session_status to None instead of Optional[Callable], conflicting with its callable usage and likely breaking type checking.</comment>

<file context>
@@ -19,7 +19,7 @@
     from codegen.cli.commands.claude.claude_session_api import update_claude_session_status
 except ImportError:
-    update_claude_session_status = None
+    update_claude_session_status: None = None
 
 
</file context>
Suggested change
update_claude_session_status: None = None
update_claude_session_status = None
Fix with Cubic

"response_id": response.get("id"),
"status_code": response.status_code
})
logger.info("API request successful", extra={"operation": "api.request", "endpoint": "agent/run", "response_id": response.get("id"), "status_code": response.status_code})
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

response.get(...) conflicts with response.status_code; use response.json().get("id") to access the JSON id from a requests.Response

Prompt for AI agents
Address the following comment on QUICK_START_LOGGING.md at line 83:

<comment>response.get(...) conflicts with response.status_code; use response.json().get(&quot;id&quot;) to access the JSON id from a requests.Response</comment>

<file context>
@@ -48,69 +51,56 @@ codegen config telemetry status
-    &quot;response_id&quot;: response.get(&quot;id&quot;),
-    &quot;status_code&quot;: response.status_code
-})
+logger.info(&quot;API request successful&quot;, extra={&quot;operation&quot;: &quot;api.request&quot;, &quot;endpoint&quot;: &quot;agent/run&quot;, &quot;response_id&quot;: response.get(&quot;id&quot;), &quot;status_code&quot;: response.status_code})
 ```
 
</file context>
Suggested change
logger.info("API request successful", extra={"operation": "api.request", "endpoint": "agent/run", "response_id": response.get("id"), "status_code": response.status_code})
logger.info("API request successful", extra={"operation": "api.request", "endpoint": "agent/run", "response_id": response.json().get("id"), "status_code": response.status_code})
Fix with Cubic

else:
console.print(f"[green]✓[/green] Set repository ID to: [cyan]{repo_id}[/cyan]")
console.print("[yellow][/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
console.print("[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
Copy link

@cubic-dev-ai cubic-dev-ai bot Sep 12, 2025

Choose a reason for hiding this comment

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

The message shows {repo_id} literally; without an f-string the export command won't include the actual repository ID.

Prompt for AI agents
Address the following comment on src/codegen/cli/commands/repo/main.py at line 117:

<comment>The message shows {repo_id} literally; without an f-string the export command won&#39;t include the actual repository ID.</comment>

<file context>
@@ -116,13 +108,13 @@ def _set_default_repository(repo_id: int) -&gt; None:
         else:
             console.print(f&quot;[green]✓[/green] Set repository ID to: [cyan]{repo_id}[/cyan]&quot;)
-            console.print(&quot;[yellow]ℹ[/yellow] Could not update .env file. Add &#39;export CODEGEN_REPO_ID={repo_id}&#39; to your shell for persistence&quot;)
+            console.print(&quot;[yellow]i[/yellow] Could not update .env file. Add &#39;export CODEGEN_REPO_ID={repo_id}&#39; to your shell for persistence&quot;)
 
     except Exception as e:
</file context>
Suggested change
console.print("[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
console.print(f"[yellow]i[/yellow] Could not update .env file. Add 'export CODEGEN_REPO_ID={repo_id}' to your shell for persistence")
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant