elek reviews every pull request in your repository. When a PR is opened, updated, reopened, or marked ready, the Action runs one Pi session against the diff. The session uses the model you choose, with your key. elek then posts a summary comment and inline comments on the changed lines.
elek is open source and runs entirely in your own GitHub Actions workflow. There is no hosted service, account, or telemetry.
See it review a real tenant-isolation regression in elek-demo#1.
Safety model
- The model gets Pi's
read,grep,find, andlstools and nothing else: no shell, no file writes, no MCP. A guard blocks paths outside the repository,.git, secret files, and symlink escapes. - The model never receives
GITHUB_TOKEN. elek posts the review itself. - elek has no code path that approves, merges, closes, or pushes. Reviews post
with the
COMMENTevent. - elek redacts token-shaped secrets from the review before it posts.
- When the base branch has a
.elek.yml, elek loads policy from it, so a PR cannot change the rules that review it.
One-minute setup
From your repository root, run:
npx --package github:selimozten/elek elek-init --provider deepseek
This writes .github/workflows/elek.yml and .elek.yml. Add the repository
secret DEEPSEEK_API_KEY, commit both files, and open a PR.
To use another provider, pass --provider and optionally --model:
npx --package github:selimozten/elek elek-init --provider anthropic --model claude-sonnet-4-6
npx --package github:selimozten/elek elek-init --provider openrouter --model moonshotai/kimi-k2.7-code
elek-init --help lists every flag. It refuses to overwrite existing files
unless you pass --force.
Manual workflow
name: elek
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: read
pull-requests: write
issues: write
concurrency:
group: elek-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
review:
# Fork PRs get no secrets and a read-only token, so elek skips them.
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
with:
fetch-depth: 0
- uses: selimozten/elek@v1
with:
deepseek_api_key: ${{ secrets.DEEPSEEK_API_KEY }}
provider: deepseek
model: deepseek-v4-pro
thinking: high
fetch-depth: 0 lets elek build the diff and read the base-branch config from
the checkout.
Inputs
Repository config
.elek.yml keeps review policy next to the code:
severity_threshold: important
knowledge_paths:
- AGENTS.md
- CONTRIBUTING.md
- docs/ARCHITECTURE.md
ignore_paths:
- docs/**
- "*.md"
instructions:
- Treat auth and permission changes as security-sensitive.
- Require tests for parser and config changes.
On a pull request, elek reads .elek.yml and the knowledge files from the base
branch. If elek cannot load .elek.yml from the base branch, for example
because the base branch has none, it uses the checked-out .elek.yml and
knowledge files instead. Commit .elek.yml to your default branch so PRs
cannot change their own review policy. elek
fails the run when the config file has malformed YAML, so a typo cannot drop
your policy without notice. Unknown keys log a warning.
Providers
elek works with any provider Pi supports. Set provider, model, and the
matching key input:
For Amazon Bedrock, set AWS_REGION, AWS_ACCESS_KEY_ID, and
AWS_SECRET_ACCESS_KEY as job-level env. For Vertex, set
GOOGLE_APPLICATION_CREDENTIALS and ANTHROPIC_VERTEX_PROJECT_ID.
Outputs
Permissions
permissions:
contents: read
pull-requests: write
issues: write
contents: read is enough because elek never pushes. pull-requests: write
posts the review and inline comments. issues: write posts the tracking
comment.
FAQ
Does elek review pull requests from forks? No. GitHub gives fork
pull_request runs no repository secrets and a read-only token, so elek has no
model key and cannot post. The workflow above skips forks. Without that guard,
elek exits with a skipped conclusion. Do not switch to pull_request_target
to get secrets: that event runs with your secrets while the PR author controls
the code.
What about draft pull requests? elek skips drafts and reviews the PR when you mark it ready for review.
Which events does elek handle? Only pull_request with the opened,
synchronize, reopened, or ready_for_review action. Other events end with
a warning and a skipped conclusion. elek also skips runs that a bot triggers
or that a user who is not a repository owner, member, or collaborator triggers.
What does a review cost? elek prints the token counts in the review footer
and in the input_tokens and output_tokens outputs. Multiply them by your
provider's prices. When the provider reports no usage, elek estimates the
counts from the prompt and response length and labels the line as estimated.
What does the model check? Every review applies two lenses. The risk lens
looks for bugs, security holes, breaking behavior, and side effects. The design
lens looks for structural regressions and needless complexity. The model then
drops findings it cannot verify against the changed code. prompt changes the
request but not these rules.
Why are comments from github-actions[bot]? The default GITHUB_TOKEN
posts as that account. If you pass a GitHub App or bot token as github_token,
set the job-level env ELEK_TRACKING_COMMENT_AUTHORS to that login so elek
reuses its own tracking comment on later pushes.
Documentation
docs/setup.mdexplains setup in more detail and covers troubleshooting.docs/examples.mdhas workflow recipes.docs/ARCHITECTURE.mddescribes how a review run works.CONTRIBUTING.mdandAGENTS.mdare for people and agents working on elek.
License
MIT. Built on Pi.