55import logging
66from typing import Optional , Tuple
77
8+ from rich .console import Console
9+ from rich .panel import Panel
10+
811from . import __version__
912from .config import (
1013 load_config ,
1114 init_config ,
1215 validate_api_key ,
16+ is_first_run ,
1317 ConfigError ,
1418 PROVIDER_DEFAULTS ,
19+ GROQ_SETUP_INSTRUCTIONS ,
1520)
1621from .reviewer import review_code , ReviewResult
1722from .formatter import print_review , print_error , print_info , console
2631logger = logging .getLogger (__name__ )
2732
2833
34+ # ─── Welcome Message ───
35+
36+ WELCOME_MESSAGE : str = """
37+ [bold bright_blue]🔍 Welcome to codereview![/bold bright_blue]
38+
39+ AI-powered code review in your terminal.
40+
41+ [bold]Quick setup (free, 60 seconds):[/bold]
42+
43+ [dim]1.[/dim] Go to [cyan]https://console.groq.com[/cyan]
44+ [dim]2.[/dim] Sign up with Google or GitHub
45+ [dim]3.[/dim] Click [bold]API Keys[/bold] → [bold]Create API Key[/bold]
46+ [dim]4.[/dim] Run these two commands:
47+
48+ [green]export GROQ_API_KEY="gsk_your_key_here"[/green]
49+ [green]codereview --init groq[/green]
50+
51+ [dim]5.[/dim] Review any file:
52+
53+ [green]codereview app.py[/green]
54+
55+ [dim]To make the key permanent so you don't set it every session:[/dim]
56+
57+ [green]echo 'export GROQ_API_KEY="gsk_your_key_here"' >> ~/.zshrc[/green]
58+ [green]source ~/.zshrc[/green]
59+
60+ [dim]Other providers: --init openai | --init anthropic | --init ollama[/dim]
61+ """
62+
63+
64+ def show_welcome () -> None :
65+ """Display welcome message for first-time users."""
66+ console .print (Panel (
67+ WELCOME_MESSAGE ,
68+ title = "[bold]First Time Setup[/bold]" ,
69+ border_style = "bright_blue" ,
70+ padding = (1 , 2 ),
71+ ))
72+
73+
2974# ─── Argument Parsing ───
3075
3176def build_parser () -> argparse .ArgumentParser :
@@ -49,9 +94,16 @@ def build_parser() -> argparse.ArgumentParser:
4994
5095Providers:
5196 codereview --init openai Set up with OpenAI
52- codereview --init ollama Set up with local Ollama
53- codereview --init groq Set up with Groq (free tier )
97+ codereview --init ollama Set up with local Ollama (free, offline)
98+ codereview --init groq Set up with Groq (free, no credit card )
5499 codereview --init anthropic Set up with Anthropic
100+
101+ Free setup:
102+ 1. Go to https://console.groq.com
103+ 2. Sign up (Google or GitHub)
104+ 3. Create an API key
105+ 4. export GROQ_API_KEY="gsk_your_key_here"
106+ 5. codereview --init groq
55107 """ ,
56108 )
57109
@@ -72,6 +124,11 @@ def build_parser() -> argparse.ArgumentParser:
72124 choices = list (PROVIDER_DEFAULTS .keys ()),
73125 help = "Initialize config for a provider" ,
74126 )
127+ parser .add_argument (
128+ "--setup" ,
129+ action = "store_true" ,
130+ help = "Show setup instructions" ,
131+ )
75132 parser .add_argument (
76133 "--version" ,
77134 action = "version" ,
@@ -95,15 +152,41 @@ def handle_init(provider: str) -> None:
95152 print_error (str (e ))
96153 sys .exit (1 )
97154
98- print_info (f"Config initialized for { provider } " )
99- print_info (f"Model: { config ['model' ]} " )
155+ console .print ()
156+ console .print (f"[bold green]✅ Config initialized for { provider } [/bold green]" )
157+ console .print (f"[dim] Model: { config ['model' ]} [/dim]" )
158+ console .print ()
100159
101160 if provider == "ollama" :
102- print_info ("Make sure Ollama is running: ollama serve" )
161+ console .print ("[bold]Next steps:[/bold]" )
162+ console .print (" 1. Make sure Ollama is running: [green]ollama serve[/green]" )
163+ console .print (" 2. Pull a model: [green]ollama pull llama3[/green]" )
164+ console .print (" 3. Review code: [green]codereview yourfile.py[/green]" )
103165 else :
104166 env_key : str = PROVIDER_DEFAULTS [provider ].get ("env_key" , "" )
105- if env_key :
106- print_info (f"Set your API key: export { env_key } =your-key-here" )
167+ has_key : bool = bool (config .get ("api_key" ))
168+
169+ if has_key :
170+ console .print ("[bold green]✅ API key detected![/bold green]" )
171+ console .print ()
172+ console .print ("[bold]You're ready! Try:[/bold]" )
173+ console .print (" [green]codereview yourfile.py[/green]" )
174+ else :
175+ console .print (f"[bold yellow]⚠️ No API key detected.[/bold yellow]" )
176+ console .print ()
177+ if provider == "groq" :
178+ console .print ("[bold]Get your free key:[/bold]" )
179+ console .print (" 1. Go to [cyan]https://console.groq.com[/cyan]" )
180+ console .print (" 2. Sign up → API Keys → Create API Key" )
181+ console .print (f" 3. Run: [green]export { env_key } =\" gsk_your_key_here\" [/green]" )
182+ console .print ()
183+ console .print ("[dim]To make it permanent:[/dim]" )
184+ console .print (f' [green]echo \' export { env_key } ="gsk_your_key_here"\' >> ~/.zshrc && source ~/.zshrc[/green]' )
185+ else :
186+ console .print (f"[bold]Set your API key:[/bold]" )
187+ console .print (f" [green]export { env_key } =\" your-key-here\" [/green]" )
188+
189+ console .print ()
107190
108191
109192# ─── Git Requirement ───
@@ -287,26 +370,43 @@ def main() -> None:
287370 parser : argparse .ArgumentParser = build_parser ()
288371 args : argparse .Namespace = parser .parse_args ()
289372
373+ # Handle --setup
374+ if args .setup :
375+ show_welcome ()
376+ return
377+
290378 # Handle --init
291379 if args .init :
292380 handle_init (args .init )
293381 return
294382
383+ # First run detection — show welcome if no config and no args
384+ if is_first_run ():
385+ resolved_check : Optional [Tuple [str , str , bool ]] = resolve_code (args ) if (
386+ args .files or args .staged or args .diff or args .last or args .stdin
387+ ) else None
388+
389+ if resolved_check is None :
390+ show_welcome ()
391+ return
392+
295393 # Load and validate config
296394 config : dict = load_config ()
297395 config = apply_overrides (config , args )
298396
299397 try :
300398 validate_api_key (config .get ("api_key" ), config .get ("provider" , "openai" ))
301399 except ConfigError as e :
302- print_error (str (e ))
400+ console . print (str (e ))
303401 sys .exit (1 )
304402
305403 # Resolve code source
306404 resolved : Optional [Tuple [str , str , bool ]] = resolve_code (args )
307405
308406 if resolved is None :
309407 parser .print_help ()
408+ console .print ()
409+ console .print ("[dim]Need help? Run: codereview --setup[/dim]" )
310410 sys .exit (0 )
311411
312412 code , filename , is_diff = resolved
0 commit comments