Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.14
3.12
86 changes: 86 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# custom-coding-agents

A [uv](https://docs.astral.sh/uv/) workspace containing two independently-packaged coding agents:

- **[pyagent](agents/fluent-pythonista/)** — an opinionated Python code reviewer, refactorer, and explainer. Named patterns from a built-in playbook, whole-codebase two-phase refactor flow, and RAG over a local documentation set.
- **[archagent](agents/software-architect/)** — a conversational software-architecture advisor grounded in DDD, Clean, Hexagonal, and Onion Architecture. Tracks decisions per project and can propose (and, with opt-in, apply) file edits.

Each agent is its own package with its own `pyproject.toml` and script entry point. A single `uv.lock` at the root covers the whole workspace.

## Quickstart

```bash
# Install uv if you don't have it.
curl -LsSf https://astral.sh/uv/install.sh | sh

# From the repo root:
uv sync --extra dev # resolves both agents' dependencies into one venv

# Set your API key (both agents read ANTHROPIC_API_KEY).
cp .env.example .env
# edit .env

# Run either agent from the root — no `cd` needed.
uv run pyagent --help
uv run pyagent refactor path/to/project/ # full two-phase codebase refactor
uv run pyagent refactor path/to/file.py # single-file refactor
uv run pyagent review path/to/file.py # opinionated code review
uv run pyagent chat --path path/to/project/ # interactive chat about a codebase

uv run archagent --help
uv run archagent chat # interactive architecture advisor
uv run archagent chat -p my-service # scope decisions to a named project
uv run archagent list-sessions # prior sessions
uv run archagent info # resolved config + KB stats
```

## Running tests

```bash
uv run pytest agents/fluent-pythonista/test_core.py -v
uv run pytest agents/software-architect/test_archagent.py -v
```

## Repo layout

```
custom-coding-agents/
├── pyproject.toml # workspace root
├── uv.lock # single lock for the whole workspace
├── agents/
│ ├── fluent-pythonista/ # pyagent package
│ │ ├── pyproject.toml
│ │ ├── src/pyagent/
│ │ ├── test_core.py
│ │ └── README.md
│ └── software-architect/ # archagent package
│ ├── pyproject.toml
│ ├── src/archagent/
│ ├── test_archagent.py
│ └── README.md
├── docs/
│ ├── architecture/ # consumed by archagent's RAG index
│ └── python/ # consumed by pyagent's RAG index
└── collage-maker-refactor-example/ # sample codebase used to exercise pyagent
```

Each agent can also be used standalone from its own directory (`cd agents/fluent-pythonista && uv run pyagent …`) — workspace membership is additive, not exclusive.

## Configuration

Both agents read `ANTHROPIC_API_KEY` from the environment or a local `.env` file at the workspace root.

Agent-specific env vars:

| Env var | Agent | Purpose |
|---------|-------|---------|
| `ANTHROPIC_API_KEY` | both | Required. API key for Claude. |
| `AGENT_WORKSPACE` | archagent | Optional. Directory the agent is allowed to write into — gates the `write_file` / `edit_file` tools. Off by default. |
| `HF_TOKEN` | archagent | Optional. Hugging Face token used when downloading the sentence-transformer embedding model for RAG. |
| `PYAGENT_*` | pyagent | Override `model`, `max_tokens`, `batch_max_tokens`, `context_token_budget`, `log_level`, `docs_path`. |
| `ARCHAGENT_*` | archagent | Override `model`, `max_tokens`, `log_level`, `docs_path`. |

See each agent's own README for command-level detail:

- [pyagent README](agents/fluent-pythonista/README.md)
- [archagent README](agents/software-architect/README.md)
158 changes: 158 additions & 0 deletions agents/fluent-pythonista/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# pyagent

An opinionated Python code review, refactoring, and explanation agent powered by Claude. Part of the [custom-coding-agents](../../README.md) workspace — see the workspace README for the shared install flow.

## Quickstart

```bash
# Install uv if you don't have it
curl -LsSf https://astral.sh/uv/install.sh | sh

# From the workspace root — one lockfile resolves both agents into a single venv.
uv sync --extra dev

# Set your API key (the workspace .env at the repo root is read automatically).
cp .env.example .env
# Edit .env and add your ANTHROPIC_API_KEY

# Run a code review
uv run pyagent review path/to/file.py

# Refactor a single file
uv run pyagent refactor path/to/file.py

# Refactor an entire codebase (full two-phase: plan, then batched execute)
uv run pyagent refactor path/to/project/

# Narrow refactor focused on a specific concern (single context-packed pass)
uv run pyagent refactor path/to/project/ -i "modernize type hints"

# Explain a file
uv run pyagent explain path/to/file.py

# Start an interactive chat session
uv run pyagent chat --path path/to/project/
```

## Commands

| Command | Description |
|---------|-------------|
| `review <path>` | Review code for correctness, style, and best practices |
| `refactor <path>` | Apply named refactoring patterns from the playbook |
| `explain <path>` | Explain code structure, patterns, and design decisions |
| `chat` | Interactive conversation about a codebase |
| `info` | Show configuration and knowledge base stats |

All commands accept `--instructions` / `-i` (or `--question` / `-q` for explain) for additional guidance, and `--model` / `-m` to override the default model. `review`, `refactor`, and `explain` all auto-detect file vs directory paths — no mode flag required. `pyagent --version` prints the installed version and exits.

### Refactor modes

`refactor` picks its mode implicitly from the path and whether you supplied `-i`:

| Path | `-i` instructions | Mode |
|------|-------------------|------|
| file | n/a | single file, refactored in place with surrounding package context |
| directory | _(none)_ | **full** codebase refactor in two phases (plan → batched execution) |
| directory | focused instructions | **partial** refactor — a single context-packed pass over the highest-priority files matching your instructions |

The intuition: a bare `refactor ./proj` means "refactor the whole project", so every file gets a turn. A `refactor ./proj -i "modernize the auth module"` is narrow and focused, so only the files relevant to the instructions are touched — faster and cheaper.

Two flags override the heuristic when needed:

| Flag | Description |
|------|-------------|
| `--full` | Force the two-phase codebase refactor (directory only) |
| `--partial` | Force the context-packed single-pass refactor (directory only) |
| `--dry-run` | Show proposed changes without writing any files |
| `--no-confirm` / `-y` | Apply changes without a confirmation prompt |
| `--no-backup` | Skip creating backup files before writing |

The full mode works in two phases:

1. **Planning** — The LLM receives the full structural summary of the codebase and produces a named, actionable refactoring strategy (themes, order of operations, file-specific notes). The plan is persisted to `.pyagent/last_plan.json` and `last_plan.md`.
2. **Execution** — All source files are grouped into token-budget-constrained batches. Each batch is refactored with the overall plan as context. Per-batch output is persisted to `.pyagent/batches/batch_NNN.md` for audit, and a plan-adherence check flags any batch that ignored the strategy (and retries it once).

The same diff-review → confirm → backup → write workflow applies in every mode — you see every proposed change before anything is written to disk.

```bash
# Full refactor of the whole project (implicit — directory, no -i)
uv run pyagent refactor ./my_project

# Narrow refactor with a focus (implicit — directory + -i)
uv run pyagent refactor ./my_project -i "modernize type hints and remove legacy patterns"

# Force the full mode even when -i is narrow
uv run pyagent refactor ./my_project -i "clean up the models" --full

# Preview without writing
uv run pyagent refactor ./my_project --dry-run
```

## Architecture

```
src/pyagent/
├── __main__.py # CLI entrypoint (typer + rich)
├── agent.py # Core orchestration loop
├── config.py # Pydantic settings (PYAGENT_* env vars)
├── context.py # Codebase ingestion, AST parsing & file batching
├── logging.py # Structured logger factory
├── memory.py # Conversation state management
├── plan_model.py # RefactorPlan / FileChange schemas
├── prompts.py # Prompt templates per capability
├── rag.py # Documentation retrieval
├── writer.py # Diff rendering, backups, and on-disk writes
└── tools/
├── base.py # Tool protocol
├── reviewer.py # Code review tool
├── refactor.py # Refactoring tool (single-file + batch)
└── explainer.py # Explanation tool
```

## Configuration

All settings are read from environment variables (optionally via a `.env` file at the workspace root) and resolved by [`pyagent.config.Settings`](src/pyagent/config.py).

| Env var | Default | Purpose |
|---------|---------|---------|
| `ANTHROPIC_API_KEY` | _required_ | API key for Claude access |
| `PYAGENT_MODEL` | `claude-sonnet-4-20250514` | Model ID to use |
| `PYAGENT_MAX_TOKENS` | `8000` | Upper bound on per-turn model output |
| `PYAGENT_BATCH_MAX_TOKENS` | `20000` | Per-batch token budget during two-phase codebase refactors |
| `PYAGENT_CONTEXT_TOKEN_BUDGET` | `30000` | Budget for single-pass context-packed refactors |
| `PYAGENT_LOG_LEVEL` | `INFO` | Log level |
| `PYAGENT_DOCS_PATH` | `<repo>/docs/python` | Directory of `.md` files indexed for RAG |

## Knowledge Base

The agent's opinions are codified in six documents under [`docs/python/`](../../docs/python/):

| Document | Purpose |
|----------|---------|
| `python_standards.md` | Language-level style, idioms, and conventions |
| `tech_stack.md` | Preferred tools and libraries with rationale |
| `anti_patterns.md` | Code smells and mistakes to flag |
| `refactoring_playbook.md` | Named patterns with before/after examples |
| `architecture_patterns.md` | Module design, DI, and structural best practices |
| `review_rubric.md` | Severity levels, scoring dimensions, output format |

These docs are retrieved via RAG at runtime, so you can edit them to tune the agent's behavior without touching code.

## Development

```bash
# Install with dev dependencies (from the workspace root or from this package).
uv sync --extra dev

# Run this package's tests.
uv run pytest agents/fluent-pythonista/test_core.py -v

# Lint and format.
uv run ruff check agents/fluent-pythonista/
uv run ruff format agents/fluent-pythonista/
```

## Related

- [archagent](../software-architect/) — the architecture-advisor companion that lives in the same workspace.
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
[project]
name = "pyagent"
version = "0.1.0"
description = "An opinionated Python code review, refactoring, and explanation agent."
requires-python = ">=3.12"
dependencies = [
"anthropic>=0.40",
"pydantic>=2.0",
"pydantic-settings>=2.0",
"typer>=0.12",
"rich>=13.0",
]

[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-asyncio>=0.23",
"pytest-cov>=5.0",
"ruff>=0.8",
]

[project.scripts]
pyagent = "pyagent.__main__:app"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/pyagent"]

[tool.ruff]
target-version = "py312"
line-length = 88

[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"UP", # pyupgrade
"B", # flake8-bugbear
"SIM", # flake8-simplify
"TCH", # type-checking imports
"RUF", # ruff-specific rules
"S", # flake8-bandit (security)
"C4", # flake8-comprehensions
"PTH", # flake8-use-pathlib
"RET", # flake8-return
"ARG", # flake8-unused-arguments
]

[tool.ruff.lint.isort]
known-first-party = ["pyagent"]

[tool.pytest.ini_options]
testpaths = ["tests"]
[project]
name = "pyagent"
version = "0.1.0"
description = "An opinionated Python code review, refactoring, and explanation agent."
requires-python = ">=3.12"
dependencies = [
"anthropic>=0.40",
"pydantic>=2.0",
"pydantic-settings>=2.0",
"typer>=0.12",
"rich>=13.0",
]
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"pytest-asyncio>=0.23",
"pytest-cov>=5.0",
"ruff>=0.8",
]
[project.scripts]
pyagent = "pyagent.__main__:app"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/pyagent"]
[tool.ruff]
target-version = "py312"
line-length = 88
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"UP", # pyupgrade
"B", # flake8-bugbear
"SIM", # flake8-simplify
"TCH", # type-checking imports
"RUF", # ruff-specific rules
"S", # flake8-bandit (security)
"C4", # flake8-comprehensions
"PTH", # flake8-use-pathlib
"RET", # flake8-return
"ARG", # flake8-unused-arguments
]
[tool.ruff.lint.isort]
known-first-party = ["pyagent"]
[tool.pytest.ini_options]
testpaths = ["tests"]
Loading