Skip to content

feat(cli): Add UI components#453

Open
SHAURYASANYAL3 wants to merge 3 commits into
sreerevanth:mainfrom
SHAURYASANYAL3:feat/cli-ui-components
Open

feat(cli): Add UI components#453
SHAURYASANYAL3 wants to merge 3 commits into
sreerevanth:mainfrom
SHAURYASANYAL3:feat/cli-ui-components

Conversation

@SHAURYASANYAL3

@SHAURYASANYAL3 SHAURYASANYAL3 commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Splitting previous large PR. This PR adds the UI components for the CLI.

Summary by CodeRabbit

  • New Features
    • Added a CLI user interface displaying real-time dashboard metrics including token counts, costs, sessions, and block information.
    • Displays API status with fallback messaging when the service is unavailable.
    • Includes browser-based authentication guidance and interactive user prompts for streamlined access.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

A new agentwatch/cli/ui.py module is added, implementing a Rich-based CLI interface. It defines color tokens, fetches live metrics from a local dashboard HTTP endpoint, builds a top metrics panel, and composes a full-screen UI with an ASCII logo, auth URL, security notes, and interactive footer.

Changes

AgentWatch Rich CLI UI

Layer / File(s) Summary
Console setup, metrics fetch, and top panel
agentwatch/cli/ui.py
Imports Rich primitives, defines color constants and a truecolor Console, adds get_real_metrics() to GET /api/v1/dashboard/summary via httpx with a 2-second timeout and debug logging on failure, adds get_top_panel() to format token/cost/session/block counts or N/A fallback with a red bypass-permissions note, and adds print_header() as a thin wrapper that prints the panel.
Full-screen render and entry point
agentwatch/cli/ui.py
render_ui() assembles a welcome badge, padded ASCII logo text, browser sign-in instructions with a fixed auth URL, a divider rule, repeated badge/security notes, and a bold indigo footer prompt; a __main__ guard calls render_ui() for direct execution.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop hop, a new screen appears,
Colors and panels, calming our fears,
Tokens in thousands, costs in a line,
The ASCII logo looks simply divine,
Press Enter, dear user — all is fine! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat(cli): Add UI components' is partially related to the changeset but lacks specificity about what UI components are being added and their purpose. Consider a more specific title such as 'feat(cli): Add Rich-based CLI UI with dashboard metrics display' to better reflect the actual implementation.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

🧪 PR Test Results

Check Result
Tests (pytest tests/) ✅ success
Lint (ruff check .) ❌ failure
Coverage (agentwatch) 73.19%

Python 3.12 · commit 0e07ec6

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@agentwatch/cli/ui.py`:
- Around line 24-26: The get_real_metrics() function calls a protected API
endpoint at http://localhost:8000/api/v1/dashboard/summary without sending any
authentication credentials. This causes the request to fail with a 401 status
code, preventing the metrics from being retrieved. Add authentication to the
httpx.get() call by including the appropriate auth header or credentials
parameter. Ensure the authentication method matches what the upstream API
endpoint requires, so the request returns 200 with valid data instead of
failing.
- Around line 66-147: The render_ui() function does not call print_header(),
which means the metrics panel is never displayed in the main UI flow when the
application runs. Add a call to print_header() at the beginning of the
render_ui() function, before the main_panel is rendered with
console.print(main_panel), to ensure the metrics panel is properly included in
the output.
- Around line 95-96: The device authentication URL at line 95 contains a
hard-coded user code placeholder instead of the actual session-specific code,
which prevents users from logging in. Replace the static user code string
"ABCD-EFGH-IJKL-MNOP-QRST-UVWX-YZ01" in the auth URL with a dynamic variable
that contains the real user code generated for the current device authentication
session. Ensure this variable is available in the scope where the URL is being
constructed and passes the actual session-specific code to the user.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d4ef8051-1c78-46eb-b5aa-1c7bdfc00c4a

📥 Commits

Reviewing files that changed from the base of the PR and between 66eb9d7 and 0e07ec6.

📒 Files selected for processing (1)
  • agentwatch/cli/ui.py

Comment thread agentwatch/cli/ui.py
Comment on lines +24 to +26
resp = httpx.get("http://localhost:8000/api/v1/dashboard/summary", timeout=0.5)
if resp.status_code == 200:
return resp.json()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Protected dashboard endpoint is called without auth, so metrics will likely always fail.

get_real_metrics() calls a guarded API route (Line 24) but sends no credentials. Given the upstream contract, this typically returns 401 and forces perpetual N/A metrics.

Suggested direction
 def get_real_metrics() -> dict:
     try:
         import httpx
+        import os
 
-        resp = httpx.get("http://localhost:8000/api/v1/dashboard/summary", timeout=0.5)
+        api_key = os.getenv("AGENTWATCH_API_KEY")
+        headers = {"X-API-Key": api_key} if api_key else {}
+        resp = httpx.get(
+            "http://localhost:8000/api/v1/dashboard/summary",
+            timeout=0.5,
+            headers=headers,
+        )
         if resp.status_code == 200:
             return resp.json()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@agentwatch/cli/ui.py` around lines 24 - 26, The get_real_metrics() function
calls a protected API endpoint at http://localhost:8000/api/v1/dashboard/summary
without sending any authentication credentials. This causes the request to fail
with a 401 status code, preventing the metrics from being retrieved. Add
authentication to the httpx.get() call by including the appropriate auth header
or credentials parameter. Ensure the authentication method matches what the
upstream API endpoint requires, so the request returns 200 with valid data
instead of failing.

