Compare commits

...

55 Commits

Author SHA1 Message Date
ffc840ca5b Merge pull request 'feature/recipe_implementation' (#5) from feature/recipe_implementation into master
All checks were successful
CI / Test (push) Successful in 34s
CI / Lint (push) Successful in 25s
CI / Build (push) Successful in 22s
Reviewed-on: #5
2026-03-07 23:17:53 +00:00
cd47686679 docs: refactor README and docs structure for better organization
All checks were successful
CI / Test (pull_request) Successful in 42s
CI / Lint (pull_request) Successful in 27s
CI / Build (pull_request) Successful in 23s
- Simplified README.md by moving detailed command docs, workflows, and development info to dedicated user-guide/ and developer-guide/ directories.
- Created index.md files for both guides to improve navigation.
- Extracted individual command guides (e.g., chat.md, edit.md) into user-guide/ for focused, maintainable documentation.
- Moved architecture, configuration, and troubleshooting to developer-guide/.
- Updated README links to point to the new docs structure.
2026-03-07 22:42:43 +00:00
2116a62a5a refactor(cmd): remove root command addition from query init
This prevents potential duplicate command registrations if added elsewhere.
2026-03-07 21:17:10 +00:00
bb3f968711 docs(readme): update command list and add new feature descriptions
- Reorganize commit commands into commit-msg and commit
- Add sections for scaffold, recipe, and testgen
- Update PR description base branch example
- Add new features to quality section: AI unit test generation, file scaffolding, transactional recipes
- Update directory structure with .grokkit/recipes and internal/recipe
2026-03-07 21:12:21 +00:00
383d28a91a refactor(recipe): enhance shell command security with global safe list
- Introduce global safeCommands() map for command whitelisting.
- Implement case-insensitive prefix checking for allowed commands.
- Simplify argument handling by removing redundant int conversions.
- Update error messages and comments for clarity on security policies.
- Remove outdated comments and adjust prompt text for consistency.
2026-03-07 19:50:06 +00:00
4603a1ec7a fix(recipe): improve allowed shell command validation
Update the command matching logic to require an exact match or the command followed by a space and arguments. Also normalize case and trim whitespace for safe commands to prevent loose prefix matches that could allow unintended commands.
2026-03-07 19:37:53 +00:00
685b0f40d7 feat(recipe): support numeric arguments in read-only shell commands
Update the executeReadOnlyShell function to handle numbers in command arguments,
such as 'tree -L 3', by changing Args to []interface{} and converting them to strings
before execution. Add strconv import for formatting.
2026-03-07 19:27:15 +00:00
a36f3585f4 refactor(recipe): enhance read-only shell handling and robustness
- Tighten trigger conditions for read-only shell steps to specific phrases
- Add robust JSON extraction with escaped quote handling
- Reorder user confirmation before whitelist check in execution flow
- Relocate FileChange struct and clean up comments
- Update recipe markdown for step title consistency
2026-03-07 19:18:41 +00:00
3d9d1cd722 feat(recipe): add project exploration step with read-only shell support
- Introduce new Step 1 in result-refactor.md for exploring project structure using safe read-only shell commands (e.g., tree, cat).
- Rename subsequent steps accordingly.
- Add handler in runner.go for read-only shell steps triggered by keywords like "explore" or "inspect".
2026-03-07 18:58:40 +00:00
66d52917c0 feat(recipe): add read-only shell execution with user confirmation
Implement executeReadOnlyShell method to safely run whitelisted read-only commands,
prompting for user approval and integrating AI-suggested commands for filesystem context.
2026-03-07 18:50:38 +00:00
d74c613e0f chore(loader): add logging for safe commands config loading
Add debug print statements to indicate when the safe commands config file
is successfully loaded or when falling back to the built-in list.
2026-03-07 18:32:43 +00:00
f9d99527e0 feat(safety): make safe shell commands user-configurable
- Replace hardcoded safeCommands map with sync.OnceValue loading from ~/.config/grokkit/safe_shell_commands.yaml
- Provide fallback built-in safe list if config load fails
- Add safe_shell_commands.yaml.example for user reference
- Update safety check to use loaded map and prefix matching
2026-03-07 18:22:39 +00:00
7e4bdbc21c refactor(recipe/loader): expand safe shell commands and refine validation logic
- Renamed safeReadOnlyCommands to safeCommands for clarity.
- Added support for additional safe commands including GNU utilities (find, grep, which),
  Git commands (diff, branch), and various test runners (go test, make test/lint, pytest, etc.).
- Updated safety check to allow commands prefixed with any safe command for flexibility.
- Improved error message for unsafe commands.
2026-03-07 17:59:59 +00:00
b2172b8546 fix(recipe): improve unsafe shell command error message
Update the error message for unsafe shell commands to be more concise and user-friendly, removing redundant "ERROR:" prefix and "try again" instruction.
2026-03-07 17:41:09 +00:00
64fb748897 refactor(recipe): simplify path resolution and remove shell command execution
- Consolidate resolveWorkDir and remove resolvePackagePath for cleaner path handling.
- Eliminate executeShellCommands and related logic to disable shell execution in recipes.
- Simplify error messaging in loader for unsafe commands.
2026-03-07 17:34:59 +00:00
63e640c022 feat(recipe): add safety whitelist for allowed shell commands
Implement a read-only command whitelist in the recipe loader to reject
potentially dangerous shell commands, ensuring only safe operations like
ls, pwd, cat, etc., are permitted. This enhances security by preventing
execution of unauthorized commands in recipes.
2026-03-07 17:11:13 +00:00
aedf9cdf03 refactor(recipe/runner): enhance working directory resolution and shell command safety
- Rename and expand resolvePackagePath to resolveWorkDir, which now appends project_name if provided
- Update discoverFiles to use workDir and add default search pattern if none specified
- Modify executeShellCommands prompt to include workDir and enforce relative paths only
- Add safety checks to reject shell commands with ".." or absolute paths to prevent directory escapes
- Minor prompt and formatting adjustments for clarity and consistency
2026-03-07 16:18:29 +00:00
8efca62109 refactor(runner): improve package path resolution for consistency
- Introduce resolvePackagePath to handle ~ expansion, relative paths, and absolutization at the start.
- Update discoverFiles and executeShellCommands to use the resolved workDir.
- Remove redundant path logic from discoverFiles and shell execution for better maintainability.
2026-03-07 15:52:56 +00:00
0912aa7b89 feat(recipe): add safe shell command execution
Introduce a new mechanism in the recipe runner to execute whitelisted shell commands for steps like initialization, creation, or running tools (e.g., poetry, git). Commands are generated via AI prompt, parsed from JSON, validated against an allowed list, and executed within a strict working directory to ensure safety.
2026-03-07 15:34:50 +00:00
babc6e8599 chore: remove .grok/settings.json
Removed the settings file specifying the 'grok-code-fast-1' model to revert to default configuration.
2026-03-07 11:48:40 +00:00
fbf40e2f79 chore(gitignore): add .grok/ and *.patch ignores, remove grokkit
Update .gitignore to ignore new directories and patch files, and remove obsolete grokkit entry.
2026-03-07 11:47:28 +00:00
f36722ad2c feat(recipes): add template recipe and update final summary heading
- Added new template-recipe.md with structure for creating recipes.
- Changed "**Final Summary**" to "### Final Summary" in result-refactor.md for better formatting.
2026-03-07 00:53:38 +00:00
213a9869e6 docs(internal/recipe): update comment on search pattern default to "Go-style"
Changes the comment to describe the default as "Go-style" instead of the specific string for better generality.
2026-03-07 00:41:39 +00:00
757f422765 refactor(recipe): make search pattern configurable in file discovery
- Add SearchPattern field to Recipe struct
- Update discoverFiles to use configurable search pattern, defaulting to "if err != nil"
- Set default search_pattern in result-refactor.md recipe
2026-03-07 00:34:25 +00:00
ae8a199ece refactor(recipe): make file discovery fully generic using recipe metadata
Update discoverFiles to leverage recipe metadata for extensions and apply smart defaults more cleanly. Generalize logic with comments for future improvements, while retaining err != nil check for now.
2026-03-07 00:22:19 +00:00
8c14977ec6 feat(recipe): add smart defaults for package_path in file discovery
Enhance discoverFiles to respect explicit package_path param if provided.
If no param is given, intelligently default to 'src' directory if it exists,
otherwise fall back to project root (.).
2026-03-07 00:13:57 +00:00
f5c73ab291 refactor(recipe): add ResolvedParams for better param handling
Introduce ResolvedParams field to Recipe struct for storing resolved
parameter values from defaults and user overrides. Update loader to
populate and use it for template rendering. Adjust runner to use
ResolvedParams for root path and generalize file discovery.
2026-03-07 00:07:21 +00:00
1c79abce8d fix(recipe): add error handling to unified patch creation
Handle potential errors from file writes in createUnifiedPatch to prevent silent failures.
2026-03-06 23:57:22 +00:00
0e234419f4 feat(recipe): add fields for generic file discovery
Introduce ProjectLanguages and Extensions fields to the Recipe struct
to support option 2 for generic file discovery. Also update comments
for internal fields populated by the loader.
2026-03-06 23:55:54 +00:00
7ffbf352bc refactor(recipe): make file discovery generic using recipe metadata
- Build allowed extensions from recipe languages and extensions map
- Generalize filepath walking to filter by allowed extensions instead of hardcoding .go
- Retain Go-specific content check for now; can generalize later
- Simplify refactor JSON handling and patch creation by removing redundant comments and error checks
- Adjust comments and minor formatting for clarity
2026-03-06 23:51:42 +00:00
019ce1e95a refactor(cmd): improve boolean param handling and refine project root detection
- Enhance boolean parsing in runRecipe to handle variations like "1", "yes", "on" for true, and "0", "no", "off" for false, satisfying staticcheck.
- Reorganize and simplify findProjectRoot by removing checks for pyproject.toml and CMakeLists.txt, and adjusting .grokkit position.
2026-03-06 23:42:56 +00:00
95deb65f06 feat(recipe): add --param flag support and improve project root detection
- Introduce --param/-p flag to pass key=value parameters to recipes, parsed into a map with basic bool handling.
- Expand findProjectRoot to detect more project types (e.g., .gitignore, pyproject.toml, CMakeLists.txt).
- Clean up comments and minor refactoring in recipe resolution logic.
2026-03-06 23:37:00 +00:00
18bbb67789 refactor(recipe): enhance refactor handling with JSON collection and package path
- Introduce refactorJSONs to collect pure JSON from refactor steps for apply.
- Update discoverFiles to respect recipe's package_path parameter.
- Refine handleApplyStep to parse and apply changes more robustly.
- Remove outdated test output files.
2026-03-06 23:22:20 +00:00
405286abd2 refactor(recipes): update default package_path to internal/git
Changed the default value of the package_path parameter in result-refactor.md from "internal" to "internal/git".
2026-03-06 23:09:22 +00:00
a8208da4c1 refactor(recipe): implement one-file-at-a-time refactoring handler
Add refactorFiles to process discovered files individually, generating small JSON responses per file to avoid truncation. Update handleApplyStep to collect and parse multiple single-file JSONs into a unified patch. Switch discoverFiles comment to reflect real scanning. Add fallback default in Run for other steps.
2026-03-06 22:57:07 +00:00
0b5aa5eb57 refactor(recipe): improve error handling and restructure in runner
- Move FileChange struct to top-level for better organization.
- Enhance createUnifiedPatch with proper error handling on writes.
- Remove unused bufio import and update comments.
- Delete obsolete runner_test.go file.
2026-03-06 22:48:15 +00:00
7cb9eb3eb7 refactor(recipe): switch refactor step to strict JSON output
- Update result-refactor.md to output JSON array of file changes instead of code blocks
- Modify runner.go to parse JSON directly, removing regex-based extraction
- Add project_languages and extensions to recipe metadata
- Improve error handling and output consistency in steps
2026-03-06 22:40:29 +00:00
d4f3e3adbc refactor(recipe): update regex for robust Grok output matching
- Blank import bufio to avoid unused warnings.
- Refine regex to handle double-quoted format and fix backtick issues.
- Update comments for clarity on regex changes.
2026-03-06 22:25:39 +00:00
c5bdd44e55 fix(recipe): update regex to match Grok's current output style
Adjust the regex in handleApplyStep to flexibly match both old and new Grok formats for code blocks. Also, remove blank import for bufio as it's now used.
2026-03-06 22:21:58 +00:00
b2b8c1a482 refactor(recipe/runner): improve regex flexibility and simplify patch creation
- Update discoverFiles comment to be more concise.
- Enhance blockRe regex to optionally match leading "// " for filenames, supporting varied Grok output formats.
- Revise handleApplyStep comment to reflect regex changes.
- Simplify createUnifiedPatch by removing unnecessary error checks on fmt.Fprintf and defer closure.
2026-03-06 22:15:33 +00:00
40d40f7669 refactor(recipe): clean up runner implementation
- Adjust bufio import to blank (likely for side effects or pending use)
- Refine comments for clarity and remove unnecessary ones
- Split regex string to avoid backtick collisions in literals
- Add error handling to patch writing in createUnifiedPatch
- Minor formatting and defer close adjustments
2026-03-06 22:07:22 +00:00
7b415f8e26 feat(recipe): add file discovery and special step handling in runner
- Introduce discoverFiles function to scan Go files in 'internal' for error handling patterns.
- Add special case for "discover" or "find" steps to perform filesystem scans.
- Refine LLM prompting to enforce strict output format and shorten system prompt.
- Update apply/patch handling and unified patch creation with simplifications.
- Import bufio for potential future use and adjust regex for code block extraction.
2026-03-06 21:57:35 +00:00
852142730a refactor(recipe): enhance parsing for multi-line step content
Replace regex-based sub-section extraction with label-indexed parsing to
handle multi-line content, blank lines, and ensure reliability without
duplicates. Add clarifying comments for templates and summary extraction.
2026-03-06 21:48:35 +00:00
824bbcb85f refactor(recipe): simplify code block extraction regex
Update the regex in runner.go to use string concatenation for better readability.
Add test output files as fixtures for test verification.
2026-03-06 21:40:03 +00:00
b9de35f48b refactor(recipe): simplify apply step to dry-run only and add extraction tests
- Restrict filesystem interactions to apply/patch steps exclusively.
- Remove real apply logic with user confirmation; default to creating a patch file in dry-run mode.
- Update prompts, comments, and regex for better clarity and precision.
- Add unit tests for the extractCodeBlocks function to ensure reliable parsing.
2026-03-06 21:36:31 +00:00
5d0aec721d refactor(recipes): update result-refactor recipe for broader package path and error handling
- Change default package_path from internal/service to internal for wider applicability.
- Add instruction to output a specific message if no files are found or path does not exist in Step 1.
2026-03-06 21:11:17 +00:00
0ba427aaf6 feat(recipe): add apply/patch step handling with code block extraction and application
- Introduce special case in Runner.Run() for steps containing "apply" or "patch" in title.
- Add handleApplyStep to parse code blocks from previous results, support dry-run patch creation, or real application with user confirmation and backups.
- Implement extractCodeBlocks using regex to identify labelled Go code blocks.
- Add createUnifiedPatch for generating unified diff patches in dry-run mode.
- Remove final summary prompt and streamline recipe completion.
- Adjust system prompt for clarity.
2026-03-06 21:01:01 +00:00
d1ebd2af79 refactor(recipe): improve loading and execution logic
- Enhance recipe parsing in loader.go: extract overview, use split-based step extraction to avoid duplicates, refine final summary handling, and clean up comments/templates.
- Refine runner.go prompts: add Grok system message, simplify user prompts for conciseness, adjust result joining with separators, and remove unnecessary text.
2026-03-06 20:46:30 +00:00
5c67f78c27 feat(recipe): implement LLM-powered recipe execution
Add support for executing recipe steps via Grok API streaming, including parameter defaults from YAML, model selection via flags/config, previous step context, and a final summary prompt. Update runner to handle client and model, and refine loader to apply user params with fallbacks.
2026-03-06 20:32:04 +00:00
ec692b2086 docs(recipe): add feature overview for recipe system
Introduces a new Markdown file in todo/doing that outlines the recipe feature implementation, including key components, parsing logic, CLI integration, and progress checklist.
2026-03-06 19:16:57 +00:00
2cc728eed4 refactor(recipe): clean up comments, error handling, and output formatting
- Simplify import comments and error handling in cmd/recipe.go
- Streamline regex comment in internal/recipe/loader.go
- Enhance console output and add LLM placeholder in internal/recipe/runner.go
2026-03-06 19:00:16 +00:00
dcac119e57 fix(cmd/recipe): correct import path and add error handling for user input
- Updated import path for recipe package to match module name.
- Added error checking for fmt.Scanln to handle potential input errors gracefully.
2026-03-06 18:49:16 +00:00
8e414faa10 feat(cmd): add recipe run command
Implement the `recipe` command with `run` subcommand for executing transactional recipes.

- Resolve recipe paths: explicit, project-local (.grokkit/recipes), or global (~/.local/share/grokkit/recipes) with user prompt.
- Load and parse recipes using internal/recipe package.
- Integrate with root command and project root detection.
2026-03-06 18:45:03 +00:00
6bd72aad25 refactor(recipe): improve subRe regexp and add explanatory comments
Simplify the subRe regular expression by using a non-capturing group for the section labels instead of alternation, and switch the lookahead to a non-capturing group for consistency. Add comments to document the purpose of stepRe and subRe for better maintainability.
2026-03-06 18:39:56 +00:00
aa38e92fb5 feat(recipe): add recipe system for Result[T] refactoring
Implement recipe loading, parsing, and running infrastructure.
Add initial result-refactor recipe for converting Go error handling to monadic Result[T] style.
Includes markdown recipe definition, YAML frontmatter parsing, step extraction, and basic runner.
2026-03-06 18:35:58 +00:00
38 changed files with 2215 additions and 534 deletions

3
.gitignore vendored
View File

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

View File

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

View File

@ -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.

View File

@ -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.

562
README.md
View File

@ -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> [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
### 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

View File

@ -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) {

139
cmd/recipe.go Normal file
View File

@ -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(&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,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

View File

@ -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)**

View File

@ -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!

24
docs/index.md Normal file
View File

@ -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)

49
docs/user-guide/agent.md Normal file
View File

@ -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.

View File

@ -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.

45
docs/user-guide/chat.md Normal file
View File

@ -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"
```

View File

@ -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.

58
docs/user-guide/commit.md Normal file
View File

@ -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 "<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

@ -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 <command> --` followed by `Tab` to see available flags.

60
docs/user-guide/docs.md Normal file
View File

@ -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.

53
docs/user-guide/edit.md Normal file
View File

@ -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.

View File

@ -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.

52
docs/user-guide/index.md Normal file
View File

@ -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!

52
docs/user-guide/lint.md Normal file
View File

@ -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.

View File

@ -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 <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.

38
docs/user-guide/query.md Normal file
View File

@ -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.

102
docs/user-guide/recipe.md Normal file
View File

@ -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

48
docs/user-guide/review.md Normal file
View File

@ -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`.

31
docs/user-guide/safety.md Normal file
View File

@ -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 <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

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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
```

183
internal/recipe/loader.go Normal file
View File

@ -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
}

385
internal/recipe/runner.go Normal file
View File

@ -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)))
}
}
}

36
internal/recipe/types.go Normal file
View File

@ -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
}

View File

@ -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

View File

@ -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).