diff --git a/.gitignore b/.gitignore index a52a9eb..5adc634 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,11 @@ .idea/ +.grok/ .junie/ .claude/ build/ -grokkit *.bak *.log *.tmp .env +*.patch chat_history.json \ No newline at end of file diff --git a/.grok/settings.json b/.grok/settings.json deleted file mode 100644 index a2d9deb..0000000 --- a/.grok/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "model": "grok-code-fast-1" -} \ No newline at end of file diff --git a/.grokkit/recipes/result-refactor.md b/.grokkit/recipes/result-refactor.md new file mode 100644 index 0000000..fb71221 --- /dev/null +++ b/.grokkit/recipes/result-refactor.md @@ -0,0 +1,76 @@ +--- +name: result-refactor +description: Convert traditional Go error handling to Result[T] monadic style +version: 1.0 + +parameters: + package_path: + type: string + default: internal/git + description: Package to refactor + dry_run: + type: bool + default: true + description: If true, only generate patches + +project_languages: + - go + +extensions: + go: + - .go + +search_pattern: "if err != nil" + +allowed_shell_commands: + - go test ./... + - go fmt ./... + - go vet ./... + - rg --files + - git diff --name-only + - jq + +--- + +# Result[T] Refactoring Recipe + +**Overview** +Refactors all error handling in the target package to use the new Result[T] pattern. + +## Execution Steps + +### Step 1: Read-Only Shell: Explore project structure +**Objective:** Get a clear view of the current project layout. +**Instructions:** Use safe read-only shell commands to show the directory tree and key files. +**Expected output:** A tree view and relevant file contents. + +### Step 2: Discover files +**Objective:** Find every file that needs changing. +**Instructions:** Recursively scan `{{.package_path}}` for `.go` files containing `if err != nil`. +**Expected output:** A clean list of full file paths (one per line). If none, say "No files found matching the criteria." + +### Step 3: Refactor each file +**Objective:** Generate the updated code. +**Instructions:** For each file from Step 1: +- Read the full original content. +- Refactor it to use `Result[T]` instead of naked errors (follow existing style, preserve all comments). +- Return **ONLY** a single JSON array in this exact format (no extra text, no markdown): +```json +[ + { + "file": "internal/example.go", + "content": "the complete refactored file here" + } +] +``` + +### Step 4: Apply or patch +**Objective:** +Safely write changes or create reviewable output. +**Instructions:** +- If dry_run is true โ†’ create a unified diff patch file for review. +- If false โ†’ write the new files (backup originals as .bak). +**Expected output:** Confirmation of what was written + full path to any patch file. + +### Final Summary +Give me a concise executive summary: number of files changed, any warnings or patterns you noticed, and your recommended next step. \ No newline at end of file diff --git a/.grokkit/recipes/template-recipe.md b/.grokkit/recipes/template-recipe.md new file mode 100644 index 0000000..db9448b --- /dev/null +++ b/.grokkit/recipes/template-recipe.md @@ -0,0 +1,67 @@ +--- +name: my-awesome-recipe +description: Short description of what this recipe does +version: 1.0 + +parameters: + package_path: + type: string + default: internal + description: Directory or package to operate on + dry_run: + type: bool + default: true + description: If true, only generate a patch + +project_languages: + - go + +extensions: + go: + - .go + +search_pattern: "if err != nil" + +allowed_shell_commands: + - go test ./... + - go fmt ./... + - go vet ./... + +--- + +# My Awesome Recipe + +**Overview** +One-sentence summary of what the whole recipe accomplishes. + +## Execution Steps + +### Step 1: Discover files +**Objective:** Find every file that needs changing. +**Instructions:** Recursively scan `{{.package_path}}` for files containing the search pattern. +**Expected output:** A clean list of full file paths (one per line). If none, say "No files found matching the criteria." + +### Step 2: Do the work +**Objective:** Perform the main task on each discovered file. +**Instructions:** For each file from Step 1: +- Read the full original content. +- Do whatever transformation is needed. +- Return **ONLY** this exact JSON (no extra text, no markdown): + +```json +{ + "file": "path/to/file.ext", + "content": "the complete new file content here" +} +``` +**Expected output:** A JSON array containing one object per file. + +### Step 3: Apply or patch +**Objective:** Safely write changes or create reviewable output. +**Instructions:** +- If dry_run is true โ†’ create a unified diff patch file for review. +- If false โ†’ write the new files (backup originals as .bak). +- Expected output: Confirmation of what was written + full path to any patch file. + +### Final Summary +Give me a concise executive summary: number of files changed, any warnings or patterns you noticed, and your recommended next step. \ No newline at end of file diff --git a/README.md b/README.md index 2ee8fb0..3f170d1 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,21 @@ Grokkit is a fast Go CLI integrating Grok AI with git workflows and general chat [![Go Version](https://img.shields.io/badge/go-1.24.2-blue)]() [![License](https://img.shields.io/badge/license-Unlicense-lightgrey)]() -## ๐Ÿš€ Quick Start +## Requirements +- Go 1.24.2 (for building) +- Git (for git-related commands) +- XAI API key + +## ๐Ÿš€ Quick Start Installation + +### From pre-built release (recommended) +```bash +VERSION=0.1.3 # Replace with latest version tag (omit 'v') +curl -L https://repos.gmgauthier.com/gmgauthier/grokkit/releases/download/v${VERSION}/grokkit-install.sh | VERSION=${VERSION} bash - +``` + +### From Source (for development) ```bash # Set your API key export XAI_API_KEY=sk-... @@ -16,321 +29,23 @@ export XAI_API_KEY=sk-... # Install from source git clone https://repos.gmgauthier.com/gmgauthier/grokkit.git cd grokkit -make install - -# Or build locally +make test make build +make install +```` -# Verify installation -grokkit --help - -### From pre-built release (recommended) -```bash -VERSION=0.1.3 # Replace with latest version tag (omit 'v') -curl -L https://repos.gmgauthier.com/gmgauthier/grokkit/releases/download/v${VERSION}/grokkit-install.sh | VERSION=${VERSION} bash - -``` -Verify: +### Verify: ```bash grokkit version ``` -## ๐Ÿ“‹ Table of Contents - -- [Commands](#commands) - - [chat](#-grokkit-chat) - - [query](#-grokkit-query) - - [edit](#-grokkit-edit-file-instruction) - - [commit / commitmsg](#-grokkit-commitmsg) - - [review](#-grokkit-review) - - [pr-describe](#-grokkit-pr-describe) - - [history](#-grokkit-history) - - [changelog](#-grokkit-changelog) - - [lint](#-grokkit-lint-file) - - [docs](#-grokkit-docs-file) - - [testgen](#-grokkit-testgen) - - [agent](#-grokkit-agent) -- [Configuration](#configuration) -- [Workflows](#workflows) -- [Shell Completions](#shell-completions) -- [Features](#features) -- [Development](#development) -- [Documentation](#documentation) -- [License](#license) - -## Commands - -### ๐Ÿ’ฌ `grokkit chat` -Interactive CLI chat with Grok. Features persistent history across sessions. - -```bash -grokkit chat # Start chat session -grokkit chat -m grok-beta # Use specific model -grokkit chat --debug # Enable debug logging -``` - -**Tips:** -- Type `/quit`, `/q`, or `exit` to exit -- History is saved automatically between sessions -- Use `--debug` to see API request timing - -### ๐Ÿค– `grokkit query` - -One-shot technical question answering. Perfect for quick programming or engineering questions. - -```bash -# Basic usage -grokkit query "How do I sort a slice of structs by a field in Go?" - -# Longer, more detailed answer -grokkit query --wordy "Explain how Go's context package works with cancellation" -``` -Features: - -Default mode is concise, factual, and actionable ---wordy flag gives longer, more explanatory answers -Uses the fast non-reasoning model by default for speed -No persistent history or interactive chat UI - - -### โœ๏ธ `grokkit edit FILE "instruction"` -AI-powered file editing with preview. - -```bash -# Basic usage -grokkit edit main.go "add error handling to all functions" - -# Complex refactoring -grokkit edit server.go "convert this to use context for cancellation" - -# Add features -grokkit edit api.go "add rate limiting middleware" - -# Documentation -grokkit edit utils.go "add detailed docstrings to all exported functions" -``` - -**Safety features:** -- Shows preview with diff-style output -- Requires confirmation before applying -- Uses silent streaming (no console spam) - -### ๐Ÿ“ `grokkit commitmsg` -Generate conventional commit messages from staged changes. - -```bash -git add . -grokkit commitmsg # Generate message only -grokkit commitmsg -m grok-4 # Use specific model -``` - -Output format: `type(scope): subject\n\nbody` - -### โœ… `grokkit commit` -Generate commit message and commit in one step. - -```bash -git add . -grokkit commit # Generate + confirm + commit -``` - -### ๐Ÿ” `grokkit review` -AI code review of staged or unstaged changes. - -```bash -# Review staged changes -git add feature.go -grokkit review - -# Review all changes -grokkit review - -# Get detailed review -grokkit review --debug # See API timing info -``` - -Output includes: -- Summary of changes -- 3-5 actionable improvements -- Potential bugs or issues -- Best practice suggestions - -### ๐Ÿ“‹ `grokkit pr-describe` -Generate comprehensive PR descriptions. - -```bash -# From current branch vs main -grokkit pr-describe - -# With specific model -grokkit pr-describe -m grok-4 -``` - -Output includes: -- Title suggestion -- Summary of changes -- Motivation/context -- Testing notes - -### ๐Ÿ“œ `grokkit history` -Summarize recent git commits. - -```bash -grokkit history # Last 10 commits -``` - -### ๐Ÿ—’๏ธ `grokkit changelog` - -Generate a clean `CHANGELOG.md` section from git history, designed specifically so the output can be pasted directly into Gitea release notes. - -```bash -# 1. Create your version tag first -git tag v0.2.0 - -# 2. Generate preview + write (with safety confirmation) -grokkit changelog - -# 3. Output ONLY the new section (perfect for Gitea "Release notes") -grokkit changelog --stdout - -# 4. Write file + get commit reminder -grokkit changelog --commit -``` - -### ๐Ÿ“– `grokkit docs [file...]` -Generate language-appropriate documentation comments using Grok AI. - -```bash -# Preview and confirm -grokkit docs main.go - -# Auto-apply without confirmation -grokkit docs handlers.go models.go --auto-apply - -# Document multiple files at once -grokkit docs cmd/*.go --auto-apply - -# Use specific model -grokkit docs app.py -m grok-4 -``` - -**Supported doc styles by language:** - -| Language | Style | -|----------|-------| -| Go | godoc (`// FuncName does...`) | -| Python | PEP 257 docstrings (`"""Summary\n\nArgs:..."""`) | -| C / C++ | Doxygen (`/** @brief ... @param ... @return ... */`) | -| JavaScript / TypeScript | JSDoc (`/** @param {type} name ... */`) | -| Rust | rustdoc (`/// Summary\n/// # Arguments`) | -| Ruby | YARD (`# @param [Type] name`) | -| Java | Javadoc (`/** @param ... @return ... */`) | -| Shell | Shell comments (`# function: desc, # Args: ...`) | - -**Safety features:** -- Shows first 50 lines of documented code as preview -- Requires confirmation (unless `--auto-apply`) - -### ๐Ÿงช `grokkit testgen PATHS...` - -**Description**: Generate comprehensive unit tests for Go/Python/C/C++ files using AI. - -**Benefits**: -- Go: Table-driven `t.Parallel()` matching codebase. -- Python: Pytest with `@parametrize`. -- C: Check framework suites. -- C++: Google Test `EXPECT_*`. -- Boosts coverage; safe preview. - -**CLI examples**: -```bash -grokkit testgen internal/grok/client.go -grokkit testgen app.py --yes -grokkit testgen foo.c bar.cpp -``` - -**Safety features**: -- Lang detection via `internal/linter`. -- Unified diff preview. -- Y/N (--yes auto). - -### ๐Ÿค– `grokkit agent` -Multi-file agent for complex refactoring (experimental). - -```bash -grokkit agent "refactor authentication to use JWT" -``` - -### ๐Ÿ”ง `grokkit lint FILE` -Automatically detect language, run linter, and apply AI-suggested fixes. - -```bash -# Just check for issues (no fixes) -grokkit lint main.go --dry-run - -# Interactive fix (preview + confirmation) -grokkit lint app.py - -# Auto-fix without confirmation -grokkit lint server.js --auto-fix - -# Use specific model -grokkit lint script.rb -m grok-4 -``` - -**Supported languages:** -- **Go** (golangci-lint, go vet) -- **Python** (pylint, flake8, ruff) -- **JavaScript/JSX** (eslint) -- **TypeScript/TSX** (eslint, tsc) -- **Rust** (clippy) -- **Ruby** (rubocop) -- **Java** (checkstyle) -- **C/C++** (clang-tidy) -- **Shell** (shellcheck) - -**Safety features:** -- Shows preview of fixes -- Verifies fixes by re-running linter -- Requires confirmation (unless `--auto-fix`) - -## Safety & Change Management - -Grokkit is designed to work seamlessly with Git. Rather than creating redundant `.bak` files, we lean on Git's powerful version control to manage changes and rollbacks. - -### The Safety Workflow - -1. **Preview**: Every command that modifies files (like `edit`, `lint`, `docs`) shows a diff-style preview first. -2. **Confirm**: You must explicitly confirm (`y/N`) before any changes are written to disk. -3. **Git Integration**: Use Git to manage the "pre-staged," "staged," and "committed" degrees of change. - -### Managing Undesired Changes - -If you've applied a change that you don't like, Git makes it easy to roll back: - -- **Unstaged changes**: If you haven't `git add`-ed the changes yet: - ```bash - git restore - ``` -- **Staged changes**: If you've already staged the changes: - ```bash - git restore --staged - git restore - ``` -- **Committed changes**: If you've already committed the changes: - ```bash - git revert HEAD - # or to reset to a previous state: - git reset --hard HEAD~1 - ``` - -By using Git, you have a complete audit trail and multiple levels of undo, ensuring your codebase remains stable even when experimenting with AI-driven refactors. - ## Configuration ### Environment Variables ```bash export XAI_API_KEY=sk-... # Required: Your xAI API key +export XAI_API_KEY=$(vault read -field=key secret/grokkit) # Recommended for secure storage ``` ### Config File (Optional) @@ -351,7 +66,19 @@ fast = "grok-4-1-fast-non-reasoning" history_file = "~/.config/grokkit/chat_history.json" ``` -**See also:** [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for advanced configuration options. +**See also:** [docs/developer-guide/CONFIGURATION.md](docs/developer-guide/CONFIGURATION.md) for advanced configuration options. + + +## ๐Ÿ“– Commands + +See [The User Guide](docs/user-guide/index.md) for complete details on command usage. + +## ๐Ÿ›ก๏ธ Safety & Change Management + +Grokkit is designed to work seamlessly with Git, using version control instead of redundant backup files to manage changes and rollbacks. + +[Read the Safety & Change Management Guide](docs/user-guide/safety.md) + ### Logging @@ -370,121 +97,15 @@ cat ~/.config/grokkit/grokkit.log | jq 'select(.msg=="API request completed") | ## Workflows -### Git Workflow Integration +Common usage patterns to integrate Grokkit into your development cycle. -```bash -# 1. Make changes -vim src/api.go - -# 2. Review with AI -git add src/api.go -grokkit review - -# 3. Fix issues, then commit -git add src/api.go -grokkit commit - -# 4. Generate PR description -grokkit pr-describe -``` - -### Code Refactoring Workflow - -```bash -# 1. Chat to plan approach -grokkit chat -> "How should I refactor this authentication code to use middleware?" - -# 2. Apply changes with edit -grokkit edit auth.go "implement middleware pattern as discussed" - -# 3. Review changes -grokkit review - -# 4. Commit -grokkit commit -``` - -### Debugging Workflow - -```bash -# 1. Describe issue in chat -grokkit chat --debug -> "I'm getting a nil pointer error in handler.go:42" - -# 2. Apply suggested fixes -grokkit edit handler.go "add nil checks before dereferencing user object" - -# 3. Verify and commit -grokkit review -grokkit commit -``` - -### Batch File Editing - -```bash -# Edit multiple files with consistent changes -for file in src/*.go; do - grokkit edit "$file" "add context parameter to all exported functions" -done - -# Review all changes together -grokkit review -``` - -### Code Quality Workflow - -```bash -# 1. Check a file for linting issues -grokkit lint app.py --dry-run - -# 2. Apply AI-suggested fixes with preview -grokkit lint app.py - -# 3. Auto-fix multiple files -for file in src/*.js; do - grokkit lint "$file" --auto-fix -done - -# 4. Review and commit -grokkit review -grokkit commit -``` - -### Documentation Generation Workflow - -```bash -# 1. Preview docs for a single file -grokkit docs internal/api/handler.go - -# 2. Batch-document a package -grokkit docs cmd/*.go --auto-apply - -# 3. Document across languages in one pass -grokkit docs lib/utils.py src/helpers.ts --auto-apply - -# 4. Review and commit -grokkit review -grokkit commit -``` +[Read the Workflows Guide](docs/user-guide/workflows.md) ## Shell Completions Generate shell completions for faster command entry: -```bash -# Bash -grokkit completion bash | sudo tee /etc/bash_completion.d/grokkit - -# Zsh (oh-my-zsh) -grokkit completion zsh > ~/.oh-my-zsh/completions/_grokkit - -# Fish -grokkit completion fish > ~/.config/fish/completions/grokkit.fish - -# PowerShell -grokkit completion powershell | Out-String | Invoke-Expression -``` +[Read the full Completion Guide](docs/user-guide/completion.md) ## Flags @@ -523,6 +144,9 @@ grokkit review -v - โœ… **Git workflow integration** - Commit messages, reviews, PR descriptions - โœ… **Multi-language linting** - 9 languages supported with AI-powered fixes - โœ… **AI documentation generation** - 8 doc styles (godoc, PEP 257, Doxygen, JSDoc, rustdoc, YARD, Javadoc, shell) +- โœ… **AI unit test generation** - Go (table-driven), Python (pytest), C (Check), C++ (GTest) +- โœ… **AI file scaffolding** - Create new files with project-aware style matching +- โœ… **Transactional Recipes** - Markdown-based multi-step AI workflows ### Quality & Testing - โœ… **Test coverage 68%+** - Comprehensive unit tests including all command message builders @@ -556,108 +180,9 @@ grokkit review -v ## Development -```bash -# All tests pass without XAI_API_KEY (unit tests only) +Comprehensive build instructions, project structure details, and the Grokkit development workflow. -# Run tests -make test - -# Agent-specific tests -make test-agent - -# Run tests with coverage report -make test-cover -open build/coverage.html - -# Linting (matches CI, uses .golangci.yml config) -make lint -# Install golangci-lint if needed: -# go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest - -# Run specific tests -go test -run TestEditCommand ./cmd -v - -# Build binary -make build - -# Install locally -make install - -# Clean build artifacts -make clean -``` - -### Project Structure - -``` -grokkit/ -โ”œโ”€โ”€ cmd/ # CLI commands (Cobra) -โ”‚ โ”œโ”€โ”€ docs.go # grokkit docs โ€” AI documentation generation -โ”‚ โ”œโ”€โ”€ lint.go # grokkit lint โ€” AI-powered linting -โ”‚ โ””โ”€โ”€ ... # chat, edit, commit, review, history, pr-describe, agent -โ”œโ”€โ”€ config/ # Viper configuration -โ”œโ”€โ”€ docs/ # Documentation -โ”œโ”€โ”€ todo/ # TODO tracking: queued/ (pending) and completed/ (historical record) -โ”‚ โ”œโ”€โ”€ queued/ # Pending TODO items -โ”‚ โ””โ”€โ”€ completed/ # Completed TODO items with history -โ”œโ”€โ”€ internal/ -โ”‚ โ”œโ”€โ”€ errors/ # Custom error types -โ”‚ โ”œโ”€โ”€ git/ # Git operations -โ”‚ โ”œโ”€โ”€ grok/ # xAI Grok API client -โ”‚ โ”œโ”€โ”€ linter/ # Multi-language linting -โ”‚ โ”œโ”€โ”€ logger/ # Structured slog logging -โ”‚ โ””โ”€โ”€ version/ # Build/version info -โ”œโ”€โ”€ main.go # Application entrypoint -โ”œโ”€โ”€ go.mod # Dependencies -โ”œโ”€โ”€ Makefile # Build automation -โ”œโ”€โ”€ .golangci.yml # Golangci-lint configuration -โ””โ”€โ”€ scripts/ # Install scripts -``` - -### TODO Workflow - -**Policy:** -From now on, the only thing to be committed directly to the `master` branch will be to-do items (.md files in `todo/queued/`). - -**Process:** -1. When deciding to work on a to-do item: create a branch, implement on the branch, submit PR to `master`. -2. After PR merge: move the item to `todo/completed/`. - -**Example workflow:** -```bash -git checkout -b feature/some-todo -# Implement changes, test with make test lint -git add . -git commit -m "feat: implement some-todo" -git push -u origin feature/some-todo -# Create and merge PR to master - -# Post-merge: -git checkout master -git pull -mv "todo/queued/SOME_TODO.md" "todo/completed/SOME_TODO.md" -git add todo/ -git commit -m "chore: complete some-todo" -git push origin master -``` - -### Gitea Actions Automation *(automates post-merge above)* - -[`.gitea/workflows/auto-complete-todo.yml`](.gitea/workflows/auto-complete-todo.yml) triggers on PR `opened`/`synchronize`: - -- Branches `feature/some-todo`: moves `todo/queued/some-todo.md` โ†’ `completed/`. - -**One-time setup** (Gitea โ†’ Repo โ†’ Settings โ†’ Secrets & Variables โ†’ Actions): -- New Secret: `PAT_TOKEN` = [Personal Access Token](https://gitea.example.com/user/settings/tokens) (scope: `repo`). -- Optional: Branch protection โ†’ Require "Auto-complete TODO" status check. - -**Result**: No manual post-merge steps needed! - -## Documentation - -- ๐Ÿ“– [Troubleshooting Guide](docs/TROUBLESHOOTING.md) - Common issues and solutions -- ๐Ÿ—๏ธ [Architecture Overview](docs/ARCHITECTURE.md) - System design and patterns -- โš™๏ธ [Configuration Guide](docs/CONFIGURATION.md) - Advanced configuration options +[Read the Development Overview Guide](docs/developer-guide/overview.md) ## API Usage & Costs @@ -667,11 +192,6 @@ Grokkit uses the xAI Grok API. Be aware: - Streaming reduces perceived latency - Consider using model aliases for different use cases (fast/expensive) -## Requirements - -- Go 1.24.2 (for building) -- Git (for git-related commands) -- XAI API key ## Troubleshooting @@ -690,7 +210,7 @@ Error: Request failed: context deadline exceeded โ†’ Solution: chmod 644 ~/.config/grokkit/grokkit.log ``` -**See [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) for more details.** +**See [docs/developer-guide/TROUBLESHOOTING.md](docs/developer-guide/TROUBLESHOOTING.md) for more details.** ## License diff --git a/cmd/query.go b/cmd/query.go index ca450a5..67942f6 100644 --- a/cmd/query.go +++ b/cmd/query.go @@ -19,7 +19,6 @@ Default mode is factual and brief. Use --wordy for longer, more explanatory answ func init() { queryCmd.Flags().Bool("wordy", false, "Give a longer, more detailed answer") - rootCmd.AddCommand(queryCmd) } func runQuery(cmd *cobra.Command, args []string) { diff --git a/cmd/recipe.go b/cmd/recipe.go new file mode 100644 index 0000000..c54ee5e --- /dev/null +++ b/cmd/recipe.go @@ -0,0 +1,139 @@ +package cmd + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/spf13/cobra" + + "gmgauthier.com/grokkit/config" + "gmgauthier.com/grokkit/internal/grok" + "gmgauthier.com/grokkit/internal/recipe" +) + +var recipeCmd = &cobra.Command{ + Use: "recipe", + Short: "Run a recipe (transactional sous-chef mode)", +} + +var runCmd = &cobra.Command{ + Use: "run [recipe-name|recipe.md]", + Short: "Execute a recipe", + Args: cobra.MinimumNArgs(1), + RunE: runRecipe, +} + +var paramFlags []string + +func init() { + runCmd.Flags().StringSliceVarP(¶mFlags, "param", "p", nil, "key=value parameters for the recipe (can be repeated)") + recipeCmd.AddCommand(runCmd) + rootCmd.AddCommand(recipeCmd) +} + +func runRecipe(cmd *cobra.Command, args []string) error { + nameOrPath := args[0] + + recipePath, err := resolveRecipePath(nameOrPath) + if err != nil { + return err + } + + // Parse --param key=value into map + params := make(map[string]any) + for _, p := range paramFlags { + if kv := strings.SplitN(p, "=", 2); len(kv) == 2 { + key := strings.TrimSpace(kv[0]) + value := strings.TrimSpace(kv[1]) + + // Clean bool handling that satisfies staticcheck + switch strings.ToLower(value) { + case "true", "1", "yes", "on": + params[key] = true + case "false", "0", "no", "off": + params[key] = false + default: + params[key] = value + } + } + } + + r, err := recipe.Load(recipePath, params) + if err != nil { + return fmt.Errorf("failed to load recipe: %w", err) + } + + flagModel, _ := cmd.Flags().GetString("model") + model := config.GetModel("recipe", flagModel) + + client := grok.NewClient() + + runner := recipe.NewRunner(r, client, model) + return runner.Run() +} + +// resolveRecipePath and findProjectRoot stay exactly as you have them +func resolveRecipePath(nameOrPath string) (string, error) { + if strings.Contains(nameOrPath, "/") || strings.HasSuffix(nameOrPath, ".md") { + if _, err := os.Stat(nameOrPath); err == nil { + return nameOrPath, nil + } + return "", fmt.Errorf("recipe file not found: %s", nameOrPath) + } + + if !strings.HasSuffix(nameOrPath, ".md") { + nameOrPath += ".md" + } + + projectRoot, err := findProjectRoot() + if err == nil { + local := filepath.Join(projectRoot, ".grokkit", "recipes", nameOrPath) + if _, err := os.Stat(local); err == nil { + return local, nil + } + } + + global := filepath.Join(os.Getenv("HOME"), ".local", "share", "grokkit", "recipes", nameOrPath) + if _, err := os.Stat(global); err == nil { + fmt.Printf("Recipe %q not found in project.\nFound globally at %s\nUse this one? [y/N] ", nameOrPath, global) + var answer string + if _, err := fmt.Scanln(&answer); err != nil { + return "", err + } + if strings.HasPrefix(strings.ToLower(answer), "y") { + return global, nil + } + return "", fmt.Errorf("user declined global recipe") + } + + return "", fmt.Errorf("recipe %q not found in project or global store", nameOrPath) +} + +func findProjectRoot() (string, error) { + dir, err := os.Getwd() + if err != nil { + return "", err + } + for { + if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil { + return dir, nil + } + if _, err := os.Stat(filepath.Join(dir, ".gitignore")); err == nil { + return dir, nil + } + if _, err := os.Stat(filepath.Join(dir, ".grokkit")); err == nil { + return dir, nil + } + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir, nil + } + parent := filepath.Dir(dir) + if parent == dir { + break + } + dir = parent + } + return "", fmt.Errorf("not in a project") +} diff --git a/docs/ARCHITECTURE.md b/docs/developer-guide/ARCHITECTURE.md similarity index 94% rename from docs/ARCHITECTURE.md rename to docs/developer-guide/ARCHITECTURE.md index 77a23a3..77dfb53 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/developer-guide/ARCHITECTURE.md @@ -16,28 +16,33 @@ This document describes the design principles, architecture patterns, and implem Grokkit follows these core principles: -### 1. **Simplicity First** +### 1. **The Developer Is The Agent** +- The developer is in control of the code, not the LLM. +- The LLM should *enhance the developer experience*, not *replace* it. +- The developer is the one who makes **informed judgments** about the code, not the LLM. + +### 2. **Simplicity First** - Minimal dependencies (stdlib + well-known libs) - Minimal interface surface (CLI commands over TUI interactions) - Clear, readable code over clever solutions - Single responsibility per package -### 2. **Safety by Default** +### 3. **Safety by Default** - Git-based version control for change management - Confirmation prompts for destructive actions - Comprehensive error handling -### 3. **Observability** +### 4. **Observability** - Structured logging for all operations - Request/response timing - Contextual error messages -### 4. **Testability** +### 5. **Testability** - Interface-based design - Dependency injection where needed - Unit tests for pure functions -### 5. **User Experience** +### 6. **User Experience** - Streaming responses for immediate feedback - Persistent history - Shell completions @@ -77,9 +82,13 @@ grokkit/ โ”‚ โ”œโ”€โ”€ logger.go # Logger setup + helpers โ”‚ โ””โ”€โ”€ logger_test.go โ”œโ”€โ”€ docs/ # Documentation -โ”‚ โ”œโ”€โ”€ TROUBLESHOOTING.md -โ”‚ โ”œโ”€โ”€ ARCHITECTURE.md # This file -โ”‚ โ””โ”€โ”€ CONFIGURATION.md +โ”‚ โ””โ”€โ”€ developer-guide/ # Technical documentation +โ”‚ โ”œโ”€โ”€ ARCHITECTURE.md # This file +โ”‚ โ”œโ”€โ”€ CONFIGURATION.md # Configuration guide +โ”‚ โ”œโ”€โ”€ TROUBLESHOOTING.md # Troubleshooting guide +โ”‚ โ””โ”€โ”€ index.md # Developer guide index +โ”‚ โ”œโ”€โ”€ user-guide/ # End-user documentation +โ”‚ โ””โ”€โ”€ index.md # Main documentation index โ”œโ”€โ”€ .gitea/workflows/ # CI/CD โ”‚ โ”œโ”€โ”€ ci.yml # Test + lint + build โ”‚ โ””โ”€โ”€ release.yml # Multi-platform releases diff --git a/docs/CONFIGURATION.md b/docs/developer-guide/CONFIGURATION.md similarity index 100% rename from docs/CONFIGURATION.md rename to docs/developer-guide/CONFIGURATION.md diff --git a/docs/TROUBLESHOOTING.md b/docs/developer-guide/TROUBLESHOOTING.md similarity index 100% rename from docs/TROUBLESHOOTING.md rename to docs/developer-guide/TROUBLESHOOTING.md diff --git a/docs/developer-guide/index.md b/docs/developer-guide/index.md new file mode 100644 index 0000000..ed98b8a --- /dev/null +++ b/docs/developer-guide/index.md @@ -0,0 +1,11 @@ +# Developer Guide + +Welcome to the Grokkit Developer Guide. This section contains resources and guidelines for those who want to contribute to Grokkit's development or understand its internal workings. + +## Resources + +- **[Development Overview](overview.md)** โ€” Build instructions, project structure, and the standard TODO workflow. +- **[Architecture Overview](ARCHITECTURE.md)** โ€” Deep dive into the design principles, project structure, and technical implementation of Grokkit. +- **[Configuration Guide](CONFIGURATION.md)** โ€” Detailed information on how to configure Grokkit via environment variables and config files. +- **[Troubleshooting](TROUBLESHOOTING.md)** โ€” Common issues and their solutions encountered during development or deployment. +- **[Back to Documentation Index](../index.md)** diff --git a/docs/developer-guide/overview.md b/docs/developer-guide/overview.md new file mode 100644 index 0000000..35bcc7e --- /dev/null +++ b/docs/developer-guide/overview.md @@ -0,0 +1,107 @@ +# ๐Ÿ› ๏ธ Development Overview + +This document provides a comprehensive overview of the development process for Grokkit, including build instructions, project structure, and the standard TODO workflow. + +## Development + +```bash +# All tests pass without XAI_API_KEY (unit tests only) + +# Run tests +make test + +# Agent-specific tests +make test-agent + +# Run tests with coverage report +make test-cover +open build/coverage.html + +# Linting (matches CI, uses .golangci.yml config) +make lint +# Install golangci-lint if needed: +# go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +# Run specific tests +go test -run TestEditCommand ./cmd -v + +# Build binary +make build + +# Install locally +make install + +# Clean build artifacts +make clean +``` + +### Project Structure + +``` +grokkit/ +โ”œโ”€โ”€ cmd/ # CLI commands (Cobra) +โ”‚ โ”œโ”€โ”€ docs.go # grokkit docs โ€” AI documentation generation +โ”‚ โ”œโ”€โ”€ lint.go # grokkit lint โ€” AI-powered linting +โ”‚ โ”œโ”€โ”€ recipe.go # grokkit recipe โ€” transactional recipe runner +โ”‚ โ”œโ”€โ”€ scaffold.go # grokkit scaffold โ€” project-aware file generation +โ”‚ โ””โ”€โ”€ ... # chat, edit, commit, review, history, pr-describe, agent +โ”œโ”€โ”€ config/ # Viper configuration +โ”œโ”€โ”€ docs/ # Documentation +โ”œโ”€โ”€ .grokkit/ # Project-local Grokkit data +โ”‚ โ””โ”€โ”€ recipes/ # Custom AI workflows (recipes) +โ”œโ”€โ”€ todo/ # TODO tracking: queued/ (pending) and completed/ (historical record) +โ”‚ โ”œโ”€โ”€ queued/ # Pending TODO items +โ”‚ โ””โ”€โ”€ completed/ # Completed TODO items with history +โ”œโ”€โ”€ internal/ +โ”‚ โ”œโ”€โ”€ errors/ # Custom error types +โ”‚ โ”œโ”€โ”€ git/ # Git operations +โ”‚ โ”œโ”€โ”€ grok/ # xAI Grok API client +โ”‚ โ”œโ”€โ”€ linter/ # Multi-language linting +โ”‚ โ”œโ”€โ”€ logger/ # Structured slog logging +โ”‚ โ”œโ”€โ”€ recipe/ # Recipe loading and execution engine +โ”‚ โ””โ”€โ”€ version/ # Build/version info +โ”œโ”€โ”€ main.go # Application entrypoint +โ”œโ”€โ”€ go.mod # Dependencies +โ”œโ”€โ”€ Makefile # Build automation +โ”œโ”€โ”€ .golangci.yml # Golangci-lint configuration +โ””โ”€โ”€ scripts/ # Install scripts +``` + +## TODO Workflow + +**Policy:** +From now on, the only thing to be committed directly to the `master` branch will be to-do items (.md files in `todo/queued/`). + +**Process:** +1. When deciding to work on a to-do item: create a branch, implement on the branch, submit PR to `master`. +2. After PR merge: move the item to `todo/completed/`. + +**Example workflow:** +```bash +git checkout -b feature/some-todo +# Implement changes, test with make test lint +git add . +git commit -m "feat: implement some-todo" +git push -u origin feature/some-todo +# Create and merge PR to master + +# Post-merge: +git checkout master +git pull +mv "todo/queued/SOME_TODO.md" "todo/completed/SOME_TODO.md" +git add todo/ +git commit -m "chore: complete some-todo" +git push origin master +``` + +### Gitea Actions Automation *(automates post-merge above)* + +[`.gitea/workflows/auto-complete-todo.yml`](../../.gitea/workflows/auto-complete-todo.yml) triggers on PR `opened`/`synchronize`: + +- Branches `feature/some-todo`: moves `todo/queued/some-todo.md` โ†’ `completed/`. + +**One-time setup** (Gitea โ†’ Repo โ†’ Settings โ†’ Secrets & Variables โ†’ Actions): +- New Secret: `PAT_TOKEN` = [Personal Access Token](https://gitea.example.com/user/settings/tokens) (scope: `repo`). +- Optional: Branch protection โ†’ Require "Auto-complete TODO" status check. + +**Result**: No manual post-merge steps needed! diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..803a46b --- /dev/null +++ b/docs/index.md @@ -0,0 +1,24 @@ +# Grokkit Documentation + +Welcome to the Grokkit documentation. Grokkit is a fast, native Go CLI that integrates Grok AI into your daily development and git workflows. + +Whether you're looking for quick answers, AI-powered file editing, or complex multi-step automated workflows, Grokkit provides the tools to enhance your productivity. + +## Table of Contents + +- **[User Guide](user-guide/index.md)** โ€” Comprehensive documentation for all Grokkit commands and features. + - **[Grokkit Workflows](user-guide/workflows.md)** โ€” Learn how to integrate Grokkit into your development cycle effectively. + - **[Safety & Change Management](user-guide/safety.md)** โ€” Learn how Grokkit integrates with Git to keep your codebase stable and safe. + - **[Configuration Guide](developer-guide/CONFIGURATION.md)** โ€” Detailed information on how to configure Grokkit via environment variables and config files. +- **[Developer Guide](developer-guide/index.md)** โ€” Resources and guidelines for contributing to Grokkit development. + - **[Development Overview](developer-guide/overview.md)** โ€” Build instructions, project structure, and the standard TODO workflow. + - **[Architecture Overview](developer-guide/ARCHITECTURE.md)** โ€” Deep dive into the design principles, project structure, and technical implementation of Grokkit. + - **[Troubleshooting](developer-guide/TROUBLESHOOTING.md)** โ€” Common issues and their solutions. + +--- + +## Quick Links + +- [Grokkit Repository](https://repos.gmgauthier.com/gmgauthier/grokkit) +- [Grokkit Releases](https://repos.gmgauthier.com/gmgauthier/grokkit/releases) +- [Main README](../README.md) diff --git a/docs/user-guide/agent.md b/docs/user-guide/agent.md new file mode 100644 index 0000000..99bbee7 --- /dev/null +++ b/docs/user-guide/agent.md @@ -0,0 +1,49 @@ +# ๐Ÿค– Agent Guide + +The `agent` command is a multi-file autonomous agent that allows you to perform complex refactorings or feature implementations across multiple files using natural language instructions. + +> [!WARNING] +> This command is currently experimental. Always ensure you have a clean git state before running the agent. + +### Why use Agent? + +- **Multi-file awareness**: Unlike the `edit` command, the `agent` command scans your project to understand the context and identifies which files need to be changed. +- **Autonomous Planning**: Grok generates a high-level plan for the entire task before proposing any code changes. +- **Interactive Execution**: You review the plan first, then review and approve changes for each file individually or all at once. +- **Project-wide Refactoring**: Ideal for tasks like "refactor authentication to use JWT" or "add a new field to the User struct across all layers". + +### Usage + +Multi-file agent for complex refactoring (experimental). + +```bash +grokkit agent "refactor authentication to use JWT" +``` + +### Options + +| Flag | Description | +|------|-------------| +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### Workflow + +1. **Project Scan**: The agent scans the current directory for relevant files (currently focused on `.go` files). +2. **Plan Generation**: Grok analyzes your instruction and the file list to create a step-by-step plan. +3. **Plan Review**: You review the proposed plan and decide whether to proceed. +4. **Iterative Editing**: + - For each file in the plan, Grok generates the updated content. + - You see a diff-style preview of the proposed changes for that specific file. + - You can choose to: + - `y`: Apply changes to this file and move to the next. + - `n`: Skip changes for this file and move to the next. + - `a`: Apply changes to this file and all remaining files in the plan without further confirmation. +5. **Completion**: Once all files are processed, the agent provides a summary of the actions taken. + +### Safety & Best Practices + +- **Clean Git State**: Always run the agent on a clean git branch. This allows you to easily `git reset --hard` or `git restore` if the AI makes undesired changes. +- **Review the Plan**: Pay close attention to the initial plan. If it seems off, abort and try again with a more specific instruction. +- **Incremental Approval**: For complex tasks, approve files one by one (`y`) rather than using the "apply all" (`a`) option. +- **Verify Results**: After the agent finishes, run your tests (`make test`) and linter (`make lint`) to ensure the changes are correct and follow project standards. +- **Specific Instructions**: Provide as much context as possible in your instruction to help the agent understand the scope of the change. diff --git a/docs/user-guide/changelog.md b/docs/user-guide/changelog.md new file mode 100644 index 0000000..8d42209 --- /dev/null +++ b/docs/user-guide/changelog.md @@ -0,0 +1,51 @@ +# ๐Ÿ—’๏ธ Changelog Guide + +The `changelog` command automatically generates a `CHANGELOG.md` section based on your git history. It's designed to create professional, categorized changelogs that can be used directly for releases. + +### Key Features + +- **Categorized Changes**: Automatically groups commits into `Added`, `Changed`, and `Fixed`. +- **Gitea Compatible**: The output is formatted for easy pasting into Gitea release notes. +- **Project Maintenance**: Automatically updates your existing `CHANGELOG.md` file. +- **Smart Summaries**: Grok creates concise, imperative bullet points for each change. + +### Usage + +Generate a clean `CHANGELOG.md` section from git history, designed specifically so the output can be pasted directly into Gitea release notes. + +```bash +# 1. Create your version tag first +git tag v0.2.0 + +# 2. Generate preview + write (with safety confirmation) +grokkit changelog + +# 3. Output ONLY the new section (perfect for Gitea "Release notes") +grokkit changelog --stdout + +# 4. Write file + get commit reminder +grokkit changelog --commit +``` + +### Options + +| Flag | Description | +|------|-------------| +| `--since` | Start from this tag/ref (default: previous tag) | +| `--version`, `-V` | Override the version number for the header (default: latest git tag) | +| `--stdout` | Print ONLY the new section (useful for pasting into release notes) | +| `--commit` | Reminds you to commit the changes after updating the file | +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### How it Works + +1. **History Retrieval**: Grokkit finds the commits since the last tag. +2. **Categorization**: It sends the commit history to Grok to be categorized and summarized. +3. **Markdown Generation**: Grok returns a formatted markdown section. +4. **File Update**: Grokkit prepends the new section to your `CHANGELOG.md` or creates it if it doesn't exist. + +### Best Practices + +- **Conventional Commits**: Use conventional commit messages to help the AI categorize changes more accurately. +- **Use tags**: Ensure your project uses git tags so Grokkit can correctly identify the changes since the last version. +- **Review before writing**: Always review the proposed changelog update before confirming. diff --git a/docs/user-guide/chat.md b/docs/user-guide/chat.md new file mode 100644 index 0000000..47e6f40 --- /dev/null +++ b/docs/user-guide/chat.md @@ -0,0 +1,45 @@ +# ๐Ÿ’ฌ Chat Guide + +The `chat` command starts a full interactive session with Grok. Unlike other commands that are one-shot, `chat` maintains a conversation history, allowing for multi-turn dialogues and context-aware responses. + +### Key Features + +- **Interactive**: Real-time conversation with Grok. +- **Streaming**: Responses are streamed to your terminal as they are generated. +- **History**: Grokkit automatically saves and reloads your chat history from `~/.config/grokkit/chat_history.json`. +- **System Prompt**: Grok is configured with a project-aware system prompt to provide relevant answers. + +### Usage + +```bash +grokkit chat # Start chat session +grokkit chat -m grok-beta # Use specific model +grokkit chat --debug # Enable debug logging +``` + +### Tips + +- Type `/quit`, `/q`, or `exit` to exit +- History is saved automatically between sessions +- Use `--debug` to see API request timing + +### Commands within Chat + +- `/quit` or `/q`: Exit the chat session. +- `exit`: Exit the chat session. +- `Ctrl+C`: Exit the chat session. + +### Options + +| Flag | Description | +|------|-------------| +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### Configuration + +You can configure the location of the history file in your `config.toml`: + +```toml +[chat] +history_file = "~/.config/grokkit/my_custom_history.json" +``` diff --git a/docs/user-guide/commit-msg.md b/docs/user-guide/commit-msg.md new file mode 100644 index 0000000..35d814e --- /dev/null +++ b/docs/user-guide/commit-msg.md @@ -0,0 +1,62 @@ +# ๐Ÿ“ Commit Message Guide + +The `commit-msg` command generates a conventional commit message based on your currently staged changes. Unlike the `commit` command, it only outputs the suggested message without actually performing the git commit. + +### Why use Commit Message? + +- **Consistency**: Automatically generate messages following the [Conventional Commits](https://www.conventionalcommits.org/) specification (e.g., `feat(api): add JWT authentication`). +- **Convenience**: Quickly get a descriptive summary of your changes without manually reviewing the diff. +- **Workflow flexibility**: Useful when you want to review, edit, or use the generated message in a custom git command or GUI. + +### Basic Usage + +```bash +git add . +grokkit commit-msg # Generate message only +grokkit commit-msg -m grok-4 # Use specific model +``` + +**Output format:** `type(scope): subject\n\nbody` + +### Options + +| Flag | Description | +|------|-------------| +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### How it Works + +1. **Diff Retrieval**: Grokkit runs `git diff --cached --no-color` to get all staged changes. +2. **AI Analysis**: It sends the diff to Grok with instructions to generate a conventional commit message. +3. **Streaming Output**: The generated message is streamed directly to your terminal. + +### Workflow Example + +1. Stage your changes: + ```bash + git add main.go internal/grok/client.go + ``` +2. Generate the message: + ```bash + grokkit commit-msg + ``` +3. Use the output to commit: + ```bash + git commit -m "$(grokkit commit-msg)" + ``` + +### Comparison with `commit` command + +| Feature | `commit-msg` | `commit` | +|---------|--------------|----------| +| Generates AI message | Yes | Yes | +| Shows diff-based summary | Yes | Yes | +| Asks for confirmation | No | Yes | +| Performs `git commit` | No | Yes | +| Use case | Scripting / Manual control | Interactive git workflow | + +### Best Practices + +- **Stage only related changes**: To get the most accurate commit message, stage only the changes that belong to a single logical unit of work. +- **Review the output**: AI-generated messages are usually good but may need minor tweaks for complex changes. +- **Model Choice**: Use a reasoning model (`grok-4`) for complex architectural changes to get more detailed body descriptions in the commit message. diff --git a/docs/user-guide/commit.md b/docs/user-guide/commit.md new file mode 100644 index 0000000..aafaed8 --- /dev/null +++ b/docs/user-guide/commit.md @@ -0,0 +1,58 @@ +# โœ… Commit Guide + +Grokkit provides two commands to help you generate high-quality, conventional commit messages from your staged changes: `commit-msg` and `commit`. + +### Commit-msg + +The `commit-msg` command generates a conventional commit message based on your currently staged changes (`git add`). It's perfect for when you want to review the message before using it in your commit. + +#### Usage + +```bash +git add . +grokkit commit-msg +``` + +**Output Example:** +```text +feat(git): add support for custom commit message templates + +Implemented a new system for defining custom templates for commit messages, allowing for project-specific conventions. +``` + +### Commit + +The `commit` command generates a commit message and commits in one step. + +#### Usage + +```bash +git add . +grokkit commit # Generate + confirm + commit +``` + +**Interactive Workflow:** +1. Grokkit analyzes your staged changes. +2. It generates a conventional commit message. +3. It shows you the proposed message. +4. It asks for confirmation: `Commit with this message? (y/n): `. +5. If you confirm, it runs `git commit -m ""`. + +### Why use AI for Commits? + +- **Conventional Format**: Automatically follows the `type(scope): subject` format. +- **Accurate Descriptions**: Grok analyzes the actual diff to provide a meaningful summary of your changes. +- **Consistency**: Ensures that all commit messages in your project follow the same high standard. +- **Save Time**: No more staring at a blank screen trying to remember everything you changed. + +### Options + +| Flag | Description | +|------|-------------| +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### Best Practices + +- **Stage only relevant changes**: For the best commit message, only stage the changes that belong in a single commit. +- **Review before committing**: Always read the generated message to ensure it accurately reflects your intent. +- **Model selection**: For complex changes, use a more powerful model like `grok-4` to get a better summary. diff --git a/docs/user-guide/completion.md b/docs/user-guide/completion.md new file mode 100644 index 0000000..a6617d1 --- /dev/null +++ b/docs/user-guide/completion.md @@ -0,0 +1,42 @@ +# Completion Guide + +The `completion` command generates shell completion scripts for Grokkit, making it faster and easier to use the CLI by providing tab-completion for commands and flags. + +### Supported Shells + +- **Bash** +- **Zsh** +- **Fish** +- **PowerShell** + +### Installation + +To enable completions, you need to generate the script for your shell and source it. + +#### Bash + +```bash +grokkit completion bash | sudo tee /etc/bash_completion.d/grokkit +``` + +#### Zsh (oh-my-zsh) + +```zsh +grokkit completion zsh > ~/.oh-my-zsh/completions/_grokkit +``` + +#### Fish + +```fish +grokkit completion fish > ~/.config/fish/completions/grokkit.fish +``` + +#### PowerShell + +```powershell +grokkit completion powershell | Out-String | Invoke-Expression +``` + +### Usage + +Once installed, you can simply type `grokkit ` followed by `Tab` to see available commands, or `grokkit --` followed by `Tab` to see available flags. diff --git a/docs/user-guide/docs.md b/docs/user-guide/docs.md new file mode 100644 index 0000000..341d1d4 --- /dev/null +++ b/docs/user-guide/docs.md @@ -0,0 +1,60 @@ +# ๐Ÿ“– Docs Guide + +The `docs` command uses AI to generate language-appropriate documentation comments for your source files. It supports a wide range of programming languages and documentation styles. + +### Usage + +Generate language-appropriate documentation comments using Grok AI. + +```bash +# Preview and confirm +grokkit docs main.go + +# Auto-apply without confirmation +grokkit docs handlers.go models.go --auto-apply + +# Document multiple files at once +grokkit docs cmd/*.go --auto-apply + +# Use specific model +grokkit docs app.py -m grok-4 +``` + +### Supported doc styles by language + +| Language | Style | +|----------|-------| +| Go | godoc (`// FuncName does...`) | +| Python | PEP 257 docstrings (`"""Summary\n\nArgs:..."""`) | +| C / C++ | Doxygen (`/** @brief ... @param ... @return ... */`) | +| JavaScript / TypeScript | JSDoc (`/** @param {type} name ... */`) | +| Rust | rustdoc (`/// Summary\n/// # Arguments`) | +| Ruby | YARD (`# @param [Type] name`) | +| Java | Javadoc (`/** @param ... @return ... */`) | +| Shell | Shell comments (`# function: desc, # Args: ...`) | + +### Safety features + +- Shows first 50 lines of documented code as preview +- Requires confirmation (unless `--auto-apply`) + +### Options + +| Flag | Description | +|------|-------------| +| `--auto-apply` | Apply documentation without confirmation | +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### How it Works + +1. **Language Detection**: Grokkit detects the language of each file to select the appropriate documentation style. +2. **Contextual Analysis**: It reads the file and prepares a prompt for Grok. +3. **AI Generation**: Grok generates the documentation comments for all public functions, methods, and types. +4. **Interactive Preview**: Grokkit shows you a preview of the documented code. +5. **Confirmation**: You review and confirm before the changes are applied to your file (unless you use `--auto-apply`). + +### Best Practices + +- **Document public APIs**: Use `docs` to ensure your project's public interface is well-documented. +- **Review for Accuracy**: Always read the generated documentation to ensure it accurately reflects the function's purpose and behavior. +- **Use for complex code**: For particularly complex functions, AI-generated documentation can be very helpful for clarifying logic. diff --git a/docs/user-guide/edit.md b/docs/user-guide/edit.md new file mode 100644 index 0000000..b364aa6 --- /dev/null +++ b/docs/user-guide/edit.md @@ -0,0 +1,53 @@ +# โœ๏ธ Edit Guide + +The `edit` command allows you to modify an existing file in-place using natural language instructions. It's a quick and efficient way to refactor code, fix bugs, or add features without manually editing the file. + +### Why use Edit? + +- **Natural Language**: Just tell Grok what you want to change (e.g., "Add a new parameter to the `NewClient` function"). +- **Interactive Preview**: See the proposed changes in a unified diff format before they are applied. +- **Refactoring made easy**: Effortlessly refactor large functions or rewrite entire blocks of code. +- **Cleanup**: `edit` automatically removes unnecessary comments, last modified timestamps, and ownership headers for a cleaner codebase. + +### Basic Usage + +```bash +# Basic usage +grokkit edit main.go "add error handling to all functions" + +# Complex refactoring +grokkit edit server.go "convert this to use context for cancellation" + +# Add features +grokkit edit api.go "add rate limiting middleware" + +# Documentation +grokkit edit utils.go "add detailed docstrings to all exported functions" +``` + +### Safety Features + +- **Diff-style Preview**: Shows exactly what will change. +- **Confirmation Required**: Nothing is written without your `y/N`. +- **Silent Streaming**: No console spam while waiting. + +### Options + +| Flag | Description | +|------|-------------| +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### How it Works + +1. **File Retrieval**: Grokkit reads the content of the target file. +2. **Contextual Analysis**: It prepares a prompt for Grok with the original file content and your instructions. +3. **AI Generation**: Grok processes the request and returns the updated file content. +4. **Interactive Preview**: Grokkit shows you a preview of the changes in a unified diff format. +5. **Confirmation**: You review the changes and confirm before the file is overwritten. + +### Best Practices + +- **Specific Instructions**: The more specific you are, the better the result. Instead of "Fix the bug", try "Fix the race condition in the `UpdateState` method". +- **Review carefully**: Always review the diff before applying changes, especially for complex refactors. +- **Git workflow**: Commit your changes before using `edit` so you can easily revert if you're not happy with the result. +- **Combine with Lint**: After editing, run `grokkit lint` to ensure the new code meets your project's standards. diff --git a/docs/user-guide/history.md b/docs/user-guide/history.md new file mode 100644 index 0000000..5a348a7 --- /dev/null +++ b/docs/user-guide/history.md @@ -0,0 +1,33 @@ +# ๐Ÿ“œ History Guide + +The `history` command provides a concise, AI-generated summary of your recent git history. It analyzes the last 10 commits to give you a high-level overview of recent developments. + +### Key Features + +- **Quick Summaries**: Get a quick catch-up on what's been happening in the repo. +- **AI-Powered Analysis**: Grok translates individual commit messages into 3-5 high-level bullet points. +- **Fast and Efficient**: A one-shot command for immediate results. + +### Usage + +```bash +grokkit history # Last 10 commits +``` + +### Options + +| Flag | Description | +|------|-------------| +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### How it Works + +1. **Commit Log**: Grokkit runs `git log --oneline -10` to get the 10 most recent commits. +2. **AI Analysis**: It sends this log to Grok with a prompt to summarize the history. +3. **Bullet Point Summary**: Grok returns a 3-5 point summary of the most important changes. + +### When to use History + +- **Catching up**: Use `history` after pulling from the remote to see what's changed. +- **Branch review**: Use it to quickly recall what you've worked on recently. +- **Project overview**: Great for getting a quick status update on a project you haven't touched in a few days. diff --git a/docs/user-guide/index.md b/docs/user-guide/index.md new file mode 100644 index 0000000..5c503b7 --- /dev/null +++ b/docs/user-guide/index.md @@ -0,0 +1,52 @@ +# Grokkit User's Guide + +Welcome to the full user documentation for **Grokkit** โ€” a fast, native Go CLI for Grok that supercharges your coding workflow. + +## Quick Navigation + +### ๐Ÿ›ก๏ธ Safety & Change Management +- **[Safety & Change Management](safety.md)** โ€” Learn how Grokkit integrates with Git to keep your codebase stable and safe. + +### ๐Ÿ”„ Workflows +- **[Grokkit Workflows](workflows.md)** โ€” Learn how to integrate Grokkit into your development cycle effectively. + +### Core Commands +- **[๐Ÿ‘จโ€๐Ÿณ Recipe](recipe.md)** โ€” The star of the show. Run powerful, transactional, multi-step LLM workflows defined in simple markdown files. +- **[๐Ÿค– Agent](agent.md)** โ€” Multi-file agent for complex refactorings and project-wide changes. +- **[๐Ÿ—๏ธ Scaffold](scaffold.md)** โ€” Safely generate new files with Grok preview + confirmation. +- **[๐Ÿงช Testgen](testgen.md)** โ€” Generate high-quality unit tests for Go, Python, C/C++, etc. +- **[โœ๏ธ Edit](edit.md)** โ€” In-place file editing with Grok (safe preview mode). + +### Git Workflow Commands +- **[โœ… Commit](commit.md)** โ€” AI-powered conventional commit messages with direct git commit. +- **[๐Ÿ“ Commit-Msg](commit-msg.md)** โ€” Generate AI-suggested conventional commit messages. +- **[๐Ÿ—’๏ธ Changelog](changelog.md)** โ€” Generate CHANGELOG.md from git history. +- **[๐Ÿ“‹ PR-Describe](pr-describe.md)** โ€” Generate full PR descriptions. +- **[๐Ÿ“œ History](history.md)** โ€” Summarize recent git history. + +### Other Useful Commands +- **[๐Ÿ’ฌ Chat](chat.md)** โ€” Full interactive chat with history and streaming +- **[๐Ÿค– Query](query.md)** โ€” One-shot programming-focused queries +- **[๐Ÿ” Review](review.md)** โ€” AI code review of the current repo/directory +- **[๐Ÿ”ง Lint](lint.md)** โ€” Lint + AI-suggested fixes +- **[๐Ÿ“– Docs](docs.md)** โ€” Generate documentation comments +- **[Completion](completion.md)** โ€” Generate shell completion scripts +- **[๐Ÿท๏ธ Version](version.md)** โ€” Print version information + +--- + +## Getting Started + +See the [main README](../README.md) for installation and basic usage. + +See the [Configuration Guide](../developer-guide/CONFIGURATION.md) for detailed information on how to configure Grokkit via environment variables and config files. + +Want to dive deep? Start with the **[Recipe Guide](recipe.md)** โ€” it's the most powerful and unique feature of Grokkit. + +--- + +## Contributing to the Docs + +Found something missing or unclear? Feel free to open a PR or issue on the repo. + +Happy hacking! \ No newline at end of file diff --git a/docs/user-guide/lint.md b/docs/user-guide/lint.md new file mode 100644 index 0000000..20b78f4 --- /dev/null +++ b/docs/user-guide/lint.md @@ -0,0 +1,52 @@ +# ๐Ÿ”ง Lint Guide + +The `lint` command is an AI-powered linter that identifies issues in your code and optionally provides AI-suggested fixes. It's designed to work with multiple languages and provide actionable suggestions. + +### Key Features + +- **Multi-language Support**: Automatically detects and lints Go, Python, C/C++, JS/TS, Rust, and more. +- **AI-Suggested Fixes**: Not only finds issues but can also suggest how to fix them. +- **Interactive Preview**: See the proposed fixes in a diff format before applying them. +- **Clean Code**: Grok is instructed to provide minimal, idiomatic fixes that match your project's style. + +### Usage + +Automatically detect language, run linter, and apply AI-suggested fixes. + +```bash +# Just check for issues (no fixes) +grokkit lint main.go --dry-run + +# Interactive fix (preview + confirmation) +grokkit lint app.py + +# Auto-fix without confirmation +grokkit lint server.js --auto-fix + +# Use specific model +grokkit lint script.rb -m grok-4 +``` + +### Supported languages + +- **Go** (golangci-lint, go vet) +- **Python** (pylint, flake8, ruff) +- **JavaScript/JSX** (eslint) +- **TypeScript/TSX** (eslint, tsc) +- **Rust** (clippy) +- **Ruby** (rubocop) +- **Java** (checkstyle) +- **C/C++** (clang-tidy) +- **Shell** (shellcheck) + +### Safety features + +- Shows preview of fixes +- Verifies fixes by re-running linter +- Requires confirmation (unless `--auto-fix`) + +### Best Practices + +- **Lint early and often**: Catching issues early is much easier than fixing them later. +- **Review fixes carefully**: AI-suggested fixes are usually excellent, but always review them to ensure they align with your project's specific requirements. +- **Combine with Review**: Use `lint` for basic issues and `grokkit review` for deeper logic analysis. diff --git a/docs/user-guide/pr-describe.md b/docs/user-guide/pr-describe.md new file mode 100644 index 0000000..c5ddf45 --- /dev/null +++ b/docs/user-guide/pr-describe.md @@ -0,0 +1,49 @@ +# ๐Ÿ“‹ PR-Describe Guide + +The `pr-describe` command generates a professional Pull Request title and a detailed body by analyzing the diff between your current branch and a base branch. + +### Key Features + +- **Automated PR Descriptions**: Saves time by drafting the entire PR description for you. +- **Context-Aware**: Analyzes every change on your branch to explain the "what" and "why." +- **Professional Format**: Includes sections for changes, motivation, and testing notes. +- **Customizable Base**: Compare against any branch (defaults to `master`). + +### Usage + +```bash +# From current branch vs master +grokkit pr-describe + +# Compare against a specific base branch +grokkit pr-describe --base main + +# With specific model +grokkit pr-describe -m grok-4 +``` + +**Output includes:** +- Title suggestion +- Summary of changes +- Motivation/context +- Testing notes + +### Options + +| Flag | Description | +|------|-------------| +| `--base`, `-b` | Base branch to compare against (default: `master`) | +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### How it Works + +1. **Diff Generation**: Grokkit runs `git diff ..HEAD` to identify all changes on your current branch. +2. **AI Analysis**: It sends the full diff to Grok with a specialized prompt for PR generation. +3. **Structured Output**: Grok returns a professional PR title and body. +4. **Streaming Results**: You see the description as it's being generated. + +### Best Practices + +- **Keep branches focused**: PR descriptions are most effective when the branch addresses a single feature or fix. +- **Review and edit**: Use the AI-generated description as a strong starting point, then add any specific internal context or links (e.g., Jira tickets). +- **Model selection**: For large PRs with many changes, use a more powerful model like `grok-4` for a better high-level summary. diff --git a/docs/user-guide/query.md b/docs/user-guide/query.md new file mode 100644 index 0000000..ffefb16 --- /dev/null +++ b/docs/user-guide/query.md @@ -0,0 +1,38 @@ +# ๐Ÿค– Query Guide + +The `query` command is a one-shot, non-interactive interface for asking Grok programming-focused questions. It's ideal for quick inquiries where you don't need a full chat history. + +### Why use Query? + +- **Fast**: Get a direct answer to a single question. +- **Minimalist**: No chat history or context overhead. +- **Focused**: Perfect for "How do I do X in Go?" or "Explain this regex." + +### Usage + +```bash +# Basic usage +grokkit query "How do I sort a slice of structs by a field in Go?" + +# Longer, more detailed answer +grokkit query --wordy "Explain how Go's context package works with cancellation" +``` + +### Features + +- **Default mode** is concise, factual, and actionable. +- **`--wordy` flag** gives longer, more explanatory answers. +- **Fast model** used by default for speed (non-reasoning). +- **No persistent history** or interactive chat UI. + +### Options + +| Flag | Description | +|------|-------------| +| `--wordy` | Give a longer, more detailed answer | +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### When to use Query vs. Chat + +- Use **Query** for simple, independent questions that don't require follow-up. +- Use **Chat** when you need to have a back-and-forth conversation or want Grok to remember previous context. diff --git a/docs/user-guide/recipe.md b/docs/user-guide/recipe.md new file mode 100644 index 0000000..aed64a5 --- /dev/null +++ b/docs/user-guide/recipe.md @@ -0,0 +1,102 @@ +# ๐Ÿ‘จโ€๐Ÿณ Recipe Guide + +The `recipe` command is the most powerful feature in Grokkit. It lets you define sophisticated, multi-step, transactional workflows that Grok executes step-by-step with full transparency and user approval. + +### What is a Recipe? + +A recipe is a plain markdown file (`.md`) that lives in: +- `.grokkit/recipes/` (project-local, preferred) +- `~/.local/share/grokkit/recipes/` (global) + +Each recipe contains: +- YAML frontmatter (metadata + parameters) +- Clear, numbered steps written in natural language +- Optional final summary + +### Usage + +Execute transactional "recipes" for complex, multi-step AI workflows. + +```bash +# Run a project-local recipe +grokkit recipe run result-refactor + +# Pass parameters to the recipe +grokkit recipe run result-refactor -p package_path=internal/git -p dry_run=false + +# Run a specific recipe file +grokkit recipe run ./my-custom-recipe.md +``` + +### Recipe System + +- **Local Recipes**: Stored in `.grokkit/recipes/*.md`. +- **Global Recipes**: Stored in `~/.local/share/grokkit/recipes/*.md`. +- Recipes are **markdown-based** with YAML frontmatter for parameters and configuration. + +### Anatomy of a Recipe + +```markdown +--- +name: result-refactor +description: Convert naked errors to Result[T] pattern +version: 1.0 + +parameters: + package_path: + type: string + default: internal + description: Package to refactor + +project_languages: + - go + +extensions: + go: + - .go + +search_pattern: "if err != nil" + +allowed_shell_commands: + - go test + - go vet +--- + +# Result[T] Refactoring + +**Overview** +Converts traditional Go error handling to the modern Result[T] monadic style. + +## Execution Steps + +### Step 1: Discover files +**Objective:** Find files that need refactoring. +**Instructions:** Recursively scan `{{.package_path}}`... +**Expected output:** Clean list of full file paths. + +### Step 2: Read-Only Shell: Explore project structure +**Objective:** Get additional context if needed. +**Instructions:** Use safe read-only commands... + +### Step 3: Refactor each file +... + +### Step 4: Apply or patch +... +``` + +### Key Features + +* Parameters โ€” override with --param key=value +* Read-only shell access โ€” use steps titled "Read-Only Shell..." for safe ls, cat, tree, find, rg, jq, etc. +* User confirmation โ€” you approve every shell command +* Dry-run safety โ€” most recipes support dry_run=true by default +* Transactional โ€” you see every step and can stop at any time + +### Best Practices + +* Keep recipes focused (one clear goal) +* Use "Read-Only Shell" steps when the LLM needs context +* Always include a good search_pattern for discovery +* Document expected output clearly in each step + diff --git a/docs/user-guide/review.md b/docs/user-guide/review.md new file mode 100644 index 0000000..ae40972 --- /dev/null +++ b/docs/user-guide/review.md @@ -0,0 +1,48 @@ +# ๐Ÿ” Review Guide + +The `review` command provides an AI-powered code review of your current repository or a specific directory. It analyzes your changes (git diff) and repository status to provide meaningful feedback. + +### Key Features + +- **Automated Code Review**: Get an instant review of your changes without waiting for a teammate. +- **Context-Aware**: Analyzes your staged and unstaged changes using `git diff` and `git status`. +- **Actionable Feedback**: Provides a concise summary and 3-5 specific, actionable improvements. + +### Usage + +```bash +# Review staged changes +git add feature.go +grokkit review + +# Review all changes +grokkit review + +# Get detailed review +grokkit review --debug # See API timing info +``` + +**Output includes:** +- Summary of changes +- 3-5 actionable improvements +- Potential bugs or issues +- Best practice suggestions + +### Options + +| Flag | Description | +|------|-------------| +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### How it Works + +1. **Change Analysis**: Grokkit runs `git status` and `git diff` to see what you've changed. +2. **Review Request**: It sends these changes to Grok with a specialized code review prompt. +3. **AI Evaluation**: Grok reviews the code for logic errors, style issues, and potential bugs. +4. **Summary and Tips**: You get a high-level summary and specific suggestions for improvement. + +### Best Practices + +- **Review small diffs**: For the most focused and useful feedback, run `review` frequently on smaller sets of changes. +- **Combine with Lint**: Run `grokkit lint` first to catch basic syntax and style issues, then use `review` for deeper logic analysis. +- **Model selection**: More complex changes may benefit from the deeper reasoning capabilities of `grok-4`. diff --git a/docs/user-guide/safety.md b/docs/user-guide/safety.md new file mode 100644 index 0000000..f2bd3ad --- /dev/null +++ b/docs/user-guide/safety.md @@ -0,0 +1,31 @@ +# ๐Ÿ›ก๏ธ Safety & Change Management + +Grokkit is designed to work seamlessly with Git. Rather than creating redundant `.bak` files, we lean on Git's powerful version control to manage changes and rollbacks. + +## The Safety Workflow + +1. **Preview**: Every command that modifies files (like `edit`, `lint`, `docs`) shows a diff-style preview first. +2. **Confirm**: You must explicitly confirm (`y/N`) before any changes are written to disk. +3. **Git Integration**: Use Git to manage the "pre-staged," "staged," and "committed" degrees of change. + +## Managing Undesired Changes + +If you've applied a change that you don't like, Git makes it easy to roll back: + +- **Unstaged changes**: If you haven't `git add`-ed the changes yet: + ```bash + git restore + ``` +- **Staged changes**: If you've already staged the changes: + ```bash + git restore --staged + git restore + ``` +- **Committed changes**: If you've already committed the changes: + ```bash + git revert HEAD + # or to reset to a previous state: + git reset --hard HEAD~1 + ``` + +By using Git, you have a complete audit trail and multiple levels of undo, ensuring your codebase remains stable even when experimenting with AI-driven refactors. diff --git a/docs/user-guide/scaffold.md b/docs/user-guide/scaffold.md new file mode 100644 index 0000000..7b92d62 --- /dev/null +++ b/docs/user-guide/scaffold.md @@ -0,0 +1,50 @@ +# ๐Ÿ—๏ธ Scaffold Guide + +The `scaffold` command allows you to quickly generate new files using AI that matches your project's existing coding style, naming conventions, and patterns. + +### Features + +- **Project context harvesting**: Analyzes siblings and directory structure for style matching. +- **Optional test generation**: Use `--with-tests` to generate a basic test file. +- **Safety checks**: Won't overwrite existing files without `--force`. +- **Language detection** and overrides (`--lang`). + +### Usage + +Scaffold a new file with Grok using project context for style matching. + +```bash +# Basic usage +grokkit scaffold internal/git/utils.go "git wrapper for listing tags" + +# Scaffold with a basic test file +grokkit scaffold app.py "Flask route for health checks" --with-tests + +# Preview without writing +grokkit scaffold main.go "simple CLI entrypoint" --dry-run +``` + +### Options + +| Flag | Description | +|------|-------------| +| `--with-tests` | Also generate a basic test file (e.g., `utils_test.go`) | +| `--dry-run` | Preview the generated code without writing any files | +| `--yes`, `-y` | Skip the confirmation prompt and write files immediately | +| `--force` | Overwrite the destination file if it already exists | +| `--lang` | Manually specify the language (e.g., "Go", "Python", "TypeScript") | +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### How it Works + +1. **Context Harvesting**: Grokkit reads existing files in the same directory to understand your project's "vibe." +2. **Language Detection**: It automatically detects the language based on the file extension. +3. **AI Generation**: It sends the description and project context to Grok. +4. **Style Matching**: Grok is instructed to match the project's exact style. +5. **Confirmation**: You review the code and confirm before it's saved. + +### Tips for Better Results + +- **Be descriptive**: Instead of "a logger", try "a structured logger using slog that writes to a rotating file". +- **Use extensions**: Ensure your file path has the correct extension so Grokkit can detect the language. +- **Project layout**: Run `scaffold` in a directory that already contains some code for best style matching. diff --git a/docs/user-guide/testgen.md b/docs/user-guide/testgen.md new file mode 100644 index 0000000..83d51ea --- /dev/null +++ b/docs/user-guide/testgen.md @@ -0,0 +1,49 @@ +# ๐Ÿงช Testgen Guide + +The `testgen` command generates high-quality unit tests for your existing code files using AI. It's designed to match your project's testing conventions and use the most modern practices for each language. + +### Benefits + +- **Go**: Table-driven `t.Parallel()` matching codebase. +- **Python**: Pytest with `@parametrize`. +- **C**: Check framework suites. +- **C++**: Google Test `EXPECT_*`. +- **Boosts coverage**; safe preview. + +### Usage + +Generate comprehensive unit tests for Go/Python/C/C++ files using AI. + +```bash +grokkit testgen internal/grok/client.go +grokkit testgen app.py --yes +grokkit testgen foo.c bar.cpp +``` + +### Safety Features + +- **Lang detection** via `internal/linter`. +- **Unified diff preview**. +- **Y/N confirmation** (`--yes` to auto-confirm). + +### Options + +| Flag | Description | +|------|-------------| +| `--yes`, `-y` | Skip the confirmation prompt and write tests immediately | +| `--model`, `-m` | Override the default model (e.g., `grok-4`) | + +### How it Works + +1. **Language Detection**: Grokkit detects the language using its internal linter. +2. **Context Analysis**: It reads the source file and any existing test file. +3. **AI Generation**: It sends the source code to Grok with a language-specific system prompt. +4. **Style Matching**: Grok is instructed to use modern idioms and match the project's testing style. +5. **Interactive Diff**: If a test file already exists, it shows a diff of the proposed changes. + +### Best Practices + +- **Start with unit tests**: Test individual functions and methods. +- **Run tests immediately**: After `testgen` completes, run `make test` or your language-specific test runner to verify the generated tests. +- **Review for accuracy**: AI-generated tests are a great starting point, but always review them to ensure the logic and assertions are correct. +- **Coverage**: Use `make test-cover` (for Go) to see how much your new tests have improved your coverage. diff --git a/docs/user-guide/version.md b/docs/user-guide/version.md new file mode 100644 index 0000000..c330a26 --- /dev/null +++ b/docs/user-guide/version.md @@ -0,0 +1,21 @@ +# ๐Ÿท๏ธ Version Guide + +The `version` command prints the version, commit hash, and build date for the `grokkit` binary. + +### Usage + +```bash +grokkit version +``` + +### Output + +```bash +grokkit version v0.1.0 (commit ab12cd3) +``` + +### Why use Version? + +- **Troubleshooting**: When reporting an issue, providing the version helps maintainers identify the state of the code you are using. +- **Verification**: Confirm that you have successfully installed the latest version or that your local build is up-to-date. +- **Consistency**: Ensure all team members are using the same version of the tool for reproducible results. diff --git a/docs/user-guide/workflows.md b/docs/user-guide/workflows.md new file mode 100644 index 0000000..4fc3373 --- /dev/null +++ b/docs/user-guide/workflows.md @@ -0,0 +1,113 @@ +# ๐Ÿ”„ Grokkit Workflows + +Learn how to integrate Grokkit into your development cycle effectively. + +## Git Workflow Integration + +The standard way to use Grokkit for your daily git tasks: + +```bash +# 1. Make changes +vim src/api.go + +# 2. Review with AI +git add src/api.go +grokkit review + +# 3. Fix issues, then commit +git add src/api.go +grokkit commit + +# 4. Generate PR description +grokkit pr-describe +``` + +## Code Refactoring Workflow + +Use Grokkit to plan and execute larger code changes: + +```bash +# 1. Chat to plan approach +grokkit chat +> "How should I refactor this authentication code to use middleware?" + +# 2. Apply changes with edit +grokkit edit auth.go "implement middleware pattern as discussed" + +# 3. Review changes +grokkit review + +# 4. Commit +grokkit commit +``` + +## Debugging Workflow + +Quickly identify and fix bugs using a combination of chat and editing: + +```bash +# 1. Describe issue in chat +grokkit chat --debug +> "I'm getting a nil pointer error in handler.go:42" + +# 2. Apply suggested fixes +grokkit edit handler.go "add nil checks before dereferencing user object" + +# 3. Verify and commit +grokkit review +grokkit commit +``` + +## Batch File Editing + +Automate repetitive edits across many files: + +```bash +# Edit multiple files with consistent changes +for file in src/*.go; do + grokkit edit "$file" "add context parameter to all exported functions" +done + +# Review all changes together +grokkit review +``` + +## Code Quality Workflow + +Maintain high standards with AI-assisted linting and documentation: + +```bash +# 1. Check a file for linting issues +grokkit lint app.py --dry-run + +# 2. Apply AI-suggested fixes with preview +grokkit lint app.py + +# 3. Auto-fix multiple files +for file in src/*.js; do + grokkit lint "$file" --auto-fix +done + +# 4. Review and commit +grokkit review +grokkit commit +``` + +## Documentation Generation Workflow + +Generate comprehensive documentation for your project in seconds: + +```bash +# 1. Preview docs for a single file +grokkit docs internal/api/handler.go + +# 2. Batch-document a package +grokkit docs cmd/*.go --auto-apply + +# 3. Document across languages in one pass +grokkit docs lib/utils.py src/helpers.ts --auto-apply + +# 4. Review and commit +grokkit review +grokkit commit +``` diff --git a/internal/recipe/loader.go b/internal/recipe/loader.go new file mode 100644 index 0000000..812ffaa --- /dev/null +++ b/internal/recipe/loader.go @@ -0,0 +1,183 @@ +package recipe + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + "sync" + "text/template" + + "gopkg.in/yaml.v3" +) + +// Global safe read-only whitelist +// LoadSafeCommands reads the user's safe shell commands config (with fallback) +var safeCommands = sync.OnceValue(func() map[string]bool { + cfgPath := filepath.Join(os.Getenv("HOME"), ".config", "grokkit", "safe_shell_commands.yaml") + + data, err := os.ReadFile(cfgPath) + if err != nil { + // Fallback to a built-in safe list + fmt.Println("Could not read safe shell commands config, using built-in fallback") + return map[string]bool{ + "ls": true, "pwd": true, "cat": true, "tree": true, + "find": true, "grep": true, "rg": true, + "git status": true, "git log": true, "git diff": true, "git branch": true, + "go test": true, "go vet": true, "go fmt": true, "go mod tidy": true, + "make test": true, + "pytest": true, "poetry run pytest": true, "ctest": true, + "python -m pytest": true, "python": true, "poetry": true, + } + + } + fmt.Println("Using safe shell commands config:", cfgPath) + + var cfg struct { + SafeCommands []string `yaml:"safe_commands"` + } + err = yaml.Unmarshal(data, &cfg) + if err != nil { + return nil + } + + m := make(map[string]bool) + for _, c := range cfg.SafeCommands { + m[strings.ToLower(strings.TrimSpace(c))] = true + } + return m +}) + +var ( + // stepRe still finds the headings (this one is solid) + stepRe = regexp.MustCompile(`(?m)^### Step (\d+): (.+)$`) +) + +func Load(path string, userParams map[string]any) (*Recipe, error) { + b, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + parts := bytes.SplitN(b, []byte("---"), 3) + if len(parts) < 3 { + return nil, fmt.Errorf("missing YAML frontmatter") + } + + var r Recipe + if err := yaml.Unmarshal(parts[1], &r); err != nil { + return nil, fmt.Errorf("yaml parse: %w", err) + } + + // === SAFETY CHECK using user-configurable whitelist === + safeMap := safeCommands() + for _, cmd := range r.AllowedShellCommands { + trimmed := strings.ToLower(strings.TrimSpace(cmd)) + + allowed := false + for safe := range safeMap { + safeTrim := strings.ToLower(strings.TrimSpace(safe)) + + // Match exact command OR command followed by space + arguments + if trimmed == safeTrim || strings.HasPrefix(trimmed, safeTrim+" ") { + allowed = true + break + } + } + if !allowed { + return nil, fmt.Errorf("\u001B[31mRecipe contains unsafe shell command: %q. "+ + "Remove or replace the dangerous command in your recipe.\u001B[0m", cmd) + } + } + + // Apply defaults + user --param overrides + if r.Parameters == nil { + r.Parameters = make(map[string]Parameter) + } + r.ResolvedParams = make(map[string]any) + for name, p := range r.Parameters { + if v, ok := userParams[name]; ok { + r.ResolvedParams[name] = v + } else if p.Default != nil { + r.ResolvedParams[name] = p.Default + } + } + + // Render templates with resolved values + tpl, err := template.New("recipe").Parse(string(parts[2])) + if err != nil { + return nil, err + } + var rendered bytes.Buffer + if err := tpl.Execute(&rendered, r.ResolvedParams); err != nil { + return nil, err + } + body := rendered.String() + + // Extract Overview + if idx := strings.Index(body, "## Execution Steps"); idx != -1 { + r.Overview = strings.TrimSpace(body[:idx]) + } + + // Extract steps with robust multi-line parsing + matches := stepRe.FindAllStringSubmatch(body, -1) + for i, m := range matches { + stepNum := i + 1 + title := m[2] + + start := strings.Index(body, m[0]) + end := len(body) + if i+1 < len(matches) { + nextStart := strings.Index(body[start:], matches[i+1][0]) + end = start + nextStart + } + + section := body[start:end] + + step := Step{Number: stepNum, Title: title} + + // Simple, reliable label-based parsing (handles multi-line + blank lines) + labels := []string{"**Objective:**", "**Instructions:**", "**Expected output:**"} + for _, label := range labels { + labelStart := strings.Index(section, label) + if labelStart == -1 { + continue + } + contentStart := labelStart + len(label) + contentEnd := len(section) + + // Find next label or end of section + for _, nextLabel := range labels { + next := strings.Index(section[contentStart:], nextLabel) + if next != -1 { + contentEnd = contentStart + next + break + } + } + + content := strings.TrimSpace(section[contentStart:contentEnd]) + + switch label { + case "**Objective:**": + step.Objective = content + case "**Instructions:**": + step.Instructions = content + case "**Expected output:**": + step.Expected = content + } + } + + r.Steps = append(r.Steps, step) + } + + // Final summary (everything after last step) + if len(matches) > 0 { + lastMatch := matches[len(matches)-1][0] + lastIdx := strings.LastIndex(body, lastMatch) + r.FinalSummaryPrompt = strings.TrimSpace(body[lastIdx+len(lastMatch):]) + } + + return &r, nil +} diff --git a/internal/recipe/runner.go b/internal/recipe/runner.go new file mode 100644 index 0000000..50db69d --- /dev/null +++ b/internal/recipe/runner.go @@ -0,0 +1,385 @@ +package recipe + +import ( + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + + "gmgauthier.com/grokkit/internal/grok" +) + +type Runner struct { + Recipe *Recipe + Client *grok.Client + Model string +} + +func NewRunner(r *Recipe, client *grok.Client, model string) *Runner { + return &Runner{Recipe: r, Client: client, Model: model} +} + +func (r *Runner) Run() error { + fmt.Printf("๐Ÿณ Starting recipe: %s v%s\n\n", r.Recipe.Name, r.Recipe.Version) + + workDir := r.resolveWorkDir() + + var previousResults []string + var refactorJSONs []string + + for _, step := range r.Recipe.Steps { + fmt.Printf("Step %d/%d: %s\n", step.Number, len(r.Recipe.Steps), step.Title) + + titleLower := strings.ToLower(step.Title) + + switch { + case strings.Contains(titleLower, "discover") || strings.Contains(titleLower, "find"): + files := r.discoverFiles(workDir) + result := strings.Join(files, "\n") + previousResults = append(previousResults, "Discovered files:\n"+result) + fmt.Println(result) + + case strings.Contains(titleLower, "refactor"): + r.refactorFiles(previousResults, &refactorJSONs) + continue + + case strings.Contains(titleLower, "apply") || strings.Contains(titleLower, "patch"): + r.handleApplyStep(refactorJSONs) + continue + + // Explicit trigger for read-only shell + case strings.Contains(titleLower, "read-only shell") || strings.Contains(titleLower, "shell read-only"): + r.executeReadOnlyShell(step, previousResults) + continue + + default: + prompt := fmt.Sprintf(`Recipe Overview: +%s + +Previous step results (for context): +%s + +=== CURRENT STEP === +Objective: %s +Instructions: %s +Expected output format: %s + +Execute this step now. Respond ONLY with the expected output format โ€” no explanations, no extra text.`, + r.Recipe.Overview, + strings.Join(previousResults, "\n\n---\n\n"), + step.Objective, + step.Instructions, + step.Expected) + + messages := []map[string]string{ + {"role": "system", "content": "You are Grok, built by xAI. Precise expert programmer and refactoring assistant."}, + {"role": "user", "content": prompt}, + } + + response := r.Client.Stream(messages, r.Model) + fmt.Println() + + previousResults = append(previousResults, fmt.Sprintf("Step %d result:\n%s", step.Number, response)) + } + } + + fmt.Println("\nโœ… Recipe complete.") + return nil +} + +// resolveWorkDir expands ~ and makes absolute +func (r *Runner) resolveWorkDir() string { + root := "." + if v, ok := r.Recipe.ResolvedParams["package_path"]; ok { + if s, ok := v.(string); ok && s != "" { + root = s + } + } + + if strings.HasPrefix(root, "~/") { + home, _ := os.UserHomeDir() + root = filepath.Join(home, root[2:]) + } else if root == "~" { + root, _ = os.UserHomeDir() + } + + abs, _ := filepath.Abs(root) + return abs +} + +// discoverFiles โ€” uses resolved workDir +func (r *Runner) discoverFiles(workDir string) []string { + var files []string + + allowedExt := make(map[string]bool) + for _, lang := range r.Recipe.ProjectLanguages { + if exts, ok := r.Recipe.Extensions[lang]; ok { + for _, ext := range exts { + allowedExt[ext] = true + } + } + } + + searchFor := r.Recipe.SearchPattern + if searchFor == "" { + searchFor = "if err != nil" + } + + _ = filepath.WalkDir(workDir, func(path string, d os.DirEntry, err error) error { + if err != nil || d.IsDir() { + return nil + } + if allowedExt[filepath.Ext(path)] { + b, _ := os.ReadFile(path) + if strings.Contains(string(b), searchFor) { + files = append(files, path) + } + } + return nil + }) + + if len(files) == 0 { + files = append(files, "No files found matching the criteria.") + } + return files +} + +// refactorFiles โ€” one file at a time +func (r *Runner) refactorFiles(previousResults []string, refactorJSONs *[]string) { + discoveredLine := previousResults[len(previousResults)-1] + lines := strings.Split(discoveredLine, "\n") + + for _, line := range lines { + filePath := strings.TrimSpace(line) + if filePath == "" || strings.HasPrefix(filePath, "Discovered") || filePath == "No files found matching the criteria." { + continue + } + + fmt.Printf(" Refactoring %s...\n", filePath) + + content, err := os.ReadFile(filePath) + if err != nil { + fmt.Printf(" โŒ Could not read %s\n", filePath) + continue + } + + prompt := fmt.Sprintf(`Refactor the following file to use Result[T] instead of naked errors. +Follow existing style and preserve all comments. +Return ONLY this exact JSON (no extra text, no markdown): + +{ + "file": "%s", + "content": "the complete refactored file here" +} + +Original file: +%s`, filePath, string(content)) + + messages := []map[string]string{ + {"role": "system", "content": "You are Grok, built by xAI. Precise expert programmer and refactoring assistant."}, + {"role": "user", "content": prompt}, + } + + response := r.Client.Stream(messages, r.Model) + fmt.Println() + + *refactorJSONs = append(*refactorJSONs, response) + } +} + +// handleApplyStep stays as you have it (or your latest version) +func (r *Runner) handleApplyStep(refactorJSONs []string) { + if len(refactorJSONs) == 0 { + fmt.Println(" โš ๏ธ No refactored files to apply โ€” skipping.") + return + } + + var allChanges []FileChange + for _, jsonStr := range refactorJSONs { + start := strings.Index(jsonStr, "{") + end := strings.LastIndex(jsonStr, "}") + 1 + if start == -1 { + continue + } + + var ch FileChange + if err := json.Unmarshal([]byte(jsonStr[start:end]), &ch); err == nil && ch.File != "" { + allChanges = append(allChanges, ch) + } + } + + if len(allChanges) == 0 { + fmt.Println(" โš ๏ธ No valid file changes found โ€” skipping.") + return + } + + fmt.Println(" ๐Ÿ“„ Dry-run mode: creating patch file...") + patchPath := filepath.Join(".", "recipe-refactor.patch") + if err := createUnifiedPatch(allChanges, patchPath); err != nil { + fmt.Printf(" โŒ Failed to create patch: %v\n", err) + return + } + fmt.Printf(" โœ… Patch created: %s\n", patchPath) + fmt.Println(" Review it, then run with dry_run=false to apply.") +} + +type FileChange struct { + File string `json:"file"` + Content string `json:"content"` +} + +func createUnifiedPatch(changes []FileChange, patchPath string) error { + f, err := os.Create(patchPath) + if err != nil { + return err + } + defer func(f *os.File) { + err := f.Close() + if err != nil { + return + } + }(f) + + for _, ch := range changes { + _, err := fmt.Fprintf(f, "--- %s\n+++ %s\n@@ -0,0 +1,%d @@\n", ch.File, ch.File, strings.Count(ch.Content, "\n")+1) + if err != nil { + return err + } + for _, line := range strings.Split(ch.Content, "\n") { + _, err := fmt.Fprintf(f, "+%s\n", line) + if err != nil { + return err + } + } + } + return nil +} + +// executeReadOnlyShell โ€” safe, whitelisted, read-only shell execution with user confirmation +func (r *Runner) executeReadOnlyShell(step Step, previousResults []string) { + prompt := fmt.Sprintf(`You need additional context from the filesystem for this step. + +Recipe Overview: +%s + +Previous step results: +%s + +=== CURRENT STEP === +Objective: %s +Instructions: %s + +Return ONLY a JSON array of read-only commands. Example: + +[ + { + "command": "ls", + "args": ["-la"] + }, + { + "command": "tree", + "args": [".", "-L", 3] + } +] + +Only use safe read-only commands.`, + r.Recipe.Overview, + strings.Join(previousResults, "\n\n---\n\n"), + step.Objective, + step.Instructions) + + messages := []map[string]string{ + {"role": "system", "content": "You are Grok, built by xAI. Precise expert programmer and refactoring assistant."}, + {"role": "user", "content": prompt}, + } + + response := r.Client.Stream(messages, r.Model) + fmt.Println() + + // Robust JSON extraction + start := strings.Index(response, "[") + end := strings.LastIndex(response, "]") + 1 + if start == -1 { + fmt.Println(" โš ๏ธ No valid read-only commands returned โ€” skipping.") + return + } + + jsonStr := response[start:end] + jsonStr = strings.ReplaceAll(jsonStr, "\\\"", "\"") + + type ShellCommand struct { + Command string `json:"command"` + Args []interface{} `json:"args"` + } + + var cmds []ShellCommand + if err := json.Unmarshal([]byte(jsonStr), &cmds); err != nil { + fmt.Printf(" โš ๏ธ Could not parse commands: %v\n", err) + return + } + + // Use the GLOBAL safe list for the security check + safeMap := safeCommands() + + for _, cmd := range cmds { + // Build argument list, converting numbers to strings + args := make([]string, len(cmd.Args)) + for i, arg := range cmd.Args { + switch v := arg.(type) { + case string: + args[i] = v + case float64: + args[i] = strconv.FormatFloat(v, 'f', -1, 64) + default: + args[i] = fmt.Sprintf("%v", v) + } + } + + fullCmd := cmd.Command + if len(args) > 0 { + fullCmd += " " + strings.Join(args, " ") + } + + fmt.Printf(" Grok wants to run: %s\n Allow this command? [y/N] ", fullCmd) + + var answer string + _, err := fmt.Scanln(&answer) + if err != nil { + return + } + if !strings.HasPrefix(strings.ToLower(answer), "y") { + fmt.Println(" โŒ Cancelled by user.") + continue + } + + // FINAL SECURITY CHECK โ€” use the global safe list + allowed := false + trimmedCmd := strings.ToLower(strings.TrimSpace(cmd.Command)) + for safe := range safeMap { + if strings.HasPrefix(trimmedCmd, strings.ToLower(safe)) { + allowed = true + break + } + } + + if !allowed { + fmt.Printf(" โŒ Command not allowed by global safety policy: %s\n", cmd.Command) + continue + } + + // Run with strict cwd + execCmd := exec.Command(cmd.Command, args...) + execCmd.Dir = r.resolveWorkDir() + output, err := execCmd.CombinedOutput() + + if err != nil { + fmt.Printf(" โŒ Failed: %v\n%s\n", err, string(output)) + } else { + fmt.Printf(" โœ… Success\n%s\n", string(output)) + previousResults = append(previousResults, fmt.Sprintf("Command output:\n%s", string(output))) + } + } +} diff --git a/internal/recipe/types.go b/internal/recipe/types.go new file mode 100644 index 0000000..985f607 --- /dev/null +++ b/internal/recipe/types.go @@ -0,0 +1,36 @@ +package recipe + +type Recipe struct { + Name string `yaml:"name"` + Description string `yaml:"description"` + Version string `yaml:"version"` + Parameters map[string]Parameter `yaml:"parameters"` + AllowedShellCommands []string `yaml:"allowed_shell_commands"` + + // Generic discovery support (option 2) + ProjectLanguages []string `yaml:"project_languages"` + Extensions map[string][]string `yaml:"extensions"` + SearchPattern string `yaml:"search_pattern"` // new + + // Resolved runtime values from --param flags + ResolvedParams map[string]any `yaml:"-"` + + // Internal fields populated by loader + Overview string `yaml:"-"` + Steps []Step `yaml:"-"` + FinalSummaryPrompt string `yaml:"-"` +} + +type Parameter struct { + Type string `yaml:"type"` + Default any `yaml:"default"` + Description string `yaml:"description"` +} + +type Step struct { + Number int + Title string + Objective string + Instructions string + Expected string +} diff --git a/safe_shell_commands.yaml.example b/safe_shell_commands.yaml.example new file mode 100644 index 0000000..5bd8c39 --- /dev/null +++ b/safe_shell_commands.yaml.example @@ -0,0 +1,27 @@ +# Grokkit safe shell commands whitelist +# Only commands listed here (or prefixed by these) are allowed in recipes. +# This is a safety boundary โ€” never add rm, mv, cd, sudo, etc. +# This file should be placed in ~/.config/grokkit/safe_shell_commands.yaml +# customize it as you see fit. + +safe_commands: + - ls + - pwd + - cat + - tree + - find + - grep + - rg # ripgrep + - git status + - git log + - git diff + - git branch + - go test + - go vet + - go fmt + - go mod tidy + - make test + - pytest + - poetry run pytest + - ctest + - python -m pytest diff --git a/todo/doing/recipe-feature.md b/todo/doing/recipe-feature.md new file mode 100644 index 0000000..dbe5702 --- /dev/null +++ b/todo/doing/recipe-feature.md @@ -0,0 +1,42 @@ +# Recipe Feature Overview + +The `feature/recipe_implementation` branch introduces a "Recipe" system to `grokkit`. This system allows for complex, multi-step refactorings or tasks to be defined in Markdown files and executed sequentially by an LLM. + +## Key Components + +### 1. Recipe Definitions +Recipes are stored as Markdown files (e.g., `.grokkit/recipes/result-refactor.md`) with: +- **YAML Frontmatter**: Metadata like `name`, `description`, `version`, and `parameters`. +- **Structured Steps**: Defined using `### Step N: Title` headings. +- **Step Details**: Each step includes `**Objective:**`, `**Instructions:**`, and `**Expected output:**` sections. + +### 2. Internal Recipe Package (`internal/recipe/`) +- **`types.go`**: Defines the data structures for `Recipe`, `Step`, and `Parameter`. +- **`loader.go`**: + - Parses Markdown files and extracts YAML frontmatter. + - Uses regular expressions (`stepRe`, `subRe`) to extract step details. + - Supports basic `text/template` rendering for parameter substitution in instructions. +- **`runner.go`**: + - Orchestrates recipe execution. + - Currently implements a dry-run/preview mode that prints steps to the console. + - Placeholder for future LLM integration. + +### 3. CLI Integration (`cmd/recipe.go`) +- **`grokkit recipe run [recipe-name|recipe.md]`**: The main entry point for users. +- **Path Resolution**: + 1. **Explicit Path**: Checks if the argument is a direct file path. + 2. **Project Local**: Looks in `.grokkit/recipes/` within the project root. + 3. **Global Share**: Falls back to `~/.local/share/grokkit/recipes/` (XDG-compliant). + +## Technical Details +- **Go Version**: 1.24.2. +- **Dependencies**: `gopkg.in/yaml.v3` for frontmatter, `github.com/spf13/cobra` for CLI. +- **Parsing**: Uses multi-line regex for robust section extraction even with varied Markdown formatting. + +## Current Progress & Next Steps +- [x] Recipe data structures and YAML frontmatter parsing. +- [x] Markdown step extraction and template rendering. +- [x] CLI command with project-local/global path resolution. +- [ ] Integration with LLM for actual step execution. +- [ ] Support for `--param` flags in the CLI. +- [ ] Shell command execution within steps (if allowed).