Comment thread agentwatch/cli/ui.py
Comment on lines +66 to +147
def render_ui():
# ==========================================
# 2. Main Body Container Content
# ==========================================
main_content = []

# 3. Accent Badges
badge_text = Text("∗ Welcome to AgentWatch research preview!", style=COLOR_MAIN_ACCENT)
badge_panel = Panel(badge_text, border_style=COLOR_MAIN_ACCENT, expand=False, padding=(0, 1))
main_content.append(badge_panel)

# 4. 3D Drop-Shadow ASCII Logo
# Retro double-stamped shadow effect colored in Salmon
ascii_logo = """
█████╗ ██████╗ ███████╗███╗ ██╗████████╗██╗ ██╗ █████╗ ████████╗██████╗ ██╗ ██╗
██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝██║ ██║██╔══██╗╚══██╔══╝██╔════╝ ██║ ██║
███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ██║ █╗ ██║███████║ ██║ ██║ ███████║
██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██║███╗██║██╔══██║ ██║ ██║ ██╔══██║
██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ╚███╔███╔╝██║ ██║ ██║ ╚██████╗ ██║ ██║
╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
"""
logo_text = Text(ascii_logo.strip("\n"), style=f"bold {COLOR_MAIN_ACCENT}")
main_content.append(Padding(logo_text, (1, 0, 1, 0)))

# 5. Instructional Content & Links
login_instruction = Text(
"Browser didn't open? Use the url below to sign in:\n", style=COLOR_WHITE
)
login_url = Text(
"https://auth.agentwatch.dev/device?user_code=ABCD-EFGH-IJKL-MNOP-QRST-UVWX-YZ01",
style=COLOR_DIM,
)
main_content.append(login_instruction + login_url)

# Divider
main_content.append(Padding(Rule(style=COLOR_DIM), (1, 0, 1, 0)))

# 6. Duplicated Badge & Security Bullet Points
main_content.append(badge_panel)

security_title = Text("\nSecurity notes:", style=f"bold {COLOR_WHITE}")
main_content.append(security_title)

security_notes = Text()
security_notes.append(
"\n1. AgentWatch is currently in research preview\n", style=f"bold {COLOR_WHITE}"
)
security_notes.append(
" AgentWatch is an experimental AI tool. It may produce incorrect or unexpected results.\n",
style=COLOR_DIM,
)

security_notes.append("2. AgentWatch runs in your terminal\n", style=f"bold {COLOR_WHITE}")
security_notes.append(
" It has the ability to view your files and execute commands on your behalf.\n",
style=COLOR_DIM,
)

security_notes.append("3. Review commands carefully\n", style=f"bold {COLOR_WHITE}")
security_notes.append(
" For your security, we strongly recommend carefully reviewing any commands before allowing AgentWatch to run them.\n",
style=COLOR_DIM,
)
security_notes.append(
" Learn more about the AgentWatch security model at: https://agentwatch.dev/security",
style=COLOR_DIM,
)

main_content.append(security_notes)

# Combine into main container
main_panel = Panel(Group(*main_content), border_style=COLOR_DIM, padding=(1, 2))

# ==========================================
# 7. External Interactive Footer
# ==========================================
footer_text = Text("\nPress Enter to continue...", style=f"bold {COLOR_INDIGO}")

# Render the layout
console.print(main_panel)
console.print(footer_text)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Top metrics panel is never rendered from the main UI path.

render_ui() does not call print_header(), so the metrics panel introduced in this module is effectively dead in the __main__ flow.

Minimal fix
 def render_ui():
+    print_header()
     # ==========================================
     # 2. Main Body Container Content
     # ==========================================
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@agentwatch/cli/ui.py` around lines 66 - 147, The render_ui() function does
not call print_header(), which means the metrics panel is never displayed in the
main UI flow when the application runs. Add a call to print_header() at the
beginning of the render_ui() function, before the main_panel is rendered with
console.print(main_panel), to ensure the metrics panel is properly included in
the output.

Comment thread agentwatch/cli/ui.py
Comment on lines +95 to +96
"https://auth.agentwatch.dev/device?user_code=ABCD-EFGH-IJKL-MNOP-QRST-UVWX-YZ01",
style=COLOR_DIM,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Device auth URL uses a hard-coded user code, which breaks real sign-in.

The login link embeds a static user_code; users will be directed to an invalid/stale code instead of their session-specific code.

Suggested shape
-def render_ui():
+def render_ui(device_auth_url: str):
@@
-    login_url = Text(
-        "https://auth.agentwatch.dev/device?user_code=ABCD-EFGH-IJKL-MNOP-QRST-UVWX-YZ01",
-        style=COLOR_DIM,
-    )
+    login_url = Text(device_auth_url, style=COLOR_DIM)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@agentwatch/cli/ui.py` around lines 95 - 96, The device authentication URL at
line 95 contains a hard-coded user code placeholder instead of the actual
session-specific code, which prevents users from logging in. Replace the static
user code string "ABCD-EFGH-IJKL-MNOP-QRST-UVWX-YZ01" in the auth URL with a
dynamic variable that contains the real user code generated for the current
device authentication session. Ensure this variable is available in the scope
where the URL is being constructed and passes the actual session-specific code
to the user.

@SHAURYASANYAL3

Copy link
Copy Markdown
Contributor Author

Closing in favor of #454 which includes this code to pass CI.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant