Retrieval-grounded, guardrail-first remediation from incident evidence to verified draft PR.
RepoMedic is a self-hosted AI remediation assistant for engineering teams that want AI help with production incidents without giving the model direct authority over their repositories. It ingests incidents from manual reports, logs, traces, or webhooks, retrieves repository-specific context, asks a configured LLM for a structured remediation plan, applies deterministic safety checks, optionally patches an isolated workspace, runs configured verification commands, and can open a controlled GitHub draft PR.
RepoMedic does not auto-merge, mutate production, or push to default branches. Its output is designed to be inspected by engineers.
AI code-fix tools are risky when they jump from an error message straight to a patch. RepoMedic adds the missing operational layers:
- repository-specific retrieval before remediation
- strict model output schemas
- path, patch-size, and branch guardrails outside the model
- isolated workspace patching
- build/test/lint verification before PR-ready status
- durable runs, jobs, incidents, PR records, and metrics
- a server-rendered operations dashboard for normal use
It is useful for teams experimenting with guarded AI remediation, LLMOps, incident response automation, and draft-PR workflows over GitHub repositories.
- Operations dashboard for repositories, incidents, runs, jobs, PR attempts, collectors, signals, metrics, and knowledge status.
- Automation preflight for repo and collector readiness before autonomous analysis, patching, or draft PR creation.
- RAG knowledge base for runbooks, repository docs, fix summaries, and historical incidents.
- Postgres + pgvector retrieval by default, with optional Qdrant support.
- Optional LlamaIndex chunking for longer knowledge documents.
- Observability intake from OpenSearch-compatible logs, Jaeger traces, signed OpenSearch webhooks, and signed GitHub webhooks.
- Durable collector run history with signal counts, queued jobs, skipped reasons, warnings, cursor state, and errors.
- Durable repo configuration for allowed paths, blocked paths, verification commands, local repo paths, and automation defaults.
- Postgres-backed remediation queue processed by
repomedic-worker. - Task-based LLM routing for incident analysis and patch generation.
- LLM providers for Ollama, vLLM/OpenAI-compatible endpoints, Claude API, Codex CLI, and Claude Code CLI.
- Patch guardrails for retrieval support, groundedness, confidence, risk, changed file count, patch size, allowed paths, and blocked paths.
- Isolated workspace patching before any draft PR action.
- Verification runner for configured build, test, and lint commands.
- Controlled GitHub draft PR creation through GitHub CLI or GitHub App
installation tokens for verified
pr_readyruns. - MCP server runtime for Claude Code, Claude Desktop, Codex, Cursor, and other MCP-aware clients to call guarded RepoMedic tools directly.
- Metrics and audit records for provider/model attribution, verification status, risk, confidence, draft PR success, and failure stages.
The screenshots below were captured from the real local dashboard at
/dashboard against a clean database.
Overview tab with first-run counters and empty states for incidents and runs.
Pull Requests tab empty state, which points users to PR-ready run details.
Additional useful screenshots to capture later from a clean demo dataset:
- incident detail with queued analysis action
- run detail with verification output and changed files
- collector setup tab with an OpenSearch or Jaeger config
- knowledge tab after ingesting sample runbooks
- A user registers a repository policy or submits inline policy with an incident analysis request.
- A manual incident, collector signal, or signed webhook creates or updates a durable incident record.
- The API queues a remediation job when requested or when repo/collector automation allows it.
- The worker retrieves relevant repository context from the selected vector backend.
- The incident analysis provider returns strict JSON with diagnosis, targets, risk notes, and a fix plan.
- If patching is enabled, a dedicated patch-generation task uses exact local file context to produce a focused diff.
- Guardrails decide whether the diff is safe enough to apply in an isolated workspace.
- Verification commands from repo config run without shell-control syntax.
- RepoMedic persists run metrics and exposes the result through the API and dashboard.
- A verified
pr_readyrun can create a GitHub draft PR against explicitly allowlisted safe branches.
sequenceDiagram
participant User as Engineer or Collector
participant API as FastAPI API
participant DB as Postgres + pgvector
participant Worker as repomedic-worker
participant LLM as LLM provider
participant Git as Local workspace + git
participant GH as GitHub PR client
User->>API: Register repo / submit incident / run collector
API->>DB: Persist repo config, signal, incident, job
Worker->>DB: Claim queued remediation job
Worker->>DB: Retrieve top-k knowledge context
Worker->>LLM: Incident analysis JSON request
LLM-->>Worker: Structured remediation output
Worker->>LLM: Patch generation request when enabled
LLM-->>Worker: Unified diff or no diff
Worker->>Git: Clone local repo into isolated workspace
Worker->>Git: Apply patch and collect changed files
Worker->>Git: Run configured build/test/lint commands
Worker->>DB: Persist run, evaluation, verification
Worker->>GH: Create draft PR when allowed and verified
Worker->>DB: Persist draft PR record
User->>API: Review dashboard, run, and PR detail
flowchart LR
subgraph UI["User interfaces"]
Dashboard["FastAPI/Jinja dashboard"]
REST["REST API"]
MCP["MCP server"]
end
subgraph Intake["Incident intake"]
Manual["Manual incident API/UI"]
OpenSearch["OpenSearch collector/webhook"]
Jaeger["Jaeger collector"]
GitHubWebhook["GitHub webhook"]
end
subgraph Core["RepoMedic services"]
API["repomedic-api"]
MCPService["repomedic-mcp"]
Collector["repomedic-collector"]
Worker["repomedic-worker"]
Knowledge["Knowledge service"]
Guardrails["Guardrails + patch gate"]
Verification["Verification runner"]
end
subgraph Storage["Persistence"]
Postgres["Postgres"]
Pgvector["pgvector embeddings"]
Qdrant["optional Qdrant"]
end
subgraph External["External tools"]
LLM["Ollama / vLLM / Claude / Codex CLI"]
GitWorkspace["Local git workspace"]
GHCLI["GitHub CLI"]
end
Dashboard --> API
REST --> API
MCP --> MCPService
Manual --> API
OpenSearch --> Collector
Jaeger --> Collector
GitHubWebhook --> API
Collector --> API
MCPService --> Postgres
MCPService --> Knowledge
MCPService --> GHCLI
API -->|persist config, incidents, jobs| Postgres
Worker -->|claim jobs| Postgres
Worker --> Knowledge
Knowledge --> Pgvector
Knowledge --> Qdrant
Pgvector --> Postgres
Worker --> LLM
Worker --> Guardrails
Worker --> GitWorkspace
Worker --> Verification
Worker --> GHCLI
Worker --> Postgres
- FastAPI serves both JSON APIs and the Jinja2 dashboard.
- Postgres is the durable store for repo configs, incidents, events, jobs, signals, runs, PR records, and knowledge documents.
- pgvector is the default retrieval backend; Qdrant is available through a Docker Compose profile.
- The queue is a Postgres table claimed by the worker with database locking.
- Verification commands come from repo config, not model output.
- Draft PRs require
pr_ready, passing verification, a workspace diff, and allowlisted repository/base branch settings. - The dashboard shows warn-only setup readiness for repository policy, collectors, LLM provider credentials/tooling, knowledge indexing, workers, and draft PR safety. These warnings do not block saving configs.
- Repo and collector preflight checks show blockers separately from warnings for analysis, patch, and draft-PR modes. The same service powers REST, dashboard, and MCP output.
repomedic-mcpexposes RepoMedic as an MCP server over local stdio or trusted-network Streamable HTTP. It reuses the same safety gates as REST.- Controlled MCP client tool-use can collect extra context during remediation only from explicit per-repo policies and global runtime allowlists.
- Docker Compose is the only orchestration shipped in this repo. No Kubernetes manifests or Aspire app host are present.
- RepoMedic does not expose arbitrary external tool execution, shell tools, production mutation, ready-PR conversion, auto-merge, or default-branch mutation.
apps/
api/ FastAPI app, REST routes, Jinja dashboard, static CSS
worker/ Postgres-backed remediation worker
collector/ Polling process for enabled collectors
mcp/ MCP server tools/resources for AI clients
application/ Shared use cases used by API and MCP adapters
core/ Settings, LLM task selection, structured logging
domain/
collectors/ Collector result and severity domain logic
incidents/ Incident normalization
knowledge/ RAG models, ports, indexing, and knowledge service
metrics/ Run metric domain models and ports
remediation/ Analysis service, prompts, guardrails, patch gate
repositories/ Repository policy rules
verification/ Verification result models
infrastructure/
collectors/ OpenSearch, Jaeger, webhook normalization, intake runner
db/ SQLAlchemy models, sessions, operations, run metrics
embeddings/ sentence-transformers embedding provider
git/ Local workspace and GitHub draft PR clients
indexing/ Optional LlamaIndex adapter
llm/ Ollama, OpenAI-compatible/vLLM, Claude, Codex providers
retrieval/ pgvector and Qdrant knowledge repositories
verification/ Command runner
schemas/ Pydantic API request/response models
migrations/ Alembic migrations
prompts/ Incident analysis and patch-generation prompt templates
examples/ Sample incidents, policies, runbooks, and repo docs
docs/ Architecture, API, safety, demo, and operations docs
docs/images/ README screenshots captured from the running dashboard
tests/ Unit and integration-style tests
No GIFs are committed. The lightweight Mermaid flow below shows the real runtime path from observability signal to draft PR.
flowchart TD
A["Log, trace, webhook, or manual incident"] --> B["Incident record"]
B --> C{"Auto queue enabled or user queues analysis?"}
C -- No --> D["Incident stays reviewable in dashboard"]
C -- Yes --> E["remediation_jobs row"]
E --> F["Worker claims job"]
F --> G["Retrieve knowledge context"]
G --> H["Structured incident analysis"]
H --> I{"Patch requested?"}
I -- No --> J["Suggestion-only run"]
I -- Yes --> K["Patch generation with local file context"]
K --> L{"Guardrails and patch gate pass?"}
L -- No --> J
L -- Yes --> M["Apply diff in isolated workspace"]
M --> N["Run configured verification"]
N --> O{"Verification passed?"}
O -- No --> J
O -- Yes --> P["pr_ready run"]
P --> Q{"Draft PR allowed?"}
Q -- No --> R["Review run in dashboard/API"]
Q -- Yes --> S["GitHub draft PR"]
- Python
3.12(.python-versionis3.12) - Docker and Docker Compose
uvfor the same local workflow used by CI- Git
- GitHub CLI
ghor GitHub App credentials if you want draft PR creation - Optional: Ollama, vLLM-compatible serving, Qdrant, Codex CLI, Claude Code CLI, or an Anthropic API key depending on the provider/backend you choose
git clone https://github.com/mecemis/repo-medic.git
cd repo-medic
cp .env.example .envIf local port 5432 is already used, set POSTGRES_PORT in .env before
starting the stack. Host-side commands must use the same port in DATABASE_URL.
Set the host folder that contains the repos RepoMedic may patch. Compose mounts
that folder at /host-repos in the API, worker, collector, and MCP containers:
printf '\nREPOMEDIC_HOST_REPOS_ROOT=%s\n' "$HOME/code" >> .envFor Docker-first use, set each repository config local_repo_path to the
container path, for example /host-repos/example-service. If a config already
contains a host path such as /Users/me/code/example-service,
RepoMedic uses REPO_PATH_MAPPINGS to resolve it to /host-repos/example-service
inside the containers. Compose fills that mapping from
REPOMEDIC_HOST_REPOS_ROOT; advanced users can set comma-separated mappings
manually, for example:
REPO_PATH_MAPPINGS=/Users/me/code=/host-repos,/srv/repos=/reposModel providers run where the worker runs. In the default Docker image,
ollama, vllm, openai_compatible, and claude_api are the practical
container-friendly choices. If you do not have provider API keys and want to use
authenticated local CLIs, set CLI_RUNTIME=host_worker, do not rely on the
Docker worker for remediation jobs, and run the worker from the host where
codex, claude, and gh are installed.
For local CLI mode:
# Add these to .env:
# CLI_RUNTIME=host_worker
# LLM_PROVIDER=codex_cli
# INCIDENT_ANALYSIS_LLM_PROVIDER=codex_cli
# PATCH_GENERATION_LLM_PROVIDER=codex_cli
# PULL_REQUEST_CLIENT=gh_cli
docker compose up -d postgres api collector mcp
docker compose stop worker
codex --version
claude --version
gh auth status -h github.com
gh auth setup-git -h github.com
set -a
source .env
set +a
DATABASE_URL="postgresql+asyncpg://repomedic:repomedic@localhost:${POSTGRES_PORT:-5432}/repomedic" \
uv run python -m apps.worker.mainIn this mode, queued jobs and automatic draft PR creation run through the host worker. Direct dashboard/API draft PR creation still runs in the API process; if the API is inside Docker, use auto PR creation from the host worker or run the API on the host too.
The dashboard Overview tab includes an AI Runtime table that shows whether
each provider is usable from the current API/worker runtime, which model it will
use, and the Docker-specific action needed when it is blocked. Use Test
provider to run an active probe: Ollama checks /api/tags,
OpenAI-compatible/vLLM checks /v1/models, Claude API checks /v1/models, and
CLI providers run --version in the same runtime that would execute jobs. The
same data is available for scripts:
curl http://localhost:8000/api/v1/runtime/providers
curl "http://localhost:8000/api/v1/runtime/providers?provider=ollama"
curl -X POST http://localhost:8000/api/v1/runtime/providers/ollama/probeThe Repos tab includes Queue smoke for each registered repository. It creates a synthetic incident and queued job through the same queue used by collectors. The worker still uses the repository's stored provider, patch, verification, guardrail, and draft-PR settings.
docker compose up --build -d
docker compose exec api alembic upgrade head
curl http://localhost:8000/api/v1/healthzOpen:
http://localhost:8000/dashboard
The default Compose stack includes:
repomedic-apirepomedic-workerrepomedic-collectorrepomedic-mcprepomedic-postgres
Start optional services only when you need them:
docker compose --profile ollama up --build -d
docker compose exec ollama ollama pull ${OLLAMA_MODEL:-deepseek-coder:33b}
RETRIEVAL_BACKEND=qdrant docker compose --profile qdrant up --build -d
LLM_PROVIDER=vllm docker compose --profile vllm up --build -dUse Docker for Postgres, then run the API from the host:
docker compose up -d postgres
uv sync --extra dev --extra embeddings --frozen
uv run alembic upgrade head
uv run uvicorn apps.api.main:app --host 0.0.0.0 --port 8000 --reloadRun a one-shot worker from the host:
uv run python -m apps.worker.main --onceRun the MCP server over local stdio:
uv run python -m apps.mcp.mainRun the MCP server over Streamable HTTP:
MCP_TRANSPORT=streamable-http MCP_HOST=127.0.0.1 MCP_PORT=8100 \
uv run python -m apps.mcp.mainRun the worker continuously:
uv run python -m apps.worker.mainRepoMedic includes a first-class MCP server for agent clients that need a standard tool interface. It exposes guarded tools for repo config, knowledge, incident intake, job queueing, collector runs, run/PR inspection, and draft PR creation.
RepoMedic can also act as a controlled MCP client during remediation, but only
for predeclared context calls in a repo config. The remediation model does not
choose arbitrary tools. Repo policy names the server, tool, arguments, and
allowlist; runtime settings then enforce server URL/stdio allowlists, timeouts,
call limits, output caps, and redaction. Tool results are added to the prompt as
extra evidence and persisted in each run under evaluation.mcp_tool_use.
Local stdio clients can launch RepoMedic directly:
{
"mcpServers": {
"repomedic": {
"command": "uv",
"args": ["run", "python", "-m", "apps.mcp.main"],
"cwd": "/absolute/path/to/repo-medic",
"env": {
"DATABASE_URL": "postgresql+asyncpg://repomedic:repomedic@localhost:5432/repomedic"
}
}
}
}Claude Code can connect to the HTTP transport after docker compose up -d mcp:
claude mcp add --transport http repomedic http://localhost:8100/mcpCodex or other MCP-aware clients can use the same command/args for stdio or
http://localhost:8100/mcp for Streamable HTTP. The HTTP endpoint has no auth
in this release; bind it to localhost or a trusted network only.
Example repo policy for controlled MCP context collection:
{
"mcp_tool_policy": {
"enabled": true,
"servers": {
"observability": {
"transport": "streamable-http",
"url": "http://localhost:8100/mcp"
}
},
"allowed_tools": ["observability/repomedic_search_knowledge"],
"context_calls": [
{
"name": "related-knowledge",
"server": "observability",
"tool": "repomedic_search_knowledge",
"arguments": {
"repository": "{{repository}}",
"query": "{{raw_error}}",
"limit": 3
}
}
],
"max_calls": 3,
"timeout_seconds": 30,
"max_output_chars": 12000
}
}For Docker-to-Docker calls use http://mcp:8100/mcp in the repo policy and keep
that URL in MCP_CLIENT_ALLOWED_SERVER_URLS.
uv sync --extra dev --frozen
uv run ruff check .
uv run mypy .
uv run pytest
uv run playwright install chromium
uv run pytest -m e2e
uv lock --check
docker compose config
docker compose --profile qdrant config
docker compose --profile vllm configThe default uv run pytest command excludes browser E2E tests. Run the API
against a migrated database, install Chromium once with uv run playwright install chromium, then run uv run pytest -m e2e to exercise dashboard flows in
a real browser. The E2E suite also includes an autonomous smoke harness that
uses test doubles for analysis and PR creation to prove the persisted path from
collector signal to incident, job, run, and draft PR record without calling a
real LLM or GitHub.
.env.example contains the full local configuration template. The table below
summarizes the variables that materially change runtime behavior.
| Variable | Required | Description | Example |
|---|---|---|---|
APP_NAME |
No | FastAPI application name. | RepoMedic |
ENVIRONMENT |
No | Runtime environment label used in health/logging. | local |
LOG_LEVEL |
No | Logging level. | INFO |
API_PREFIX |
No | Prefix for JSON API routes. | /api/v1 |
API_PORT |
No | Host port for the API container. | 8000 |
MCP_TRANSPORT |
No | MCP server transport for host runs. Compose forces HTTP for the mcp service. |
stdio or streamable-http |
MCP_HOST |
No | MCP HTTP bind host. Use localhost unless on a trusted network. | 127.0.0.1 |
MCP_PORT |
No | MCP HTTP port. | 8100 |
MCP_PATH |
No | MCP Streamable HTTP path. | /mcp |
MCP_ALLOW_MUTATIONS |
No | Enables MCP tools that write RepoMedic state. | true |
MCP_ALLOW_DRAFT_PRS |
No | Enables MCP draft PR tool; existing PR safety policy still applies. | true |
MCP_MAX_LIST_LIMIT |
No | Max list size returned by MCP tools. | 100 |
MCP_CLIENT_ENABLED |
No | Enables controlled MCP client context calls during remediation. | false |
MCP_CLIENT_ALLOWED_SERVER_URLS |
No | Comma-separated allowlist for streamable HTTP MCP servers. | http://localhost:8100/mcp |
MCP_CLIENT_ALLOW_STDIO |
No | Allows repo policies to use stdio MCP servers. Keep false unless commands are globally allowlisted. | false |
MCP_CLIENT_ALLOWED_STDIO_COMMANDS |
No | Comma-separated executable allowlist for stdio MCP servers. | empty |
MCP_CLIENT_MAX_CALLS |
No | Global cap for controlled MCP calls per remediation run. | 3 |
MCP_CLIENT_TIMEOUT_SECONDS |
No | Global timeout cap for each controlled MCP tool call. | 30 |
MCP_CLIENT_MAX_OUTPUT_CHARS |
No | Global output cap persisted and sent to the remediation prompt. | 12000 |
DATABASE_URL |
Yes for host runs | Async SQLAlchemy database URL. Compose overrides this inside containers. | postgresql+asyncpg://repomedic:repomedic@localhost:5432/repomedic |
POSTGRES_USER |
No | Local Postgres user. | repomedic |
POSTGRES_PASSWORD |
No | Local Postgres password; change outside local demos. | repomedic |
POSTGRES_DB |
No | Local Postgres database. | repomedic |
POSTGRES_PORT |
No | Host port mapped to Postgres. | 5432 |
LLM_PROVIDER |
Yes for model-backed analysis | Default provider for LLM tasks. | ollama |
OLLAMA_BASE_URL |
If using Ollama | Ollama API URL for host runs. | http://localhost:11434 |
OLLAMA_MODEL |
If using Ollama | Default Ollama model. | deepseek-coder:33b |
VLLM_BASE_URL |
If using vLLM/OpenAI-compatible | OpenAI-compatible base URL. | http://localhost:8001 |
VLLM_API_KEY |
If using vLLM/OpenAI-compatible | API key for the OpenAI-compatible endpoint. | repomedic-local-dev-key |
VLLM_MODEL |
If using vLLM/OpenAI-compatible | Model name sent to the endpoint. | Qwen/Qwen2.5-Coder-7B-Instruct |
ANTHROPIC_API_KEY |
If using Claude API | Anthropic API key for claude_api. |
empty |
CLAUDE_API_BASE_URL |
If using Claude API | Anthropic Messages API base URL. | https://api.anthropic.com |
CLAUDE_API_VERSION |
If using Claude API | Anthropic API version header. | 2023-06-01 |
CLAUDE_API_MODEL |
If using Claude API | Claude model for native API requests. | claude-sonnet-4-6 |
CLAUDE_API_MAX_TOKENS |
If using Claude API | Maximum response tokens. | 4096 |
CODEX_CLI_COMMAND |
If using Codex CLI | Executable used for Codex CLI provider. | codex |
CODEX_CLI_MODEL |
If using Codex CLI | Model string passed to Codex CLI. | gpt-5.4 |
CODEX_CLI_SANDBOX |
If using Codex CLI | Codex CLI sandbox mode. | read-only |
CLAUDE_CLI_COMMAND |
If using Claude Code CLI | Executable used for Claude Code CLI provider. | claude |
CLAUDE_CLI_MODEL |
If using Claude Code CLI | Model string passed to Claude Code CLI. | claude-sonnet-4-6 |
CLAUDE_CLI_TIMEOUT_SECONDS |
If using Claude Code CLI | Timeout for non-interactive Claude CLI JSON runs. | 900 |
CLI_RUNTIME |
No | same_process checks CLI tools in the API/worker runtime. host_worker is for Docker API/dashboard plus host-run worker CLIs. |
same_process |
PROVIDER_PROBE_TIMEOUT_SECONDS |
No | Timeout for dashboard/API provider readiness probes. | 5 |
INCIDENT_ANALYSIS_LLM_PROVIDER |
No | Task-specific provider override. | ollama |
PATCH_GENERATION_LLM_PROVIDER |
No | Task-specific patch provider override. | codex_cli |
PULL_REQUEST_CLIENT |
No | Draft PR backend: gh_cli local default or github_app. |
gh_cli |
GITHUB_TOKEN |
No | Alternative to mounted gh auth when using gh_cli. |
empty |
GITHUB_APP_ID |
If using github_app |
GitHub App ID used to mint installation tokens. | empty |
GITHUB_APP_PRIVATE_KEY |
If using github_app |
Inline PEM private key. Prefer secret injection, never commit it. | empty |
GITHUB_APP_PRIVATE_KEY_PATH |
If using github_app |
Path to the GitHub App PEM private key. | empty |
GITHUB_APP_INSTALLATION_ID |
No | Optional installation ID override; otherwise RepoMedic looks it up per repo. | empty |
GITHUB_APP_API_BASE_URL |
No | GitHub REST API base URL. | https://api.github.com |
GITHUB_APP_API_VERSION |
No | GitHub REST API version header. | 2022-11-28 |
GITHUB_APP_REQUEST_TIMEOUT_SECONDS |
No | GitHub App API request timeout. | 30 |
COLLECTOR_WEBHOOK_SECRET |
For webhooks | HMAC secret for OpenSearch/GitHub webhook verification. | change-me |
COLLECTOR_POLL_INTERVAL_SECONDS |
No | Poll interval for repomedic-collector. |
60 |
OPENSEARCH_BASE_URL |
If using OpenSearch collector | Default OpenSearch-compatible URL. | https://opensearch.example.com |
OPENSEARCH_INDEX |
If using OpenSearch collector | Default log index pattern. | logs-* |
OPENSEARCH_USERNAME |
No | Basic auth username. | empty |
OPENSEARCH_PASSWORD |
No | Basic auth password. | empty |
OPENSEARCH_API_KEY |
No | API key auth value. | empty |
JAEGER_BASE_URL |
If using Jaeger collector | Jaeger query API URL. | http://localhost:16686 |
RETRIEVAL_BACKEND |
No | Knowledge retrieval backend. | pgvector or qdrant |
KNOWLEDGE_INDEXER |
No | Document indexing strategy. | direct or llamaindex |
QDRANT_URL |
If using Qdrant | Qdrant base URL. | http://localhost:6333 |
QDRANT_COLLECTION |
If using Qdrant | Qdrant collection name. | repomedic_knowledge |
EMBEDDING_MODEL |
If using local embeddings | sentence-transformers model name. | sentence-transformers/all-MiniLM-L6-v2 |
EMBEDDING_DIMENSIONS |
If using local embeddings | Expected embedding vector size. | 384 |
PATCH_GATE_MIN_RETRIEVAL_SCORE |
No | Minimum average retrieval score for patch readiness. | 0.25 |
PATCH_GATE_MAX_RISK_SCORE |
No | Maximum risk score for patch readiness. | 0.2 |
PATCH_GENERATION_MAX_FILES |
No | Max local files included in patch-generation context. | 2 |
PATCH_GENERATION_MAX_FILE_CHARS |
No | Max characters per file context. | 6000 |
WORKSPACE_ROOT |
No | Isolated patch workspace root. | .repomedic-workspaces |
REPOMEDIC_HOST_REPOS_ROOT |
Docker | Host folder mounted into containers at /host-repos. |
/Users/me/code |
HOST_REPOS_ROOT |
No | Runtime path for mounted host repositories. | /host-repos |
REPO_PATH_MAPPINGS |
No | Comma-separated host_path=runtime_path mappings for stored repo paths. |
/Users/me/code=/host-repos |
VERIFICATION_MAX_COMMANDS |
No | Maximum repo-configured verification commands per run. | 10 |
VERIFICATION_MAX_COMMAND_LENGTH |
No | Maximum length of each verification command string. | 500 |
VERIFICATION_MAX_OUTPUT_CHARS |
No | Max stdout or stderr characters persisted per command after redaction. | 12000 |
VERIFICATION_ALLOWED_ENV_VARS |
No | Comma-separated environment allowlist passed to verification commands. | PATH,HOME,... |
VERIFICATION_SECRET_ENV_NAME_PATTERNS |
No | Env-name patterns whose values are redacted from command output. | TOKEN,SECRET,... |
VERIFICATION_BLOCKED_EXECUTABLES |
No | Direct executables blocked in repo verification commands. | bash,sh,curl,... |
VERIFICATION_REQUIRE_WORKSPACE_CWD |
No | Require verification cwd to be inside WORKSPACE_ROOT. |
true |
DRAFT_PR_ALLOWED_REPOSITORIES |
For draft PRs | Comma-separated owner/name allowlist. Blank disables PR creation. | owner/safe-test-repo |
DRAFT_PR_ALLOWED_BASE_BRANCH_PATTERNS |
For draft PRs | Allowed base branch patterns. | repomedic-safe/* |
DRAFT_PR_SAFE_BASE_BRANCH_PREFIX |
No | Safe base branch prefix. | repomedic-safe/ |
DRAFT_PR_SAFE_HEAD_BRANCH_PREFIX |
No | Safe head branch prefix. | repomedic/ |
Do not commit real secrets in .env.
curl -X POST http://localhost:8000/api/v1/knowledge/ingest \
-H 'content-type: application/json' \
-d '{
"repository": "acme/example-service",
"source_type": "runbook",
"source_ref": "runbooks/payment-webhook.md",
"title": "Payment webhook runbook",
"content": "Missing payment metadata should return a 4xx response, not a 500.",
"metadata": {"owner": "payments"}
}'curl -X POST http://localhost:8000/api/v1/knowledge/search \
-H 'content-type: application/json' \
-d '{
"repository": "acme/example-service",
"query": "webhook metadata missing causes 500",
"top_k": 5
}'curl -X POST http://localhost:8000/api/v1/incidents/analyze \
-H 'content-type: application/json' \
-d @examples/incident-analysis-request.jsonThis returns retrieval matches, structured remediation output, guardrail
decisions, verification status, evaluation scores, and PR-ready text. With
apply_patch=false, the result is suggestion-only.
curl -X POST http://localhost:8000/api/v1/repos \
-H 'content-type: application/json' \
-d '{
"repository": "acme/example-service",
"service_name": "payment-api",
"default_branch": "main",
"allowed_paths": ["src/payment", "tests/payment"],
"blocked_paths": [".github/workflows", "infra", "secrets"],
"build_commands": [],
"test_commands": ["pytest tests/payment"],
"lint_commands": ["ruff check src tests"],
"local_repo_path": "/host-repos/example-service",
"apply_patch_default": true,
"auto_queue_analysis_default": true,
"auto_create_draft_pr_default": false,
"mcp_tool_policy": {
"enabled": false,
"servers": {},
"allowed_tools": [],
"context_calls": []
}
}'Then create an incident:
curl -X POST http://localhost:8000/api/v1/incidents \
-H 'content-type: application/json' \
-d @examples/incident.jsonQueue analysis for that incident from the dashboard or through:
curl -X POST http://localhost:8000/api/v1/incidents/<incident-id>/analyze \
-H 'content-type: application/json' \
-d '{"apply_patch": true, "top_k": 6}'Inspect jobs and runs:
curl http://localhost:8000/api/v1/jobs
curl http://localhost:8000/api/v1/runsCheck autonomous readiness before enabling patch or PR automation:
curl "http://localhost:8000/api/v1/repos/acme/example-service/preflight?mode=draft_pr"The response includes status, capabilities, structured checks,
blockers, and warnings. Missing local checkout, allowed paths, verification
commands, LLM credentials/tooling, draft PR allowlists, collector source config,
and repo/collector auto-mode mismatches are surfaced before a signal is allowed
to drive a patch or draft PR.
Create OpenSearch and Jaeger collectors from the dashboard, or use the API:
curl -X POST http://localhost:8000/api/v1/collectors \
-H 'content-type: application/json' \
-d '{
"name": "payment-jaeger-errors",
"repository": "acme/example-service",
"collector_type": "jaeger",
"enabled": true,
"query": {
"base_url": "http://localhost:16686",
"service": "payment-api",
"tags": {"error": "true"}
},
"auto_queue_analysis": true,
"auto_apply_patch": true,
"auto_create_draft_pr": false,
"min_severity": "medium"
}'Run enabled collectors once:
curl -X POST http://localhost:8000/api/v1/collectors/run \
-H 'content-type: application/json' \
-d '{"limit": 50}'Inspect collector readiness and run history:
curl "http://localhost:8000/api/v1/collectors/<collector-id>/preflight?mode=draft_pr"
curl http://localhost:8000/api/v1/collectors/runs
curl http://localhost:8000/api/v1/collectors/runs/<run-id>Collector run and webhook responses include auto_queue_skipped,
auto_queue_skip_reasons, and auto_queue_warnings. Incident detail events also
record auto_queue_decision or auto_queue_skipped, so you can see whether an
observability signal queued remediation, skipped because repo/collector policy
was off, or queued with setup warnings such as missing verification commands.
Collector poll history is also persisted in collector_run_records, so the
dashboard and API keep the last poll status even after the immediate response is
gone.
Draft PR creation is disabled until DRAFT_PR_ALLOWED_REPOSITORIES and safe base
branch patterns allow the target. The local default backend is gh_cli, using
mounted GitHub CLI auth or GITHUB_TOKEN. For server-style operation, set
PULL_REQUEST_CLIENT=github_app plus GITHUB_APP_ID and either
GITHUB_APP_PRIVATE_KEY or GITHUB_APP_PRIVATE_KEY_PATH. The App needs
repository Contents write permission to push RepoMedic branches and Pull
requests write permission to open draft PRs. This is GitHub App installation
authentication, not user login or RepoMedic dashboard authentication.
curl -X POST http://localhost:8000/api/v1/runs/<run-id>/draft-pr \
-H 'content-type: application/json' \
-d '{
"repository": "owner/safe-test-repo",
"base_branch": "repomedic-safe/demo-base",
"head_branch": "repomedic/demo-head",
"title": "Draft: RepoMedic remediation",
"body": "Draft PR opened by RepoMedic after verification.",
"commit_message": "Apply RepoMedic remediation",
"create_base_branch": true,
"draft": true
}'- Use
uv run ruff check .before committing. - Use
uv run mypy .for type checks. - Use
uv run pytestfor the test suite. - Use
uv run pytest -m e2efor browser dashboard checks against a running local server. - Use
docker compose configafter editing Compose files. - Put domain rules in
domain/; keep framework and external-service code ininfrastructure/. - Add API schemas in
schemas/and route handlers inapps/api/routes/. - Add migrations under
migrations/versions/for database changes. - Keep verification commands in repo config; never accept shell commands from model output.
- Prefer deterministic guardrails over prompt-only safety rules.
Useful docs:
No issue, milestone, TODO, or roadmap file is present in this repository. The README therefore does not claim planned features as committed work.
Operational publication checks are documented in docs/release-checklist.md.
-
Create a branch.
-
Keep changes scoped and covered by tests.
-
Run:
uv run ruff check . uv run mypy . uv run pytest
-
Open a PR with a short summary, test results, and any operational notes.
Security-sensitive changes should also be checked against docs/security-safety.md.
Apache-2.0. See LICENSE.

