Note: 100% of the code in this project was generated using artificial intelligence (Anthropic's Claude Code).
Two AI agents that integrate natively with Linear using the Linear Agents platform:
- Enrique — Enriches tasks with technical analysis
- Devora — Implements changes and creates Pull Requests
When assigned to a task, Enrique:
- Downloads and processes attached media (images, videos with transcription)
- Analyzes the relevant codebases using Claude Code
- Updates the task description with:
- Technical Analysis — Implementation approach with specific file references
- Complexity Estimate — Low / Medium / High with justification
- Acceptance Criteria — Functionality, UX, and Technical requirements
When assigned to a task, Devora:
- Creates isolated git worktrees for affected repositories
- Implements changes using Claude Code based on the technical analysis
- Commits, pushes, and creates Pull Requests on GitHub
- Links PRs directly in the Linear activity panel
- Cleans up worktrees when PRs are merged or closed
┌─────────────────────────────────────────────────────────────────────────────┐
│ LINEAR AGENT FLOW │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Linear (assign agent) │
│ │ │
│ ▼ │
│ AgentSessionEvent webhook │
│ │ │
│ ▼ │
│ Express server (OAuth authenticated) │
│ │ │
│ ├──► Enrique: Claude Code analysis → Update description │
│ │ │
│ └──► Devora: Git worktree → Claude Code → GitHub PR │
│ │
│ Activity updates streamed to Linear via Agent Activities API │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ GITHUB CLEANUP │
├─────────────────────────────────────────────────────────────────────────────┤
│ GitHub (PR closed) → Webhook → Remove worktree │
└─────────────────────────────────────────────────────────────────────────────┘
Key components:
- Express receives webhooks from Linear and GitHub
- OAuth tokens authenticate API calls (auto-refresh supported)
- Agent Activities provide real-time progress in Linear's native UI
- Claude Code (
claude -p) analyzes and implements in non-interactive mode - Git worktrees provide isolated environments for each implementation
- GitHub CLI (
gh) creates Pull Requests automatically - Cloudflare Tunnel exposes the local server with a fixed URL
- Node.js 20+
- Claude Code CLI
- cloudflared
- ffmpeg (for video audio extraction)
- GitHub CLI (
gh) authenticated
git clone https://github.com/Avilocap/linear-agents.git
cd linear-agents
npm install
cp .env.example .envYou need two OAuth Apps in Linear (one per agent identity):
-
Go to Linear Settings → API → OAuth Applications → New Application
-
Create Enrique app:
- Name:
Enrique - Redirect URI:
https://your-domain.com/oauth/callback - Webhook URL:
https://your-domain.com/webhook/agent/enrique - Webhook events: Enable Agent session events
- Capabilities: Enable Assignable and Mentionable
- Name:
-
Create Devora app:
- Name:
Devora - Redirect URI:
https://your-domain.com/oauth/callback - Webhook URL:
https://your-domain.com/webhook/agent/devora - Webhook events: Enable Agent session events
- Capabilities: Enable Assignable and Mentionable
- Name:
-
Copy credentials to
.env:
ENRIQUE_CLIENT_ID=...
ENRIQUE_CLIENT_SECRET=...
ENRIQUE_WEBHOOK_SECRET=...
DEVORA_CLIENT_ID=...
DEVORA_CLIENT_SECRET=...
DEVORA_WEBHOOK_SECRET=...
OAUTH_REDIRECT_URI=https://your-domain.com/oauth/callbackFor each repository that Devora will work with:
- Go to Repository Settings → Webhooks → Add webhook
- URL:
https://your-domain.com/webhook/github - Content type:
application/json - Secret: Save to
GITHUB_WEBHOOK_SECRET - Events: Select Pull requests only
PORT=3000
# Linear OAuth Apps
ENRIQUE_CLIENT_ID=
ENRIQUE_CLIENT_SECRET=
ENRIQUE_WEBHOOK_SECRET=
DEVORA_CLIENT_ID=
DEVORA_CLIENT_SECRET=
DEVORA_WEBHOOK_SECRET=
OAUTH_REDIRECT_URI=https://your-domain.com/oauth/callback
# OpenAI (for video transcription)
OPENAI_API_KEY=
# GitHub
GITHUB_TOKEN=
GITHUB_WEBHOOK_SECRET=
# Optional
PROJECT_ROOT=/path/to/your/projects
LINEAR_TEAM_KEY=YOUR_TEAMcloudflared login
cloudflared tunnel create linear-agents
cloudflared tunnel route dns linear-agents your-subdomain.yourdomain.com./start.shThen install each agent by visiting:
https://your-domain.com/oauth/install/enriquehttps://your-domain.com/oauth/install/devora
Approve as admin in Linear. Tokens are stored in .tokens.json.
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/oauth/install/:agent |
— | Start OAuth install flow |
GET |
/oauth/callback |
— | OAuth callback |
POST |
/webhook/agent/enrique |
Linear signature | Enrique session events |
POST |
/webhook/agent/devora |
Linear signature | Devora session events |
POST |
/webhook/github |
GitHub signature | PR cleanup events |
GET |
/health |
— | Health check |
- Open a Linear task
- Click Delegate to agent (or use the
akeyboard shortcut) - Select Enrique or Devora
The agent will show real-time progress in Linear's native activity panel.
You can also trigger agents by mentioning them in comments:
@Enrique analiza esta tarea@Devora implementa esto
Create plist files in ~/Library/LaunchAgents/:
com.zinkee.linear-agents.plist— Node servercom.zinkee.linear-agents-tunnel.plist— Cloudflare tunnel
Both with RunAtLoad and KeepAlive enabled.
# Start
launchctl load ~/Library/LaunchAgents/com.zinkee.linear-agents.plist
launchctl load ~/Library/LaunchAgents/com.zinkee.linear-agents-tunnel.plist
# Restart
./restart.sh
# Logs
tail -f logs/server.loglinear-agents/
├── src/
│ ├── server.js # Express server with OAuth + webhooks
│ ├── enricher.js # Enrique agent logic
│ ├── implementer.js # Devora agent logic
│ ├── activity-emitter.js # Linear Agent Activities client
│ ├── linear-client.js # Authenticated GraphQL client
│ ├── token-store.js # OAuth token persistence
│ └── worktree-manager.js # Git worktree management
├── .env.example
├── .tokens.json # OAuth tokens (gitignored)
├── package.json
├── start.sh
└── restart.sh
MIT