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