From 05d86562ee92d2d714193888298ffeb81fd722eb Mon Sep 17 00:00:00 2001 From: Harivansh Rathi Date: Sun, 14 Dec 2025 16:24:09 -0500 Subject: [PATCH] update to allow claude command access --- .../{add-tests.md => veet-add-tests.md} | 0 .../commands/{explain.md => veet-explain.md} | 0 .../{generate.md => veet-generate.md} | 0 .claude/commands/{hint.md => veet-hint.md} | 0 README.md | 22 +++-- install.sh | 19 +++- veetcode/cli.py | 95 ++++++++++++++++++- 7 files changed, 122 insertions(+), 14 deletions(-) rename .claude/commands/{add-tests.md => veet-add-tests.md} (100%) rename .claude/commands/{explain.md => veet-explain.md} (100%) rename .claude/commands/{generate.md => veet-generate.md} (100%) rename .claude/commands/{hint.md => veet-hint.md} (100%) diff --git a/.claude/commands/add-tests.md b/.claude/commands/veet-add-tests.md similarity index 100% rename from .claude/commands/add-tests.md rename to .claude/commands/veet-add-tests.md diff --git a/.claude/commands/explain.md b/.claude/commands/veet-explain.md similarity index 100% rename from .claude/commands/explain.md rename to .claude/commands/veet-explain.md diff --git a/.claude/commands/generate.md b/.claude/commands/veet-generate.md similarity index 100% rename from .claude/commands/generate.md rename to .claude/commands/veet-generate.md diff --git a/.claude/commands/hint.md b/.claude/commands/veet-hint.md similarity index 100% rename from .claude/commands/hint.md rename to .claude/commands/veet-hint.md diff --git a/README.md b/README.md index 32eb97f..6d1cad9 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,9 @@ veet ```bash git clone https://github.com/harivansh-afk/veet-code.git -cd veetcode +cd veet-code uv sync +./veet install-commands # optional: install Claude slash commands ./veet ``` @@ -49,14 +50,23 @@ uv sync | `q` | Quit | | `Ctrl+P` | Command palette | +## CLI Commands + +```bash +veet # Launch TUI +veet list # List all problems +veet install-commands # Install Claude slash commands +veet path # Show install location +``` + ## Generate Problems -Use Claude Code slash commands in `.claude/commands/`: +Use Claude slash commands (works anywhere after install): -- `/generate` — create a new problem -- `/hint` — get a hint -- `/explain` — explain the solution -- `/add-tests` — add more test cases +- `/veet-generate` — create a new problem +- `/veet-hint` — get a hint +- `/veet-explain` — explain the solution +- `/veet-add-tests` — add more test cases ## Themes diff --git a/install.sh b/install.sh index 17ea125..3c2cafb 100755 --- a/install.sh +++ b/install.sh @@ -3,6 +3,7 @@ set -e REPO="harivansh-afk/veet-code" INSTALL_DIR="$HOME/.veetcode" +CLAUDE_COMMANDS="$HOME/.claude/commands" echo "Installing veetcode..." @@ -25,15 +26,27 @@ fi cd "$INSTALL_DIR" uv sync -# Create symlink +# Create symlink for CLI mkdir -p "$HOME/.local/bin" ln -sf "$INSTALL_DIR/veet" "$HOME/.local/bin/veet" +# Install Claude slash commands +if [ -d "$HOME/.claude" ]; then + echo "Installing Claude slash commands..." + mkdir -p "$CLAUDE_COMMANDS" + for cmd in "$INSTALL_DIR/.claude/commands"/veet-*.md; do + ln -sf "$cmd" "$CLAUDE_COMMANDS/$(basename "$cmd")" + done + echo " ✓ /veet-generate, /veet-hint, /veet-explain, /veet-add-tests" +fi + echo "" echo "✓ veetcode installed!" echo "" -echo "Run: veet" +echo "Commands:" +echo " veet Launch TUI" +echo " veet list List problems" +echo " /veet-generate Generate problem (in Claude)" echo "" echo "Make sure ~/.local/bin is in your PATH:" echo ' export PATH="$HOME/.local/bin:$PATH"' - diff --git a/veetcode/cli.py b/veetcode/cli.py index afc630c..4137f5c 100644 --- a/veetcode/cli.py +++ b/veetcode/cli.py @@ -1,20 +1,105 @@ """CLI entry point for veetcode.""" import typer - -from veetcode.app import run_app +from pathlib import Path app = typer.Typer( name="veetcode", help="Terminal-based LeetCode practice with auto-testing", add_completion=False, + invoke_without_command=True, ) -@app.command() -def main() -> None: +def find_repo_root() -> Path: + """Find veetcode repo root. Prefers current dir, then script location, then ~/.veetcode.""" + candidates = [ + Path.cwd(), + Path(__file__).parent.parent, + Path.home() / ".veetcode", + ] + for p in candidates: + if (p / "problems").exists(): + return p + return Path(__file__).parent.parent + + +@app.callback(invoke_without_command=True) +def main(ctx: typer.Context) -> None: """Launch the Veetcode TUI.""" - run_app() + if ctx.invoked_subcommand is None: + from veetcode.app import run_app + run_app() + + +@app.command() +def list() -> None: + """List all problems.""" + from veetcode.app import scan_problems + + repo = find_repo_root() + problems = scan_problems(repo / "problems") + solved_file = repo / ".solved.json" + + solved: set[str] = set() + if solved_file.exists(): + import json + solved = set(json.loads(solved_file.read_text())) + + if not problems: + typer.echo("No problems found.") + return + + for p in problems: + mark = "✓" if p.name in solved else " " + diff = {"easy": "E", "medium": "M", "hard": "H"}.get(p.difficulty, "?") + typer.echo(f"{mark} [{diff}] {p.name}") + + +@app.command() +def install_commands() -> None: + """Install Claude slash commands to ~/.claude/commands/""" + repo = find_repo_root() + source_dir = repo / ".claude" / "commands" + target_dir = Path.home() / ".claude" / "commands" + + if not source_dir.exists(): + typer.echo(f"Commands not found: {source_dir}") + raise typer.Exit(1) + + target_dir.mkdir(parents=True, exist_ok=True) + + count = 0 + for cmd in source_dir.glob("veet-*.md"): + target = target_dir / cmd.name + if target.exists() or target.is_symlink(): + target.unlink() + target.symlink_to(cmd) + typer.echo(f" ✓ /{cmd.stem}") + count += 1 + + typer.echo(f"\nInstalled {count} commands to {target_dir}") + + +@app.command() +def uninstall_commands() -> None: + """Remove Claude slash commands from ~/.claude/commands/""" + target_dir = Path.home() / ".claude" / "commands" + + count = 0 + for cmd in target_dir.glob("veet-*.md"): + cmd.unlink() + typer.echo(f" ✗ /{cmd.stem}") + count += 1 + + typer.echo(f"\nRemoved {count} commands") + + +@app.command() +def path() -> None: + """Show veetcode installation path.""" + repo = find_repo_root() + typer.echo(repo) if __name__ == "__main__":