Compare commits

..

No commits in common. "ffc840ca5b3894e467909208276b4992e0bf1f6e" and "736fe4fcd6f7ab894a2eac136e41506fbbfc9357" have entirely different histories.

38 changed files with 534 additions and 2215 deletions

3
.gitignore vendored
View File

@ -1,11 +1,10 @@
.idea/ .idea/
.grok/
.junie/ .junie/
.claude/ .claude/
build/ build/
grokkit
*.bak *.bak
*.log *.log
*.tmp *.tmp
.env .env
*.patch
chat_history.json chat_history.json

3
.grok/settings.json Normal file
View File

@ -0,0 +1,3 @@
{
"model": "grok-code-fast-1"
}

View File

@ -1,76 +0,0 @@
---
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.

View File

@ -1,67 +0,0 @@
---
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.

562
README.md
View File

@ -7,21 +7,8 @@ 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)]() [![Go Version](https://img.shields.io/badge/go-1.24.2-blue)]()
[![License](https://img.shields.io/badge/license-Unlicense-lightgrey)]() [![License](https://img.shields.io/badge/license-Unlicense-lightgrey)]()
## Requirements ## 🚀 Quick Start
- 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 ```bash
# Set your API key # Set your API key
export XAI_API_KEY=sk-... export XAI_API_KEY=sk-...
@ -29,23 +16,321 @@ export XAI_API_KEY=sk-...
# Install from source # Install from source
git clone https://repos.gmgauthier.com/gmgauthier/grokkit.git git clone https://repos.gmgauthier.com/gmgauthier/grokkit.git
cd grokkit cd grokkit
make test
make build
make install make install
````
### Verify: # Or build locally
make build
# 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:
```bash ```bash
grokkit version 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> [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 <file>
```
- **Staged changes**: If you've already staged the changes:
```bash
git restore --staged <file>
git restore <file>
```
- **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 ## Configuration
### Environment Variables ### Environment Variables
```bash ```bash
export XAI_API_KEY=sk-... # Required: Your xAI API key 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) ### Config File (Optional)
@ -66,19 +351,7 @@ fast = "grok-4-1-fast-non-reasoning"
history_file = "~/.config/grokkit/chat_history.json" history_file = "~/.config/grokkit/chat_history.json"
``` ```
**See also:** [docs/developer-guide/CONFIGURATION.md](docs/developer-guide/CONFIGURATION.md) for advanced configuration options. **See also:** [docs/CONFIGURATION.md](docs/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 ### Logging
@ -97,15 +370,121 @@ cat ~/.config/grokkit/grokkit.log | jq 'select(.msg=="API request completed") |
## Workflows ## Workflows
Common usage patterns to integrate Grokkit into your development cycle. ### Git Workflow Integration
[Read the Workflows Guide](docs/user-guide/workflows.md) ```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
```
## Shell Completions ## Shell Completions
Generate shell completions for faster command entry: Generate shell completions for faster command entry:
[Read the full Completion Guide](docs/user-guide/completion.md) ```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
```
## Flags ## Flags
@ -144,9 +523,6 @@ grokkit review -v
- ✅ **Git workflow integration** - Commit messages, reviews, PR descriptions - ✅ **Git workflow integration** - Commit messages, reviews, PR descriptions
- ✅ **Multi-language linting** - 9 languages supported with AI-powered fixes - ✅ **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 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 ### Quality & Testing
- ✅ **Test coverage 68%+** - Comprehensive unit tests including all command message builders - ✅ **Test coverage 68%+** - Comprehensive unit tests including all command message builders
@ -180,9 +556,108 @@ grokkit review -v
## Development ## Development
Comprehensive build instructions, project structure details, and the Grokkit development workflow. ```bash
# All tests pass without XAI_API_KEY (unit tests only)
[Read the Development Overview Guide](docs/developer-guide/overview.md) # 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
## API Usage & Costs ## API Usage & Costs
@ -192,6 +667,11 @@ Grokkit uses the xAI Grok API. Be aware:
- Streaming reduces perceived latency - Streaming reduces perceived latency
- Consider using model aliases for different use cases (fast/expensive) - 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 ## Troubleshooting
@ -210,7 +690,7 @@ Error: Request failed: context deadline exceeded
→ Solution: chmod 644 ~/.config/grokkit/grokkit.log → Solution: chmod 644 ~/.config/grokkit/grokkit.log
``` ```
**See [docs/developer-guide/TROUBLESHOOTING.md](docs/developer-guide/TROUBLESHOOTING.md) for more details.** **See [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) for more details.**
## License ## License

View File

@ -19,6 +19,7 @@ Default mode is factual and brief. Use --wordy for longer, more explanatory answ
func init() { func init() {
queryCmd.Flags().Bool("wordy", false, "Give a longer, more detailed answer") queryCmd.Flags().Bool("wordy", false, "Give a longer, more detailed answer")
rootCmd.AddCommand(queryCmd)
} }
func runQuery(cmd *cobra.Command, args []string) { func runQuery(cmd *cobra.Command, args []string) {

View File

@ -1,139 +0,0 @@
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(&paramFlags, "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")
}

View File

@ -16,33 +16,28 @@ This document describes the design principles, architecture patterns, and implem
Grokkit follows these core principles: Grokkit follows these core principles:
### 1. **The Developer Is The Agent** ### 1. **Simplicity First**
- 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 dependencies (stdlib + well-known libs)
- Minimal interface surface (CLI commands over TUI interactions) - Minimal interface surface (CLI commands over TUI interactions)
- Clear, readable code over clever solutions - Clear, readable code over clever solutions
- Single responsibility per package - Single responsibility per package
### 3. **Safety by Default** ### 2. **Safety by Default**
- Git-based version control for change management - Git-based version control for change management
- Confirmation prompts for destructive actions - Confirmation prompts for destructive actions
- Comprehensive error handling - Comprehensive error handling
### 4. **Observability** ### 3. **Observability**
- Structured logging for all operations - Structured logging for all operations
- Request/response timing - Request/response timing
- Contextual error messages - Contextual error messages
### 5. **Testability** ### 4. **Testability**
- Interface-based design - Interface-based design
- Dependency injection where needed - Dependency injection where needed
- Unit tests for pure functions - Unit tests for pure functions
### 6. **User Experience** ### 5. **User Experience**
- Streaming responses for immediate feedback - Streaming responses for immediate feedback
- Persistent history - Persistent history
- Shell completions - Shell completions
@ -82,13 +77,9 @@ grokkit/
│ ├── logger.go # Logger setup + helpers │ ├── logger.go # Logger setup + helpers
│ └── logger_test.go │ └── logger_test.go
├── docs/ # Documentation ├── docs/ # Documentation
│ └── developer-guide/ # Technical documentation │ ├── TROUBLESHOOTING.md
│ ├── ARCHITECTURE.md # This file │ ├── ARCHITECTURE.md # This file
│ ├── CONFIGURATION.md # Configuration guide │ └── CONFIGURATION.md
│ ├── TROUBLESHOOTING.md # Troubleshooting guide
│ └── index.md # Developer guide index
│ ├── user-guide/ # End-user documentation
│ └── index.md # Main documentation index
├── .gitea/workflows/ # CI/CD ├── .gitea/workflows/ # CI/CD
│ ├── ci.yml # Test + lint + build │ ├── ci.yml # Test + lint + build
│ └── release.yml # Multi-platform releases │ └── release.yml # Multi-platform releases

View File

@ -1,11 +0,0 @@
# 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)**

View File

@ -1,107 +0,0 @@
# 🛠️ 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!

View File

@ -1,24 +0,0 @@
# 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)

View File

@ -1,49 +0,0 @@
# 🤖 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.

View File

@ -1,51 +0,0 @@
# 🗒️ 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.

View File

@ -1,45 +0,0 @@
# 💬 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"
```

View File

@ -1,62 +0,0 @@
# 📝 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.

View File

@ -1,58 +0,0 @@
# ✅ 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 "<message>"`.
### 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.

View File

@ -1,42 +0,0 @@
# 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 <command> --` followed by `Tab` to see available flags.

View File

@ -1,60 +0,0 @@
# 📖 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.

View File

@ -1,53 +0,0 @@
# ✏️ 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.

View File

@ -1,33 +0,0 @@
# 📜 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.

View File

@ -1,52 +0,0 @@
# 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!

View File

@ -1,52 +0,0 @@
# 🔧 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.

View File

@ -1,49 +0,0 @@
# 📋 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 <base>..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.

View File

@ -1,38 +0,0 @@
# 🤖 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.

View File

@ -1,102 +0,0 @@
# 👨‍🍳 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

View File

@ -1,48 +0,0 @@
# 🔍 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`.

View File

@ -1,31 +0,0 @@
# 🛡️ 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 <file>
```
- **Staged changes**: If you've already staged the changes:
```bash
git restore --staged <file>
git restore <file>
```
- **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.

View File

@ -1,50 +0,0 @@
# 🏗️ 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.

View File

@ -1,49 +0,0 @@
# 🧪 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.

View File

@ -1,21 +0,0 @@
# 🏷️ 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.

View File

@ -1,113 +0,0 @@
# 🔄 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
```

View File

@ -1,183 +0,0 @@
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
}

View File

@ -1,385 +0,0 @@
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)))
}
}
}

View File

@ -1,36 +0,0 @@
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
}

View File

@ -1,27 +0,0 @@
# 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

View File

@ -1,42 +0,0 @@
# 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).