Expands README with complete config.yaml reference, CLI options table, skills documentation, and updated command list. Removes the old roadmap (all phases complete). Updates tweaks.md with current design notes. Adds .sneakycode/ to .gitignore and includes superpowers design specs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
224 lines
8.6 KiB
Markdown
224 lines
8.6 KiB
Markdown
# SneakyCode
|
|
|
|
A privacy-first, locally-running Python coding agent that uses a local LLM (via Ollama) to perform autonomous coding tasks inside a project directory.
|
|
|
|
SneakyCode accepts natural language tasks and executes them using a defined toolset for filesystem operations, shell execution, code search, and file manipulation. It runs a ReAct-style tool-call loop: send conversation history to the LLM, receive tool calls, execute them with permission checks, and feed results back until the task is complete.
|
|
|
|
## Prerequisites
|
|
|
|
- Python 3.11+
|
|
- [Ollama](https://ollama.ai/) running locally with a model that supports function calling (e.g., `qwen3.5`, `llama3.1`, `mistral-nemo`)
|
|
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
# Clone the repository
|
|
git clone <repo-url>
|
|
cd SneakyCode
|
|
|
|
# Install dependencies
|
|
uv sync --dev
|
|
|
|
# Or with pip
|
|
pip install -e ".[dev]"
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Edit `config/config.yaml` to configure the agent. The full configuration reference:
|
|
|
|
```yaml
|
|
llm:
|
|
model: "qwen3.5:latest" # Ollama model name
|
|
endpoint: "http://localhost:11434" # Ollama endpoint
|
|
api_path: "/v1/chat/completions" # API endpoint path
|
|
temperature: 0.1 # Sampling temperature
|
|
max_tokens: 4096 # Maximum tokens in LLM response
|
|
timeout: 120 # Request timeout in seconds
|
|
max_retries: 3 # Retry attempts on transient errors
|
|
retry_backoff_base: 1.0 # Exponential backoff base (seconds)
|
|
retry_backoff_max: 30.0 # Maximum backoff seconds
|
|
|
|
agent:
|
|
max_iterations: 25 # Max tool-call iterations per turn
|
|
max_conversation_tokens: 32000 # Token budget for conversation
|
|
workspace_root: "." # Project directory for file operations
|
|
truncation_keep_recent: 10 # Messages preserved during truncation
|
|
truncation_threshold: 0.85 # Budget fraction that triggers truncation
|
|
|
|
session:
|
|
session_dir: ".sneakycode/sessions" # Directory for session files
|
|
auto_save: true # Save session after each turn
|
|
max_session_age_hours: 72 # Auto-cleanup old sessions
|
|
offer_resume: true # Offer to resume on startup
|
|
|
|
permissions:
|
|
auto_approve: [read_file, list_dir, grep_files, find_files, finish]
|
|
prompt_user: [write_file, delete_file, run_command, str_replace, patch_apply, make_dir]
|
|
deny: []
|
|
|
|
tools:
|
|
shell:
|
|
allowed_commands: # Commands the LLM may run
|
|
- git
|
|
- python
|
|
- pip
|
|
- pytest
|
|
- ruff
|
|
- ls
|
|
- cat
|
|
- head
|
|
- tail
|
|
- wc
|
|
- diff
|
|
- grep
|
|
- find
|
|
- echo
|
|
denied_commands: # Blocked commands
|
|
- rm -rf /
|
|
- sudo
|
|
- curl
|
|
- wget
|
|
max_output_bytes: 65536 # Max captured output size (bytes)
|
|
filesystem:
|
|
max_file_size_bytes: 1048576 # 1 MB — max file size for read/write
|
|
binary_detection: true # Detect and reject binary files
|
|
|
|
display:
|
|
show_tool_calls: true # Show tool call details in output
|
|
show_token_usage: true # Show token usage stats
|
|
stream_output: true # Stream LLM output to terminal
|
|
|
|
skills:
|
|
enabled: true # Enable the skills system
|
|
directories: # Directories to scan for skill files
|
|
- ".sneakycode/skills"
|
|
|
|
debug:
|
|
enabled: false # Enable debug logging
|
|
log_dir: ".sneakycode/logs" # Debug log directory
|
|
max_files: 10 # Max debug log files to retain
|
|
```
|
|
|
|
Environment variable `SNEAKYCODE_CONFIG` can override the config file path.
|
|
|
|
## Usage
|
|
|
|
```bash
|
|
# Start the interactive TUI
|
|
sneakycode
|
|
|
|
# Open a specific project directory
|
|
sneakycode /path/to/project
|
|
|
|
# Or run directly
|
|
python -m app.main
|
|
|
|
# With options
|
|
sneakycode --config path/to/config.yaml --verbose --log-file sneakycode.log
|
|
```
|
|
|
|
### CLI Options
|
|
|
|
| Option | Description |
|
|
|--------------------------|--------------------------------------------------|
|
|
| `DIRECTORY` | Project directory to use as workspace root |
|
|
| `--config PATH` | Path to config YAML file (default: `config/config.yaml`) |
|
|
| `-v`, `--verbose` | Enable verbose (DEBUG) logging |
|
|
| `--log-file PATH` | Path to log file for persistent logging |
|
|
|
|
### REPL Commands
|
|
|
|
| Command | Description |
|
|
|-------------------|----------------------------------------------------|
|
|
| `/help` | Show available commands |
|
|
| `/quit` | Save session and exit (also `/exit`, `/bye`) |
|
|
| `/history` | Show conversation history |
|
|
| `/clear` | Clear conversation history |
|
|
| `/save` | Manually save session |
|
|
| `/session` | Show session info (messages, tokens, start time) |
|
|
| `/models` | List available Ollama models |
|
|
| `/models <name>` | Switch to a different model |
|
|
| `/skills` | List available skills |
|
|
|
|
### Session Persistence
|
|
|
|
Sessions are automatically saved after each agent turn and on exit. On startup, SneakyCode offers to resume the most recent session for the current workspace.
|
|
|
|
Session files are stored in `.sneakycode/sessions/` within the workspace root (configurable via `session.session_dir`).
|
|
|
|
## Available Tools
|
|
|
|
SneakyCode provides tools across 6 categories. See [docs/tools.md](docs/tools.md) for the full reference.
|
|
|
|
| Category | Tools | Permission |
|
|
|------------|-------------------------------------------------|---------------|
|
|
| Read | `read_file`, `list_dir` | Auto-approved |
|
|
| Search | `grep_files`, `find_files` | Auto-approved |
|
|
| Write | `write_file`, `make_dir`, `delete_file` | User confirm |
|
|
| Edit | `str_replace`, `patch_apply` | User confirm |
|
|
| Shell | `run_command` | User confirm |
|
|
| Control | `finish` | Auto-approved |
|
|
| Skills | `load_skill` | Auto-approved |
|
|
|
|
The `load_skill` tool is available when `skills.enabled` is `true` in the config. It allows the LLM to load skill instructions from the configured skill directories.
|
|
|
|
## Skills
|
|
|
|
SneakyCode includes a skills system that lets you provide reusable instruction sets to the LLM. Skills are markdown files placed in `.sneakycode/skills/` (or any directory listed in `skills.directories`).
|
|
|
|
Skills are auto-discovered on startup. The LLM can load them via the `load_skill` tool, and you can list available skills with the `/skills` command.
|
|
|
|
To create a skill, add a `.md` file to your skills directory with a descriptive filename (e.g., `refactoring.md`). The file content is injected into the conversation when the skill is loaded.
|
|
|
|
## Development
|
|
|
|
```bash
|
|
# Run tests
|
|
.venv/bin/python -m pytest tests/ -v
|
|
|
|
# Run with coverage
|
|
.venv/bin/python -m pytest tests/ --cov=app
|
|
|
|
# Lint
|
|
.venv/bin/ruff check app/ tests/
|
|
|
|
# Format
|
|
.venv/bin/ruff format app/ tests/
|
|
```
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
app/
|
|
├── agent/ # Agent loop and session context
|
|
├── models/ # Pydantic config and message schemas
|
|
├── services/ # LLM client, streaming, permissions, session persistence
|
|
├── tools/ # Tool implementations (one file per group)
|
|
├── ui/ # Textual TUI application and widgets
|
|
└── utils/ # Logging, display, file helpers, token counter
|
|
config/
|
|
└── config.yaml # Application configuration
|
|
tests/
|
|
├── unit/ # Unit tests for individual components
|
|
└── integration/ # End-to-end workflow tests with mocked LLM
|
|
```
|
|
|
|
## Architecture
|
|
|
|
SneakyCode follows a **ReAct-style** agent pattern:
|
|
|
|
1. User provides a task in natural language
|
|
2. Agent sends conversation history + tool schemas to the LLM
|
|
3. LLM responds with either text (task complete) or tool calls
|
|
4. Agent executes tool calls with permission checks
|
|
5. Results are fed back to the LLM for the next iteration
|
|
6. Loop continues until the LLM produces a plain-text response or calls `finish`
|
|
|
|
The LLM client is abstracted behind an OpenAI-compatible interface, so any endpoint implementing the `/v1/chat/completions` SSE streaming protocol works as a backend.
|
|
|
|
## License
|
|
|
|
MIT
|