go mod init github.com/connorhough/smixgo mod tidymake buildmake installFor macOS (Apple Silicon):
make build-darwin-arm64For Linux (x86_64):
make build-linux-amd64smix pr review owner/repo pr_numberThis command will:
- Fetch code review feedback from the gemini-code-assist bot on the specified GitHub PR
- Process each feedback item with an LLM to generate code patches
- Launch Claude Code sessions for each generated patch
smix do "your natural language task"This command will translate your natural language request into a shell command.
Example:
smix do "list all files in the current directory"smix ask "your technical question"This command answers short technical questions using your configured LLM provider.
Example:
smix ask "what is FastAPI"smix supports multiple LLM providers. Configuration is stored in ~/.config/smix/config.yaml (or $XDG_CONFIG_HOME/smix/config.yaml).
On first run, a template configuration file is automatically created with sensible defaults.
- Requires: Claude Code CLI installed and authenticated
- Install: Visit https://claude.ai/code
- Models:
haiku,sonnet,opus
- Requires: Google AI Studio API key
- Setup: Set
SMIX_GEMINI_API_KEYenvironment variable - Get API Key: https://aistudio.google.com/apikey
- Models:
gemini-3-flash-preview,gemini-3-pro-preview
Global default (all commands use Claude):
provider: claude
model: sonnetPer-command customization (fast/cheap for ask/do, smart for pr):
provider: claude # global default
commands:
ask:
provider: gemini
model: gemini-3-flash-preview
do:
provider: gemini
model: gemini-3-flash-preview
pr:
provider: claude
model: sonnetOverride with flags:
smix ask --provider gemini --model gemini-3-pro-preview "what is FastAPI"
smix do --provider claude --model haiku "list all files"- CLI flags (
--provider,--model) - Command-specific config (
commands.ask.provider) - Global config (
provider)
Use --debug flag to see provider selection and configuration resolution:
smix ask --debug "what is FastAPI"To create a new version tag for releases:
git tag -a v0.1.0 -m "Release version 0.1.0"To push tags to remote repository:
git push origin --tagsTo create a tag with a semantic version:
git tag -a v1.0.0 -m "Release version 1.0.0"The versioning system will automatically use the most recent tag when building. If no tags exist, it will fall back to using the commit hash.
The cmd package contains only CLI wiring code (commands, flags), while the internal package contains all business logic. This separation:
- Makes business logic easier to test in isolation
- Allows for better code organization and reuse
- Follows the principle of separation of concerns
The version information is injected at build time using ldflags, which allows:
- Tracking of exact builds in production
- No need to hardcode version strings
- Consistent versioning across platforms
Error handling is centralized in main.go by having commands return errors rather than calling os.Exit() directly:
- Ensures consistent error handling across all commands
- Allows main.go to control exit codes
- Prevents commands from terminating the program prematurely
The configuration search paths follow XDG specifications and cross-platform conventions:
- Respects user's configuration directory preferences
- Provides fallback locations for broader compatibility
- Follows established conventions for CLI tools
The Makefile provides consistent builds across different environments:
- Standardized build process with version injection
- Cross-compilation targets for multiple platforms
- Clear separation of build, install, clean, and test operations
To add new commands following the established pattern:
-
Create
internal/newcommand/newcommand.gowith business logic:package newcommand func Run(param string) error { // Your business logic here return nil }
-
Create
cmd/newcommand.gowith Cobra command definition:package cmd import ( "github.com/connorhough/smix/internal/newcommand" "github.com/spf13/cobra" ) func newNewCommandCmd() *cobra.Command { var param string newCommandCmd := &cobra.Command{ Use: "newcommand", Short: "Description of newcommand", RunE: func(cmd *cobra.Command, args []string) error { return newcommand.Run(param) }, } newCommandCmd.Flags().StringVar(¶m, "param", "", "Parameter description") return newCommandCmd } func init() { rootCmd.AddCommand(newNewCommandCmd()) }