* chore: ignore local secret file
* feat(cli): replace self-update with package-manager-owned runtime resolution
The CLI no longer downloads runtime bundles from GitHub on first run. Instead:
- A new resolveRuntime() in apps/cli/src/runtime.ts resolves the bundle in
three steps: KANDEV_BUNDLE_DIR env var (Homebrew wrapper, tests) → installed
@kdlbs/runtime-{platform} npm package → cached download (only when
--runtime-version is given explicitly).
- apps/cli/src/run.ts is split: launch logic separated from download logic.
The download path stays for the explicit --runtime-version flag only.
- The --version flag now prints CLI semver (was: runtime tag selector). The
old behavior moves to --runtime-version, documented as advanced/debug.
- The npm self-update prompt (apps/cli/src/update.ts) is removed entirely.
- apps/cli/package.json declares optionalDependencies for five
@kdlbs/runtime-{platform} packages and engines.npm: ">=7" (required for
optional-dep resolution during npx).
- Adds esbuild + a "bundle" script that produces dist/cli.bundle.js — a
single-file CJS bundle with all Node deps inlined. The Homebrew formula
uses this; the npm package keeps the unbundled dist/cli.js.
Tests: 130/130 passing. Bundle smoke-tested in a directory with no
node_modules to confirm tree-kill is correctly inlined.
* feat(release): unified vX.Y.Z release flow with brew + npm sibling channels
GitHub release artifacts become the canonical build output. npm and Homebrew
are independent sibling channels — both consume the same GitHub release
tarballs; neither depends on the other.
Workflow changes (.github/workflows/release.yml):
- Trigger is now workflow_dispatch only (maintainer-only, gated by repo write
access). Inputs: bump dropdown (patch/minor/major) + dry_run checkbox.
- Single job graph orchestrates everything in one run:
prepare (bump, PR, merge, tag) → build-web/build-cli → build-bundles (5
platforms) → docker → publish-release → publish-npm + update-homebrew-tap.
- The prepare job inlines version bump, optionalDependencies sync, CHANGELOG
generation, PR create + squash-merge, and tag push. Replaces what
release-pr.sh used to do locally.
- Tag-push trigger removed; everything runs from the dispatch flow.
New scripts (called by the workflow):
- package-cli.sh: builds + esbuild-bundles the CLI for inclusion in release
bundles (cli/bin/cli.js + cli/dist/cli.bundle.js + package.json).
- package-npm-runtime.sh: generates per-platform @kdlbs/runtime-* npm
packages from release bundles. Sets npm os/cpu fields so npm 7+ skips
non-matching platforms during npx kandev install.
- publish-npm.sh: verifies GitHub assets exist, downloads them, repackages,
publishes all 5 @kdlbs/runtime-* packages + main kandev@X.Y.Z.
- update-homebrew-tap.sh: clones kdlbs/homebrew-kandev via SSH using the
HOMEBREW_TAP_DEPLOY_KEY repo secret, generates Formula/kandev.rb pointing
at the GitHub release assets, pushes directly to main.
Removed scripts:
- release.sh and release-pr.sh — both are redundant with the new workflow.
Required CI secrets:
- NPM_TOKEN: granular access token with publish access to kandev + @kdlbs/*
- HOMEBREW_TAP_DEPLOY_KEY: SSH private key for kdlbs/homebrew-kandev
* docs: brew install, runtime resolution, and GHA-driven release flow
- README.md: add Homebrew quick start (brew install kdlbs/kandev/kandev),
update NPX docs to require npm 7+, document the three update paths.
- docs/cli.md: rewrite architecture diagram to show three-step runtime
resolution. Replace --version <tag> docs with --version (CLI semver) +
--runtime-version <tag> (advanced/debug). Remove KANDEV_NO_UPDATE_PROMPT.
- apps/cli/README.md: add Homebrew install path; document
package-manager-owned updates.
- apps/cli/README_internal.md: rewrite to describe the npm package vs
GitHub bundle artifact-shape distinction and the three-step resolver.
Document the GHA-driven release UI (Run workflow + bump dropdown).
- AGENTS.md: add Release & Versioning Convention section describing the
unified single-SemVer flow, the sibling channel model, and the GHA flow.
* fix(release): release-bundle bin/cli.js must require the esbuild bundle
The previous package-cli.sh copied apps/cli/bin/cli.js verbatim into the
release bundle. That file requires `../dist/cli.js` (unbundled), which
only works when node_modules is present alongside it.
In the GitHub release bundle (used by Homebrew and manual installs),
there is no node_modules — `require('tree-kill')` and `require('tar')`
inside dist/cli.js would crash at startup.
Now package-cli.sh writes a release-specific bin/cli.js that requires
`../dist/cli.bundle.js` instead. The bundled file has all Node deps
inlined via esbuild, so it runs standalone in the Cellar.
The npm package keeps its own bin/cli.js (in apps/cli/bin/) requiring
the unbundled dist/cli.js, since npm installs tree-kill etc. normally.
Caught while smoke-testing the release bundle locally with
KANDEV_BUNDLE_DIR — backend + web boot succeeded after this fix.
* feat(release): switch npm publishing to Trusted Publishers (OIDC)
The previous flow required an NPM_TOKEN secret. Local testing with that
token failed with EOTP because the granular access token still required a
2FA OTP on publish despite the account-level setting change. npm now
recommends Trusted Publishers (OIDC) over long-lived tokens.
Workflow change (release.yml):
- publish-npm job declares `permissions: id-token: write` so GitHub Actions
can mint OIDC tokens.
- Removes NODE_AUTH_TOKEN env var. The npm CLI auto-detects the OIDC
environment and exchanges the GitHub OIDC token for a short-lived
npmjs.com publish credential.
- Comment block updated to reflect the new auth model. NPM_TOKEN is no
longer listed in required secrets (already deleted from repo secrets).
Script change (publish-npm.sh):
- Updates `npm publish` calls to include `--provenance` so each published
package ships with a signed attestation linking it back to this commit
and workflow run.
- Header comment explains the OIDC auth model.
Setup required on npmjs.com (per package, before first OIDC publish):
For each of the 6 packages — kandev plus @kdlbs/runtime-{linux-x64,
linux-arm64,darwin-x64,darwin-arm64,win32-x64} — go to the package's
"Settings → Publishing access" and add a Trusted Publisher pointing at
this repo (kdlbs/kandev), workflow filename release.yml, and (optionally)
an environment.
* fix(release): pin optionalDependencies to bootstrap version in committed source
CI was failing because apps/cli/package.json declared optionalDependencies
at 0.16.0 but only 0.0.0-bootstrap exists on npm for those packages. The
lockfile couldn't resolve, and `pnpm install --frozen-lockfile` rejected
the working tree.
Pin optionalDependencies to 0.0.0-bootstrap in the committed source so the
lockfile resolves cleanly. The release workflow now bumps them to the real
version inside publish-npm.sh, just before publishing main kandev — at
which point the matching @kdlbs/runtime-*@VERSION tarballs have already
been published earlier in the same step. This avoids the chicken-and-egg
where the prepare job tried to bump optional deps to a version that didn't
yet exist on npm.
Workflow changes:
- prepare job: only bumps the main package version, not optional deps.
- publish-npm.sh: rewrites optionalDependencies to $VERSION right before
the main `npm publish`, after the 5 runtime packages have been published.
The published kandev@X.Y.Z still has its optionalDependencies pinned to
matching @kdlbs/runtime-*@X.Y.Z. Only the local source uses the bootstrap
pin for development convenience.
* fix: address PR review comments on release flow + runtime resolution
PR reviewers (Greptile, Claude, CodeRabbit) flagged six concrete issues.
Each is addressed below.
Critical:
- publish-npm.sh: previously exited 0 even when runtime packages failed to
publish, which would leave kandev@VERSION on the registry pointing at
@kdlbs/runtime-*@VERSION that never got published. Now: capture full npm
output on failure, distinguish "already published" (idempotent skip)
from real failures, abort before publishing main kandev if any runtime
fails.
- release.yml: build-bundles referenced needs.prepare.outputs.tag without
declaring prepare in its needs array. Static analysis flagged this.
Added prepare to the needs list.
Major:
- update-homebrew-tap.sh: the formula's write_env_script only injected
KANDEV_BUNDLE_DIR. run.ts:174 reads KANDEV_VERSION to display the
running version in startup logs; without it Homebrew users would see
"release: (env)" instead of "release: 0.17.0". Pass KANDEV_VERSION:
version.to_s through the wrapper.
- runtime.ts: the catch {} block silently swallowed validateBundle errors,
hiding "package installed but corrupt" cases behind the generic
"no runtime found" message. Split the lookup so MODULE_NOT_FOUND falls
through, but validation errors propagate.
- run.ts: the --runtime-version code path skipped validateBundle, missing
the file-existence checks that the npm/env paths get. Added it.
Minor:
- release.yml: workflow-level permissions defaulted to write for everyone.
Tightened to read-only at the workflow level; jobs that need writes
(prepare, docker, publish-release) declare them explicitly.
- args.test.ts: added missing tests for --runtime-version with no value
and --runtime-version followed by another flag, parallel to the
existing --port tests.
Tests: 132 passing (was 130; +2 new).
* fix: address second-round PR review (cleanup traps, host-key pinning, supply chain)
Latest review (Claude + Greptile) flagged three security/cleanup items
on top of the previous fix commit. All three addressed below.
publish-npm.sh:
- Add `trap 'rm -rf "$WORK_DIR"' EXIT` immediately after `mktemp -d` so
the tmpdir is cleaned up even when `pnpm build` or `npm publish` fails
partway through (set -e would otherwise abort before the explicit
rm at the end).
- Remove redundant `pnpm build` before `npm publish` — the `prepublishOnly`
script in package.json already runs the build.
update-homebrew-tap.sh:
- Combine `cleanup_ssh` + WORK_DIR cleanup into one EXIT trap so `git clone`
/ `git push` failures don't leak the tmpdir.
- Pin GitHub's published SSH host keys (ed25519, ECDSA, RSA) into a temp
`known_hosts` file instead of using `accept-new` + `/dev/null`. This
closes the "trust any host key on first connect" gap. The pinned keys
come from https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints.
release.yml:
- Replace the curl|tar git-cliff install with `orhun/git-cliff-action@v4`
(already used in publish-release). The action pins to a digest, so we
no longer need to verify a tarball checksum manually. Removes a
supply-chain attack surface where a tampered git-cliff binary could run
during `prepare` (which has contents:write + pull-requests:write).
* revert: keep curl install for git-cliff, add sha512 verification instead
The previous commit (18b2a5c) replaced our `curl | tar` install with
orhun/git-cliff-action@v4 under the banner "supply chain". On reflection
that swap doesn't actually improve anything:
- @v4 is a moving tag, not a digest pin — same trust as a tagged curl URL.
- Both depend on trusting the same maintainer (orhun).
- The action adds a third-party step we don't audit.
The legitimate concern from the review was "no integrity verification on
the downloaded tarball." Address that directly: pin the asset version,
embed its published sha512, and abort if the download doesn't match.
The hash for v2.6.1's x86_64-linux-gnu tarball came from
https://github.com/orhun/git-cliff/releases/download/v2.6.1/<asset>.sha512.
This restores the original setup with a real integrity check and one
fewer external dependency.
* fix: address remaining PR nits (env restore, sha256 download dir)
runtime.test.ts: drop the redundant `delete process.env.KANDEV_BUNDLE_DIR`
in afterEach — `process.env = { ...origEnv }` already restores the
original environment. The redundant delete would silently un-set the var
if a developer had it in their shell, leaking test side effects across
suites.
update-homebrew-tap.sh: fetch_sha256 now downloads into $WORK_DIR instead
of /tmp/. The EXIT trap covers WORK_DIR, so the .sha256 files are cleaned
up automatically. Avoids leaking 5 tmpfiles per release run on long-lived
runners.
* fix: address third-round PR comments
- update-homebrew-tap.sh: Homebrew formula was calling
`bin.write_env_script` on the bin directory with target `cli/bin/cli.js`,
which would create the wrapper at `$HOMEBREW_PREFIX/bin/cli.js` (named
after the target's basename) instead of `$HOMEBREW_PREFIX/bin/kandev`.
Result: `brew install kandev` would have produced `command not found`.
Use `(bin/"kandev").write_env_script(...)` to name the wrapper
explicitly. Caught by Claude as a P0 blocker.
- publish-npm.sh: main `kandev` publish lacked the EPUBLISHCONFLICT
idempotency handling that the runtime-package loop has. If publish-npm
was re-run after a partial failure (e.g. the runtime packages succeeded
but the main package failed and was then manually published), the
re-run would fail on the main package even though the version was
already on the registry. Now: capture output, treat
"already published" as success, fail loudly with full output on real
errors. Caught by Greptile as P1.
* refactor(release): direct push to main instead of PR-and-merge dance
The prepare job was opening a release branch, creating a PR, and
immediately squash-merging it via gh CLI. That pattern was carried over
from the old release-pr.sh, but in this workflow it earns nothing:
- main has no branch protection, so direct push is allowed.
- The PR was force-merged in the same step (no `--auto`, no waiting for
required checks), so it provided no pre-merge validation.
- Discoverability is fine without a PR — git tag, GitHub release, workflow
run, and main commit are all visible.
The PR-and-merge sequence had ~5 GitHub API roundtrips, each a potential
failure point, plus added 30+ lines of YAML and required pull-requests:
write on the job. Replaced with a straight-line commit + tag + push:
git fetch origin main && git checkout main && git reset --hard origin/main
... bump pkg.json, regen CHANGELOG, npm install ...
git add ... && git commit && git tag -a && git push origin main "$TAG"
Job permissions tightened to contents: write only.
Race condition note: if main advances between fetch and push, the push
fails non-fast-forward — same outcome as the old PR pattern, where the
auto-merge would have failed. For workflow_dispatch releases with the
maintainer actively driving, the race is essentially never going to
happen, and the recovery (re-run the workflow) is the same.
The dry-run path still bumps + regenerates CHANGELOG inside the runner
so the maintainer can verify the computed values look right, just
without committing or pushing anything.
* chore(release): drop verbose comment about direct-push rationale
* docs: drop 'no first-run download' note from user-facing docs
The phrasing only makes sense to readers who knew the previous model
required a first-run download. New users have no baseline to compare
against, so it adds noise. Removed from docs/cli.md and apps/cli/README.md
(which renders on npmjs.com). Kept in apps/cli/README_internal.md as a
design note for contributors.
* Revert "chore: ignore local secret file"
The /secret entry was added defensively after the bootstrap test, but it
clutters .gitignore with a project-specific path that nobody else needs.
Drop it; secrets stay out of the repo by other means (don't commit them).
* fix: address third-pass review (stale workflow comments + missing test)
release.yml:
- The header comment block and dry_run input description still referenced
the PR-and-merge step that was removed in 53c2e45. Updated both to
describe the direct-commit flow.
runtime.test.ts:
- The runtime resolver's npm-package branch (step 2 — the primary path
after npx kandev@latest or npm install -g) had no positive coverage. In
the test env, require.resolve for @kdlbs/runtime-* throws
MODULE_NOT_FOUND, so the existing tests only exercised step 1 (env var)
and step 3 (cache via --runtime-version), plus the no-runtime-found
fallthrough.
Added two tests using vi.spyOn on Module._resolveFilename to point at a
fake bundle inside tmpDir:
- happy path: installed npm package resolves to source=npm with the
right bundleDir
- corrupt-bundle path: validateBundle errors propagate (rather than
being swallowed and falling through to "no runtime found")
These cover the real-world scenarios users will hit on either install
channel.
Tests: 132 → 134.
* fix(release): push commit + tag atomically
Without --atomic, git push can succeed for the tag ref and fail for the
main ref on a non-fast-forward, leaving an orphaned tag at the pre-bump
commit. The orphan then trips the 'Tag already exists on origin' guard
on the next re-run, requiring manual tag deletion to unblock.
--atomic makes the multi-ref push succeed-or-fail as a unit.
Caught by Greptile as P1.
* refactor(cli): drop runtime.ts step 3 — cache fallback was unreachable
resolveRuntime's runtimeVersion parameter and cache-fallback step were
dead code from production's perspective. The --runtime-version path is
handled entirely in run.ts (findCachedRelease + downloadRuntimeVersion +
findBundleRoot + validateBundle), and run.ts only ever called
resolveRuntime() with no argument. The parameter and step 3 only existed
because tests exercised them.
Two parallel "compute cache dir" implementations (runtime.ts:65 and
run.ts:157) were a drift hazard if the cache layout ever changes.
Changes:
- Drop the runtimeVersion parameter from resolveRuntime.
- Drop the cache step from runtime.ts entirely; remove the unused
CACHE_DIR + findBundleRoot imports.
- Narrow RuntimeSource from "env" | "npm" | "cache" to "env" | "npm",
and drop the now-unused tag field from ResolvedRuntime.
- Remove the three "cache fallback" tests from runtime.test.ts. The
--runtime-version cache lookup is still covered by run.test.ts via
findCachedRelease tests.
Tests: 134 → 131 (three deleted tests are obsolete, the production
behavior they were verifying is now covered by run.test.ts).
* chore(test): drop dead mock setup left over from runtime.ts step 3 removal
After feb7c5a removed the cache fallback from runtime.ts, the test file
had two dangling artifacts:
- The vi.mock("./constants", ...) block + the mockCacheDir holder + the
mockCacheDir.value = tmpDir assignment in beforeEach. runtime.ts no
longer imports anything from ./constants, so the mock was a no-op
that would mislead readers tracing why constants are mocked here.
- The PLATFORM = "macos-arm64" constant was unused — platform
determinism is already enforced by the vi.mock("./platform", ...)
block one section above.
Caught by Claude and the github-code-quality bot.
11 KiB
Kandev
Manage and run tasks in parallel. Orchestrate agents. Review changes. Ship value.
Workflows | Roadmap | Contributing | Architecture | Discord
What
Organize work across kanban and pipeline views with opinionated workflows and execute multiple tasks in parallel. Assign agents from any provider, and review their output in an integrated workspace - file editor, file tree, terminal, browser preview, and git changes in one place. Terminal agent TUIs are great for running agents, but reviewing and iterating on changes there doesn't scale.
Run it locally or self-host it on your own infrastructure and access it from anywhere via Tailscale or any VPN.
Open source, multi-provider, no telemetry, not tied to any cloud.
Vision
Humans stay in control. Define tasks, build agentic workflows with gates, review every change, decide what ships.
- Review-first - Humans support production systems. We need to understand (yet) and trust the code that gets deployed.
- Your workflow - Every team is different, and not every developer uses AI the same way. Define workflows once, share them across the team, and give everyone a consistent process for working with agents - regardless of experience level.
- Remote agents - Running multiple agents on a large codebase can quickly saturate a local machine. The goal is a single control plane: offload execution to servers, orchestrate from anywhere, including your phone.
Features
- Multi-agent support - Claude Code, Codex, GitHub Copilot, Gemini CLI, Amp, Auggie, OpenCode, Cursor, Qwen, Factory Droid, iFlow, Kilocode, Pi, Kimi, AWS Kiro, Qoder, Trae
- Parallel task execution – start and manage multiple tasks from different sources simultaneously, boosting productivity with AI agents
- Integrated workspace - Built-in terminal, code editor with LSP, git changes panel, embedded vscode and chat in one IDE-like view
- Kanban task management - Drag-and-drop boards, columns, and workflow automation
- Agentic workflows - Multi-step pipelines that mix-and-match agents per step - for example, Claude Code Opus to design a plan, GitHub Copilot Sonnet to implement it, and Codex GPT 5.4 to review the changes. See docs/workflows.md
- Sub-tasks - Agents can spawn sub-tasks that resume from the parent task's session. Useful for splitting a task that has grown too big, or producing several PRs from the same starting point.
- CLI passthrough - Drop into raw agent CLI mode for direct terminal interaction with any supported agent, leverage the full power of their TUIs
- Workspace isolation - Git worktrees prevent concurrent agents from conflicting
- Multi-repository tasks - Span a single task across multiple repositories, with one worktree per repo, per-repo branches, per-repo PRs, and per-repo grouping in the Changes panel and review dialog
- Flexible runtimes - Run agents as local processes, in isolated Docker containers or in remote executors like sprites.dev
- Session management - Resume and review agent conversations
- Stats - Track your productivity with stats on the completed tasks, agent turns, etc
Integrations
Connect Kandev to the tools your team already uses — pull issues into the kanban, link tasks to PRs, and surface review activity inline.
Supported ACP Agents
| Agent | Launch |
|---|---|
| Claude Code | npx -y @agentclientprotocol/claude-agent-acp |
| Codex | npx -y @zed-industries/codex-acp |
| GitHub Copilot | npx -y @github/copilot --acp |
| Gemini CLI | npx -y @google/gemini-cli --acp |
| Amp | npx -y amp-acp |
| Auggie | npx -y @augmentcode/auggie --acp |
| OpenCode | opencode acp |
| Cursor | cursor-agent acp (requires Cursor Pro) |
| Qwen | npx -y @qwen-code/qwen-code --acp |
| Factory Droid | npx -y droid exec --output-format acp |
| iFlow (beta) | npx -y @iflow-ai/iflow-cli --experimental-acp |
| Kilocode | npx -y @kilocode/cli acp |
| Pi | npx -y pi-acp |
| Kimi | kimi acp (install Kimi CLI from Moonshot AI) |
| Kiro | kiro-cli-chat acp (install Kiro CLI from AWS) |
| Qoder | qodercli --acp (install Qoder CLI) |
| Trae | traecli acp serve (install Trae IDE CLI) |
All agents communicate via ACP (Agent Client Protocol). Some agents support ACP natively, while others use ACP adapter packages that bridge their native protocols. CLI Passthrough mode is also available for direct terminal interaction with any agent CLI. If your agent isn't supported yet, open an issue or submit a PR with the integration. See Adding a New Agent CLI for a step-by-step guide.
Bring your own TUI agents
There is support for running any agent as TUI inside a terminal. Just add the cli command in the agent profile settings and the task will start the agent inside a PTY terminal instead of using ACP.
Supported Executors
| Executor | Description |
|---|---|
| Local Process | Runs the agent as a local process on the host machine |
| Docker | Runs the agent in an isolated Docker container |
| Sprites | Runs the agent in a remote cloud environment via sprites.dev |
Each executor uses git worktrees for workspace isolation, preventing concurrent agents from conflicting.
Quick Start
Homebrew (macOS, Linux)
brew install kdlbs/kandev/kandev
kandev
NPX
npx kandev@latest
Requires npm 7+. Installs the CLI plus a platform-matched runtime bundle in one step.
NPM (global)
npm install -g kandev@latest
kandev
Updates
brew upgrade kandevnpx kandev@latest(always uses the latest published version)npm install -g kandev@latest
The worktrees and sqlite db live in ~/.kandev by default. Works on macOS, Linux, and Windows (WSL or native).
From Source
# Clone the repository
git clone git@github.com:kdlbs/kandev.git
cd kandev
# Start in production mode
make start
Prerequisites: Go 1.26+, Node.js 18+, pnpm, Docker (optional - needed for container runtimes)
High level architecture
graph LR
UI[Web UI] --> Backend
Backend["Backend (Orchestrator)"]
Backend --> W1 & W2
subgraph W1[Local Process]
Agent1[Agent CLI] --- WT1[Worktree]
end
subgraph W2[Docker Container]
Agent2[Agent CLI] --- WT2[Worktree]
end
We also want to add support for these remote runtimes:
- Remote SSH - run agents on remote servers over SSH, using docker or local processes with workspace isolation
- K8s operator - run agents in a Kubernetes cluster, with auto-scaling and resource management.
Development
Project Structure
apps/
├── backend/ # Go backend (orchestrator, lifecycle, agentctl, WS gateway)
├── web/ # Next.js frontend (SSR, Zustand, real-time subscriptions)
├── cli/ # CLI tool (npx kandev launcher)
└── packages/ # Shared UI components & types
Prerequisites
- Go 1.21+
- Node.js 18+
- pnpm
- Docker (optional)
Running Dev Servers
# Start everything (backend + frontend with auto ports)
make dev
# Or run separately
make dev-backend # Backend on :38429
make dev-web # Frontend on :37429
Testing & Linting
make test # Run all tests (backend + web)
make lint # Run all linters
make typecheck # TypeScript type checking
make fmt # Format all code
Pre-commit Hooks
# Install pre-commit (https://pre-commit.com/#install)
pipx install pre-commit
# Install git hooks
pre-commit install
Comparison to Other Tools
There are a few similar tools in this space, and new ones appearing everyday. Here's what sets this one apart:
- Server-first architecture - Not a desktop app. Runs as a server you can access from any device, including your phone. Start a task away from your computer and check in on it later.
- Remote runtimes - Run agents on remote servers and Docker hosts, not just your local machine.
- Multi-provider - Use Claude Code, Codex, Copilot, Gemini, Amp, Auggie, OpenCode, Cursor, Qwen, Droid, iFlow, Kilocode, Pi, Kimi, Kiro, Qoder, and Trae side by side. Not locked to one vendor.
- CLI passthrough and chat - Interact with agents through structured chat messages or drop into raw CLI mode for full agent TUI capabilities.
- Open source and self-hostable - No vendor lock-in, no telemetry, runs on your infrastructure.
Contributing
Contributions are welcome! Please read CONTRIBUTING.md before opening a PR.
See the issue tracker for open tasks, or join our Discord to chat with maintainers and other contributors.
Acknowledgments
Built with these excellent open-source projects:
Monaco Editor · Tiptap · xterm.js · dockview · CodeMirror · dnd-kit · Mermaid · Recharts · TanStack Table · Zustand · Shadcn/UI · Radix UI · Tailwind CSS
