Skip to content

Conversation

@LiamConnell
Copy link

Summary

This PR adds a new sample demonstrating a CLI coding assistant built with ADK. It's a simple, educational example showing how to build an interactive terminal agent with custom tools.

Note: This is intentionally a toy example to demonstrate ADK patterns, not a production-ready coding assistant.

Features

File System Tools

  • read_file - Read file contents with metadata
  • write_file - Create or overwrite files
  • update_file - Replace text within files
  • list_directory - List files/directories with glob patterns

Task Planning Tools

  • create_plan - Break down complex tasks into steps
  • update_plan - Mark tasks as completed
  • get_plan - View current plan and progress
  • reset_plan - Clear completed plan

Interactive CLI

  • Colorful terminal output with progress tracking
  • Visual task lists showing plan progress
  • Verbose/concise output modes
  • Works with adk web for browser-based interaction

ADK Patterns Demonstrated

  • Custom tool definitions with @tool decorator
  • Tool state management (for task planning)
  • Interactive CLI runner with streaming
  • Integration with adk web command

Test Plan

Manual Testing

cd contributing/samples/cli_coding_agent

# Install dependencies
uv pip install -r requirements.txt

# Authenticate
gcloud auth application-default login

# Run interactive CLI
uv run python -m agent

# Or use ADK web interface
adk web agent

Example Interaction

[You]: Help me create a simple Python script

📋 PLAN: Create Python Script
Progress: [████░░░░░░░░] 1/3 (33%)
  ✓ [0] Create script file
  ○ [1] Add main function
  ○ [2] Add documentation

🔧 write_file(file_path=script.py, content=...)
✓ write_file

Commands:

  • exit/quit - Exit the assistant
  • verbose - Toggle verbose tool output

A toy AI coding assistant demonstrating ADK tool usage with:
- File system tools (read, write, update, list directory)
- Task planning tools (create, update, get, reset plan)
- Colorful interactive CLI with progress tracking
- Verbose/concise output modes

This sample shows how to build an interactive CLI agent with
custom tools for file manipulation and task management.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @LiamConnell, 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 adds a comprehensive new sample application to the repository: a command-line interface (CLI) coding assistant. The primary goal is to illustrate how to leverage the ADK framework to build an interactive agent that can perform practical development tasks. It focuses on providing a clear, educational example of integrating custom functionalities like file system manipulation and structured task planning within an ADK-powered agent, complete with an engaging terminal user interface.

Highlights

  • New CLI Coding Agent Sample: Introduces a new sample application: a CLI coding assistant built with ADK, showcasing an interactive terminal agent with custom tools.
  • File System Tools: The agent is equipped with tools for file system operations, including read_file, write_file, update_file, and list_directory.
  • Task Planning Capabilities: New tools for task planning are included: create_plan, update_plan, get_plan, and reset_plan, allowing the agent to manage multi-step tasks.
  • Interactive CLI with Visuals: The CLI provides a colorful, interactive user experience with progress tracking, visual task lists, and toggleable verbose/concise output modes.
  • ADK Pattern Demonstration: The sample demonstrates key ADK patterns such as custom tool definitions using the @tool decorator, tool state management, interactive CLI runner with streaming, and integration with the adk web command.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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.

@adk-bot adk-bot added the tools [Component] This issue is related to tools label Jan 23, 2026
@adk-bot
Copy link
Collaborator

adk-bot commented Jan 23, 2026

Response from ADK Triaging Agent

Hello @LiamConnell, thank you for creating this PR!

Could you please associate the github issue with this PR? If there is no existing issue, could you please create one? This information will help reviewers to review your PR more efficiently. Thanks!

Copy link
Contributor

@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 an excellent and comprehensive sample of a CLI coding assistant using the ADK. The interactive CLI with its colorful output and progress tracking is a great touch. The code is generally well-structured and demonstrates several important ADK patterns. I've identified one critical issue: a missing dependency in requirements.txt that will prevent the sample from running. Additionally, I've provided some feedback to improve code robustness, maintainability, and to highlight best practices for state management, which is particularly important for an educational example like this one. Overall, this is a valuable addition to the samples.

Comment on lines +1 to +2
google-adk
google-genai
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

The agent/__init__.py file imports and uses dotenv, but python-dotenv is not listed as a dependency in requirements.txt. This will cause an ImportError when a user follows the setup instructions. Please add it to the requirements file.

google-adk
google-genai
python-dotenv

from typing import Optional

# Global plan state
_current_plan: dict | None = None
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Using a global variable _current_plan to manage state is simple for this toy example, but it's important to be aware of its limitations. This approach is not thread-safe and would not work correctly in a multi-user or multi-session environment, as all concurrent executions would share and potentially overwrite the same plan. For a more robust solution, especially in a real application, this state should be managed on a per-session basis. The ADK provides session.state for this purpose, which would be the idiomatic way to handle session-specific data.

Comment on lines +41 to +45
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(console_handler)
root_logger.addHandler(file_handler)

Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Configuring the root logger directly can be risky. If setup_logging is called multiple times (e.g., during tests or reloads), it will add duplicate handlers, leading to repeated log messages. It's safer to clear any existing handlers before adding new ones to make the function idempotent.

Suggested change
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(console_handler)
root_logger.addHandler(file_handler)
# Configure root logger
root_logger = logging.getLogger()
root_logger.handlers.clear()
root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(console_handler)
root_logger.addHandler(file_handler)

Comment on lines +175 to +184
if isinstance(response, dict):
print(f"{Colors.GRAY} Result:{Colors.RESET}")
formatted_response = json.dumps(response, indent=4)
for line in formatted_response.split("\n"):
print(f" {line}")
elif isinstance(response, list):
print(f"{Colors.GRAY} Result:{Colors.RESET}")
formatted_response = json.dumps(response, indent=4)
for line in formatted_response.split("\n"):
print(f" {line}")
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The code for handling dict and list responses is duplicated. You can combine these two blocks to make the code more concise and maintainable by following the Don't Repeat Yourself (DRY) principle.

Suggested change
if isinstance(response, dict):
print(f"{Colors.GRAY} Result:{Colors.RESET}")
formatted_response = json.dumps(response, indent=4)
for line in formatted_response.split("\n"):
print(f" {line}")
elif isinstance(response, list):
print(f"{Colors.GRAY} Result:{Colors.RESET}")
formatted_response = json.dumps(response, indent=4)
for line in formatted_response.split("\n"):
print(f" {line}")
if isinstance(response, (dict, list)):
print(f"{Colors.GRAY} Result:{Colors.RESET}")
formatted_response = json.dumps(response, indent=4)
for line in formatted_response.split("\n"):
print(f" {line}")

2. Work through tasks sequentially
3. Mark each task complete as you finish it
4. The plan will be displayed visually with progress tracking
5. When you finish all the tasks, reset the plan.
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There is a trailing whitespace at the end of this line. It should be removed for cleanliness.

Suggested change
5. When you finish all the tasks, reset the plan.
5. When you finish all the tasks, reset the plan.

"lines": None,
"is_binary": True,
}
except PermissionError as e:
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The exception object e is captured but not used in this except block. You can simplify this by removing as e.

Suggested change
except PermissionError as e:
except PermissionError:

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

Labels

tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants