gustdeck-cli
v0.1.2
Published
AI coding agent with code, canvas, and cowork modes
Maintainers
Readme
Gust Deck
Gust Deck is a lightweight operator dashboard and Telegram-driven automation service for running coding jobs against GitHub issues. A user can start a job from Telegram or the web dashboard, the worker clones the target repository into a dedicated worktree, runs a coding agent against the issue, pushes a branch, opens a pull request, and streams progress back to both Telegram and the web UI.
What It Does
- Starts issue-driven coding jobs from Telegram with
/run <repo> #<issue> - Starts coding sessions from the web dashboard
- Tracks job state in a local SQLite database
- Queues and processes jobs with BullMQ + Redis
- Streams curated agent activity to a React dashboard over SSE
- Supports follow-up instructions from Telegram replies or the dashboard
- Creates branches, commits, pushes, and pull requests through the GitHub CLI
- Supports Claude and Codex backends behind a shared agent runtime
- Uses passwordless email login for the dashboard via Resend
Architecture
The app runs as a Bun server with two major surfaces:
src/server: Hono API, Telegram webhook handling, auth routes, BullMQ worker, agent runtime, git/GitHub orchestration, and SQLite accesssrc/client: Vite + React dashboard for jobs, job detail streaming, repo settings, session creation, and email login
Core services:
Redis: queue backend and pub/sub for live job streamsSQLite: persistent job, message, repo, and Telegram message-link storage indata/pulse.dbGitHub CLI: repo cloning, issue fetch, auth verification, and PR creationsrc/server/agent: shared runtime layer withAgent,ExecutionContext,GitRuntime, response formatting, and provider backendsClaude Code SDK: Claude-backed autonomous code editing inside per-job git worktreesCodex SDK: Codex-backed autonomous code editing inside per-job git worktreesTelegram Bot API: command intake and job status notificationsResend: magic-link email auth for the dashboard
Requirements
Before running the project, make sure these are available on the machine:
- Bun
- GitHub CLI authenticated with access to the target repos
- Redis
- A Telegram bot token and the allowed chat ID
- A Resend API key for dashboard sign-in emails in production
- Claude Code SDK access/auth on the machine that runs jobs when using
AGENT_PROVIDER=claude - Codex access available on the machine that runs jobs when using
AGENT_PROVIDER=codex
Environment Variables
Create a .env file in the project root.
| Variable | Required | Purpose |
| --- | --- | --- |
| TELEGRAM_TOKEN | Yes | Telegram bot token |
| TELEGRAM_CHAT_ID | Yes | Only this Telegram chat can control the agent |
| TELEGRAM_WEBHOOK_SECRET | Yes | Secret checked on incoming Telegram webhooks |
| REDIS_URL | No | Redis connection string, defaults to redis://127.0.0.1:6379 |
| SESSION_SECRET | Yes | Session secret placeholder for auth-related config |
| DASHBOARD_URL | No | Public dashboard base URL used in login emails and Telegram links; defaults to http://localhost:5173 in local dev |
| RESEND_API_KEY | No | Resend API key for magic-link sign-in; required in production, optional in local dev |
| AUTH_FROM_EMAIL | No | Sender for auth emails, defaults to Gust Deck <[email protected]> |
| PORT | No | Bun server port, defaults to 3000 |
| REPOS_ROOT | No | Directory for persistent clones and worktrees, defaults to <project>/repos |
| AGENT_PROVIDER | No | Coding backend to use, claude by default, or codex |
| CODEX_EXECUTABLE | No | Override the Codex binary path used by the Codex SDK |
Notes:
.env.exampleincludes the main runtime variables, including the agent backend selection.DASHBOARD_URLshould point at the dashboard origin users will actually open.- In local development,
DASHBOARD_URL=http://localhost:5173works with the Vite proxy. - In local development, if
RESEND_API_KEYis not set, the login screen shows a direct magic link instead of sending an email.
Local Development
Install dependencies:
bun installStart Redis:
docker compose up -dbun run dev:serveralso pulls, starts, and waits for the Docker Redis service automatically.Authenticate GitHub CLI:
gh auth loginAdd your
.envfile.Start the app:
bun run dev
This starts:
- API/worker server on
http://localhost:3000 - Vite dashboard on
http://localhost:5173
Vite proxies /api/* requests to the Bun server during development.
Production Run
Build the client bundle:
bun run buildStart the server:
bun run startIn production, the Bun server serves the built SPA from dist/ and exposes the API from the same process.
Telegram Setup
Configure your Telegram bot webhook to point to:
POST /api/telegramThe request must include the same secret token as TELEGRAM_WEBHOOK_SECRET in the x-telegram-bot-api-secret-token header. The bot ignores messages from chats other than TELEGRAM_CHAT_ID.
Supported commands:
/run <repo> #<issue>: queue a job for a configured repo shortcut/status: list active jobs/focus [jobId|#issue]: show or set the active job for free-text follow-ups/cancel <jobId>: mark a job as failed/cancelled/health: check Redis, SQLite, and GitHub CLI availability/help: show command help
Free-text Telegram messages are treated as follow-up instructions when Gust Deck can resolve the active job from:
- a reply to a linked bot message
- the current
/focus - the only running or queued job
Dashboard
The React dashboard provides:
Jobs: list all jobs by status and start a new coding sessionJob detail: live message stream, summary/error panels, PR link, and follow-up formSettings: manage repositories available to Telegram via short namesLogin: email magic-link sign-in
Important API routes:
POST /api/auth/requestGET /api/auth/verifyPOST /api/auth/logoutGET /api/reposPOST /api/reposDELETE /api/repos/:idGET /api/jobsPOST /api/jobsGET /api/jobs/:idGET /api/jobs/:id/streamPOST /api/jobs/:id/replyPOST /api/telegram
Job Lifecycle
When a user starts a job:
- Gust Deck resolves the repository from the configured short name or selected dashboard repo.
- The server fetches the GitHub issue via
gh issue view. - A persistent clone is created if needed under
REPOS_ROOT. - A fresh git worktree is created for the job branch.
- The configured coding backend runs against the issue prompt inside that worktree.
- Agent output is normalized, formatted, and stored in SQLite.
- Curated messages are published to Redis and streamed to the dashboard.
- All changes are committed and pushed with Git.
- A pull request is opened with
gh pr create. - Telegram receives success or failure status plus a dashboard or PR link when a chat is configured.
Data and State
- SQLite database:
data/pulse.db - Redis: queue state and pub/sub streams
- Persistent repo clones:
REPOS_ROOT/<org>/<repo> - Per-job worktrees:
REPOS_ROOT/<org>/<repo>--worktrees/...
Useful Scripts
bun run dev: run API/worker and Vite UI togetherbun run dev:server: run only the Bun server with watch modebun run dev:ui: run only the Vite dashboardbun run build: build the client app todist/bun run start: start the Bun serverbun run typecheck: run TypeScript type checking
Project Structure
src/
client/
components/
pages/
main.tsx
server/
agent/
routes/
services/
config.ts
db.ts
index.ts
data/
pulse.db
docker-compose.ymlCurrent Assumptions and Caveats
- The server process also instantiates the BullMQ worker, so API and worker run together.
- PR creation currently targets the
mainbranch. - GitHub auth is validated via
gh auth statusat startup. - Job execution assumes the machine has the tooling and permissions needed to clone, edit, commit, and push repository changes.
- The Claude backend currently uses the Claude Code SDK, while the Codex backend uses the Codex SDK, which manages Codex execution and streaming internally.
