docs: separate user and contributor documentation paths (#1729)

* docs: expand public user and contributor guides

* docs: address public guide review feedback

* docs: align web e2e coverage guidance

* test: cover collapsed docs references

* fix: validate shortcut docs references

* fix: parse balanced docs links

* fix: handle indented docs code blocks
This commit is contained in:
José Almeida
2026-07-16 15:13:21 +01:00
committed by GitHub
parent 2acc29dce1
commit 2549704bc1
26 changed files with 2262 additions and 89 deletions
-1
View File
@@ -10,7 +10,6 @@ apps/
├── web/ # Vite/React SPA frontend (Go boot payload + WS + Zustand)
├── desktop/ # Tauri desktop shell around the native runtime
├── cli/ # CLI tool (TypeScript)
├── landing/ # Landing page
└── packages/ # Shared packages/types
```
+4 -4
View File
@@ -151,7 +151,7 @@ cd kandev
make start
```
**Prerequisites:** Go 1.26+, Node.js 18+, pnpm, Docker (optional - needed for container runtimes)
**Prerequisites:** Go 1.26.0, Node.js 24, and pnpm 9.15.9 (pinned in `mise.toml`). Docker is optional and needed only for container runtimes.
## High level architecture
@@ -193,16 +193,16 @@ We also want to add support for this remote runtime:
```
apps/
├── backend/ # Go backend (orchestrator, lifecycle, agentctl, WS gateway)
├── web/ # Next.js frontend (SSR, Zustand, real-time subscriptions)
├── web/ # Vite/React frontend (SPA, Zustand, real-time subscriptions)
├── cli/ # CLI tool (npx kandev launcher)
├── landing/ # Landing page
├── desktop/ # Tauri desktop shell
└── packages/ # Shared UI components & types
```
### Prerequisites
- [mise](https://mise.jdx.dev/) for the pinned toolchain in `mise.toml` (`make bootstrap` installs it when missing)
- Go 1.26, Node.js 24, pnpm 9.15.9 (installed by `make bootstrap`)
- Go 1.26.0, Node.js 24, pnpm 9.15.9 (installed by `make bootstrap`)
- Docker (optional)
### Environment Setup
+47 -8
View File
@@ -2,16 +2,33 @@
Files in this directory are the source for [kandev.ai/docs](https://kandev.ai/docs). A merged change under `docs/public/**` triggers a Cloudflare Pages rebuild automatically.
The docs have two audiences:
- **Use Kandev** explains product tasks, configuration, security implications, limitations, and operations.
- **Contribute to Kandev** explains repository structure, code boundaries, testing, extension points, releases, and docs maintenance.
Keep a page focused on one audience. Link across the boundary when a user-facing explanation needs contributor detail, but do not mix internal implementation notes into a task guide.
## Update an Existing Page
Edit the relevant Markdown file directly. Keep commands, configuration keys, API names, and screenshots aligned with the implementation in the same pull request.
Edit the relevant Markdown file directly. Verify commands, configuration keys, default values, API names, labels, and screenshots against the implementation in the same pull request.
Use relative links between published pages, for example `[CLI](cli.md)`. The website build rewrites those links to `/docs/...` routes. Links to repository files outside `docs/public` are rewritten to their GitHub source URLs.
When behavior is conditional, say whether it is:
- supported by default;
- optional and dependent on an executor, integration, platform, or credential;
- experimental or feature-flagged;
- in progress or internal.
Do not describe an ADR, spec, plan, hidden route, or feature flag as generally available without confirming its runtime and UI path.
## Add a Page
1. Create a lowercase, kebab-case Markdown file in this directory, such as `custom-executors.md`. Its filename becomes its route: `custom-executors.md` is published at `/docs/custom-executors`.
2. Start the file with `title` and `description` frontmatter, followed by one level-one heading:
1. Decide whether the page belongs under **Use Kandev** or **Contribute to Kandev**. Search existing pages first; prefer extending one task guide over creating overlapping reference pages.
2. Create a lowercase, kebab-case Markdown file in this directory, such as `custom-executors.md`. Its filename becomes its stable route: `/docs/custom-executors`.
3. Start the file with non-empty `title` and `description` frontmatter, followed by one level-one heading:
```markdown
---
@@ -24,24 +41,46 @@ Use relative links between published pages, for example `[CLI](cli.md)`. The web
Page content starts here.
```
3. Add the filename without its extension to `meta.json` exactly once. Its position controls sidebar order. Entries such as `---Execution---` create section labels.
4. Link the new page from related documentation where useful.
4. Add the filename without `.md` to `meta.json` exactly once, below the correct audience heading. Its position controls sidebar order. Keep routes flat unless a concrete publication constraint requires a directory.
5. Link the new page from `index.md` and from closely related guides. Use relative Markdown links and repository-owned assets.
6. Include prerequisites, a concrete workflow, exact configuration, limitations or failure modes, and related pages where those sections apply.
Pages omitted from `meta.json`, duplicate entries, unknown entries, and missing frontmatter fail validation.
Pages omitted from `meta.json`, duplicate entries, unknown entries, broken local Markdown links, and missing frontmatter fail validation.
## Assets and Diagrams
- Keep user-facing screenshots under `docs/screenshots/` and reference them relatively.
- Do not link temporary capture output, local paths, or third-party hotlinked images.
- Mermaid code fences render on the website. Keep diagrams readable at docs-column width, use stable node labels, and provide surrounding prose that carries the same essential meaning.
- Prefer commands and text examples over screenshots when the UI changes frequently.
## Validate
Run the dependency-free checks from the Kandev repository root:
Run the focused dependency-free docs checks from the Kandev repository root:
```bash
node --test scripts/validate-public-docs.test.mjs
node scripts/validate-public-docs.mjs
```
To build the complete docs site, clone `kdlbs/landing` beside this repository and run:
The broader repository script suite requires the pinned repository toolchain and installed dependencies:
```bash
make test-scripts
```
To build the complete docs site, clone `kdlbs/landing` beside this repository and run with the toolchain expected by Landing:
```bash
cd ../landing
pnpm install --frozen-lockfile
KANDEV_DOCS_SOURCE_PATH=../kandev/docs pnpm --filter @kandev/docs build
```
Before opening a pull request, also check:
- every new or renamed page appears once in `meta.json`;
- links resolve from the source file, not from the repository root;
- user claims are supported by current code or tests;
- feature status and platform limitations are explicit;
- generated files under the Landing docs app were not committed.
+78
View File
@@ -0,0 +1,78 @@
---
title: "Agents and Profiles"
description: "Configure agent CLIs, models, modes, flags, environment variables, passthrough, MCP, and permission behavior."
---
# Agents and Profiles
An **agent** identifies a CLI integration. An **agent profile** is the reusable launch policy for that integration. Profiles let one installed agent serve different repositories or trust levels without repeatedly entering models, flags, and environment configuration.
## Built-in and custom agents
Kandev discovers supported ACP-native CLIs and adapter commands, including Claude Code, Codex, GitHub Copilot, Gemini CLI, Amp, Auggie, OpenCode, Cursor, Devin, Qwen, Factory Droid, iFlow, Kilocode, Pi, Kimi, Kiro, Qoder, Trae, Oh My Pi, and Grok.
Availability depends on the current platform, executable/install command, and the agent's own authentication. The list in **Settings > Agents** is authoritative for the running Kandev version.
Custom TUI agents can run an arbitrary CLI command in a PTY even when they do not speak ACP. Configure the executable, arguments, display name, optional model/description, and whether Kandev waits for the terminal. TUI mode does not manufacture ACP capabilities that the CLI lacks.
## Profile fields
Agent profiles can configure:
| Field | Effect |
|---|---|
| Name | Human-readable profile selection label. |
| Model | ACP model identifier applied at session start when the agent advertises model selection. |
| Mode | Optional ACP session mode applied with `session/set_mode`. |
| Config options | Dynamic ACP session options applied with `session/set_config_option`. |
| CLI flags | Tokenized command arguments; only enabled entries reach the subprocess. |
| Environment variables | Plain values or references to named Kandev secrets injected into the agent process. |
| CLI passthrough | Opens the native TUI execution style instead of relying only on structured ACP chat. |
| Auto approve | Lets Kandev agentctl approve ACP permission requests automatically. |
| MCP policy | Controls which Kandev/external MCP servers are made available in the session. |
Some fields appear only when the agent advertises the related capability. A profile copied from another machine can reference a model or mode that the locally installed agent does not provide; inspect discovery/status before using it.
## CLI flags
Each flag entry stores a raw string, description, and enabled state. At launch, Kandev shell-tokenizes the raw string, so one entry such as `--add-dir /shared` becomes two arguments.
- Use separate profiles for materially different permission or workspace flags.
- Do not paste shell pipelines into a flag field; it is an argument list, not a shell startup script.
- Agent updates can add, rename, or remove flags. Recheck user-modified profiles after upgrading a CLI.
- `allow_indexing` remains a compatibility field for older Auggie profiles; current launch behavior is represented by CLI flags.
## Environment and secrets
Environment variables are visible to the agent subprocess and anything it launches. Prefer a named secret reference for tokens. Secret values are still available at runtime to that process; the reference avoids duplicating plaintext in profile configuration, not exposure to the selected agent.
Use the narrowest credential that completes the job. Separate read-only review profiles from write-capable implementation/release profiles where practical.
## Permission requests and auto approval
ACP agents can ask the client to approve tool use. With **Auto approve** disabled, Kandev displays permission requests in the session so a user can choose an offered response. With it enabled, agentctl automatically selects an allowed response.
Auto approval is high impact. It can permit shell commands, file changes, network calls, or other tools exposed by the agent. Combine it only with an executor, credentials, and repository scope that are safe for unattended work.
Agent-specific flags that bypass permissions can be broader than ACP auto approval and may prevent Kandev from showing a request at all. Treat both as explicit security policy.
## ACP versus passthrough
Structured ACP sessions provide capabilities such as model/mode selection, typed messages, permission requests, tool updates, todos, usage, and resume metadata when the agent supports them.
Passthrough preserves the agent's terminal UX. It is useful for CLIs whose native interface has features not exposed through ACP. Kandev can inject task MCP configuration for supported passthrough integrations, but the agent controls how it loads and uses that configuration.
## Usage and billing hints
Kandev can show subscription utilization for supported CLIs when local credential files expose that data. Profiles using API keys are represented separately. This is operational visibility, not a universal billing ledger; provider reports, reset windows, and availability vary.
## Troubleshooting
- **Agent unavailable:** verify the command under the same user and PATH as Kandev, then refresh discovery.
- **Login required:** use the profile's login/terminal flow or authenticate the CLI outside Kandev under the service user.
- **Model rejected:** choose an advertised model and verify the provider account has access.
- **Flag fails at startup:** run the resolved command manually and remove stale/custom arguments.
- **Environment missing remotely:** configure the agent variable on the agent profile and executor prerequisites on the executor profile; local shell exports do not automatically cross SSH/container boundaries.
- **MCP tool absent:** inspect agent MCP support, profile MCP policy, executor policy, and task mode.
Contributor guide: [Adding a new agent CLI](add-agent-cli.md).
+90
View File
@@ -0,0 +1,90 @@
---
title: "Architecture"
description: "Understand Kandev's unified backend, web client, task runtime, persistence, event, and deployment boundaries."
---
# Architecture
Kandev is a server-first development workbench. A unified Go binary owns orchestration and persistent state, serves the Vite-built React application, and manages local or remote task environments through agentctl.
```mermaid
flowchart LR
Browser["React web client"] -->|HTTP and WebSocket| Backend["Unified Go backend"]
Desktop["Tauri desktop shell"] --> Backend
Backend --> DB[("SQLite or PostgreSQL")]
Backend --> Providers["Git and provider integrations"]
Backend --> Local["Local or worktree runtime"]
Backend --> Container["Docker runtime"]
Backend --> Remote["SSH, remote Docker, or Sprites"]
Local --> Agentctl1["agentctl"]
Container --> Agentctl2["agentctl"]
Remote --> Agentctl3["agentctl"]
Agentctl1 --> Agent1["Agent CLI"]
Agentctl2 --> Agent2["Agent CLI"]
Agentctl3 --> Agent3["Agent CLI"]
```
## Process entry points
`apps/backend/cmd/kandev/main.go` dispatches between the public launcher and the hidden `__backend` mode. `apps/backend/internal/launcher/` starts the installed runtime and browser. `apps/backend/internal/backendapp/` wires the production server.
At startup the backend loads configuration, creates logging and the event bus, opens persistence, constructs domain services, registers HTTP/WebSocket/MCP routes, starts schedulers and watchers, and flips readiness only after the listener and routes are ready.
The release binary embeds the built web assets. Development runs Vite separately and the backend proxies web traffic while retaining API and WebSocket ownership.
## Backend domains
Backend code is organized by domain under `apps/backend/internal/`:
- `task/`, `workflow/`, `orchestrator/`, and `runs/` own work state and dispatch;
- `agent/` and `agentctl/` own agent discovery, profiles, protocol adapters, process control, terminals, Git, and runtime communication;
- `worktree/`, `ssh/`, `sprites/`, and `agent/docker/` materialize executor environments;
- `github/`, `gitlab/`, `jira/`, `linear/`, `sentry/`, and `slack/` own provider adapters;
- `mcp/` exposes task/config coordination tools;
- `system/` owns status, database, backups, logs, disk, updates, and build information;
- `gateway/websocket/` broadcasts state changes to connected clients;
- `db/` and domain repositories provide SQLite/PostgreSQL persistence.
Handlers translate HTTP or WebSocket messages. Services enforce domain behavior. Repositories own persistence. Keep provider SDK shapes and transport DTOs out of the core model where an existing adapter boundary exists.
## Web client
`apps/web/` is a React 19 application built with Vite. The backend serves its production output as a single-page application. Client routing, initial bootstrap data, HTTP domain clients, a WebSocket connection, and Zustand state keep the UI synchronized with backend state.
Page-level code lives under `apps/web/app/`; reusable UI and feature components live under `apps/web/components/`; API, routing, state, and shared utilities live under `apps/web/lib/`. Tests are colocated or under `apps/web/e2e/` depending on scope.
The web application should display backend truth rather than reimplement workflow or lifecycle rules in components.
## Task execution
A task selects one or more repositories, an agent profile, and an executor profile. The executor materializes a task environment. The backend launches or reaches agentctl in that environment; agentctl then runs the agent CLI and exposes process, shell, Git, file, terminal, ACP, and task-MCP capabilities through its control channel.
The task environment can outlive one agent turn and can be shared by several sessions. A worktree separates Git files/branches, while a container or remote host establishes a stronger runtime boundary. None of them automatically narrow the credentials explicitly provided to the agent.
## Events and real-time state
The backend event bus decouples state changes from WebSocket broadcasts, workflow reactions, integration watches, and schedulers. Unified mode uses an in-memory bus; deployments can configure NATS where supported.
Persist the durable transition before publishing an event. Consumers must tolerate retries, reconnects, and stale clients. The UI refetches authoritative state when an incremental event is insufficient.
## Persistence
SQLite is the default. PostgreSQL support is selected through configuration. Domain repositories own schema and queries; dialect helpers isolate SQL differences.
Do not put long-running network or agent work inside database transactions. Use explicit statuses and durable IDs so startup recovery, watchers, and queued work can reconcile partial execution.
## Trust boundaries
Important boundaries are:
- browser/desktop client to backend;
- backend to provider APIs and Git remotes;
- backend to agentctl task environments;
- agentctl to the selected agent process and MCP servers;
- host to Docker/SSH/Sprites infrastructure.
Worktrees are concurrency isolation, not OS security. External MCP currently has no Kandev user-auth boundary. Remote deployments must use network access controls and scoped credentials. See [Automation and MCP](automation-and-mcp.md) and [Operations](operations.md).
## Office source tree
`apps/backend/internal/office/` contains feature-flagged, in-progress autonomy work. Its source packages are not a supported extension API for the regular task product. Keep public behavior and status explicit when touching it.
+106
View File
@@ -0,0 +1,106 @@
---
title: "Automation and MCP"
description: "Automate task creation and let agents coordinate Kandev through task-scoped and external MCP endpoints."
---
# Automation and MCP
Kandev has two automation layers and two MCP contexts. Keep their scopes distinct:
- workflow events act on a task already moving through a workflow;
- workspace automations create work from schedules, provider events, or webhooks;
- task MCP lets an active coding agent coordinate its task and related work;
- external MCP lets a separate client control Kandev through the backend.
## Workflow events
Workflow-step events can react when a task enters a step, a user sends a message, or an agent turn completes. Depending on the workflow, actions can start an agent, send a configured prompt, stop work, or move the task.
Use them for predictable task-local transitions such as Plan to human approval to Implement to Review. Inspect all events on both source and destination steps before enabling auto-start behavior so a move does not create an accidental loop.
## Workspace automations
**Settings > Automations** and the workspace automation editor define rules that create task-backed or run-only executions. An automation selects a workspace, workflow and step, repository, agent profile, executor profile, prompt, title template, concurrency limit, and one or more triggers.
Current trigger types are:
| Trigger | Filters or configuration |
|---|---|
| Schedule | Cron expression and optional timezone. |
| GitHub pull request | Events, repositories, base branches, authors, labels, and draft exclusion. |
| GitHub push | Repositories and branch globs. |
| GitHub CI | Repositories, conclusions, and optional check names. |
| Webhook | Signed endpoint with an optional filter expression. |
Execution mode **Task** creates visible kanban work. **Run** uses the same session pipeline for a lighter, hidden execution whose result appears in automation run history. Concurrency and deduplication reduce duplicate work, but they do not make external actions idempotent by themselves.
Start with a narrow repository and read-only prompt. Inspect run history and generated tasks before enabling write credentials or widening filters.
## Task MCP
Kandev injects a task-aware MCP server into compatible ACP and passthrough sessions. It gives the agent structured coordination tools instead of requiring it to infer board state from prose.
Depending on the current task and policy, tools cover:
- listing workspaces, workflows, steps, profiles, executors, and related tasks;
- creating and updating tasks or subtasks;
- moving, archiving, or deleting tasks;
- attaching sibling repositories or additional branches;
- adding dependencies and selecting a diff base;
- sending cross-task messages and reading conversations;
- creating and updating task plans/documents;
- asking the user a structured clarification question;
- creating a code walkthrough;
- inspecting associated pull requests and signalling step completion.
The server injects calling-task identity for operations that require it. Tools still enforce task relationships, workspace rules, executor constraints, and normal provider permissions. An MCP call does not bypass GitHub branch protection or human approval.
## Profile and executor MCP policy
An agent profile can add external MCP servers. An executor profile can restrict allowed transports and destinations. Supported transport forms include stdio, SSE, HTTP, and streamable HTTP where the selected agent supports them.
Passthrough agents load MCP differently. Kandev may pass command-line configuration or merge a project-local MCP file for the specific CLI. Inspect the profile UI before assuming that an arbitrary TUI receives task tools.
## External MCP
For a local backend bound to loopback, use:
```text
http://127.0.0.1:<backend-port>/mcp
```
For a remote deployment, terminate TLS and authentication at a secure reverse proxy and use:
```text
https://<kandev-host>/mcp
```
SSE compatibility endpoints are available at `/mcp/sse` and `/mcp/message`. **Settings > External MCP** provides client-specific configuration snippets.
External MCP is useful when an agent outside a Kandev task needs to inspect configuration or create and coordinate Kandev work. It runs against the backend's own reachability and credentials, not a task worktree.
## Security boundary
The external MCP endpoint currently has no Kandev user-authentication boundary. Anything that can reach the backend endpoint can attempt to use its exposed tools.
- Bind Kandev to loopback for a single-user local install.
- For remote access, place it behind a VPN, firewall, or authenticated reverse proxy that also supports long-lived streaming requests.
- Do not publish `/mcp`, `/mcp/sse`, or the backend port directly to the public internet.
- Use a separate network segment and scoped provider credentials for unattended automation.
- Review reverse-proxy logs and automation run history for unexpected clients or task creation.
The agentctl-local MCP server used inside a task is a different endpoint and is protected by the task runtime's control channel. Do not expose agentctl ports either.
## Operating checklist
Before enabling unattended automation:
1. Limit trigger repositories, branches, authors, labels, or issue query.
2. Use a dedicated agent and executor profile with minimal credentials.
3. Set a conservative concurrency limit.
4. Keep a human gate before merge, release, or production actions.
5. Test duplicate events and failed retries.
6. Confirm logs and run history contain enough context to audit an execution.
7. Verify the external MCP endpoint is unreachable outside the intended network.
Related: [Tasks and workflows](tasks-and-workflows.md), [Coordination](coordination.md), [Agents and profiles](agents-and-profiles.md), and [Integrations](integrations.md).
+96
View File
@@ -0,0 +1,96 @@
---
title: "Backend Development"
description: "Work in Kandev's Go backend using its handler, service, repository, event, and runtime patterns."
---
# Backend Development
The backend is a Go module rooted at `apps/backend`. It builds the unified `kandev` binary and the `agentctl` helper used inside local, container, and remote task environments.
## Run and test the backend
From the repository root:
```bash
make dev-backend
make test-backend
make lint-backend
```
For a package-sized loop:
```bash
cd apps/backend
go test -tags fts5 ./internal/task/...
go test -tags fts5 ./internal/mcp/server -run TestName
```
The `fts5` build tag and CGO settings used by the Makefile matter for SQLite search behavior. Reproduce CI through the root targets before concluding that a direct `go test` result is sufficient.
## Follow domain boundaries
A normal backend feature flows through:
1. domain model or request DTO;
2. repository interface and implementation when persistence changes;
3. service method that enforces behavior;
4. HTTP or WebSocket handler;
5. event publication and gateway notification when clients need real-time state;
6. startup wiring in `internal/backendapp/`;
7. unit/integration tests at each changed boundary.
Use the nearest domain's naming and error conventions. Avoid reaching directly into another domain's SQLite repository when a service or interface exists.
## HTTP and WebSocket APIs
HTTP routes generally live with a domain's handlers/controllers under `/api/v1`. Real-time task and agent behavior also uses typed actions from `apps/backend/pkg/websocket` and gateway broadcasters under `internal/gateway/websocket`.
When adding or changing a wire field:
- update the Go DTO and web TypeScript type/client together;
- preserve JSON compatibility unless the change is intentionally breaking;
- test malformed input and authorization/workspace scope;
- publish an event only after persistence succeeds;
- consider a reconnecting client that missed the event.
The public WebSocket protocol reference is generated from maintained behavior in [WebSocket API](websocket-api.md).
## Persistence and migrations
Domain repositories under `internal/*/repository` and `internal/db` own storage. SQLite is the primary local path; PostgreSQL compatibility uses dialect helpers and CI coverage.
- Make migrations forward-safe and deterministic.
- Add repository tests for both new writes and old-row reads.
- Keep transaction scope small.
- Never log secret values.
- Consider startup recovery for statuses that represent in-flight work.
## Agent runtime boundary
The backend does not run every agent command directly. `internal/agent/runtime/lifecycle` coordinates execution, while agentctl owns the process in the task environment. Control DTOs and streams cross that boundary.
Changes to agent launch, MCP injection, terminals, Git operations, or remote behavior often require tests on both sides. Check local, worktree, Docker, and at least one remote-shaped path rather than assuming local process behavior generalizes.
## Events and background work
Schedulers, integration watches, automations, workflow reactions, and run queues can execute after the initiating request returns. Make handlers return durable IDs/status, use cancellation-aware contexts, and define deduplication or idempotency where external events can repeat.
Background failures must be observable in persisted status or logs. A goroutine that only logs an error is usually insufficient for user-facing work.
## Configuration and secrets
`internal/common/config` loads server configuration. User-managed credentials go through the secrets domain or provider-specific secret adapter rather than plaintext config rows or logs.
Validate URLs, filesystem paths, shell input, and provider payloads at the boundary. Pay particular attention to prepare scripts, Git refs, archive extraction, MCP destinations, and remote command construction.
## Review checklist
- Domain rule lives in a service, not only a handler.
- Repository behavior and migration are tested.
- Events follow durable writes.
- Cancellation, timeout, retry, and duplicate-event behavior are explicit.
- No secrets or agent content leak into logs unexpectedly.
- Web types and public docs match the API.
- Relevant focused tests plus `make test-backend` and `make lint-backend` pass.
Related: [Architecture](architecture.md), [Testing](testing.md), and [Extending Kandev](extending-kandev.md).
+103
View File
@@ -0,0 +1,103 @@
---
title: "Contributing to Kandev"
description: "Set up the repository, choose the right change boundary, run checks, update public docs, and prepare a reviewable pull request."
---
# Contributing to Kandev
Kandev is a Go backend, Vite/React web application, Node launcher, Tauri desktop shell, and a collection of runtime helpers. Start by understanding the user-visible behavior and the ownership boundary of the subsystem you intend to change.
## Set up the repository
The pinned toolchain is defined in `mise.toml`: Node 24, pnpm 9.15.9, Go 1.26.0, and supporting tools.
```bash
git clone https://github.com/kdlbs/kandev.git
cd kandev
make bootstrap
```
For browser end-to-end work, also run:
```bash
make bootstrap-e2e
```
`make bootstrap` installs the pinned tools when needed, installs workspace dependencies, and configures repository hooks. Run `make doctor` when local and CI behavior disagree.
## Start the development application
```bash
make dev
```
This starts the Go backend and Vite web development server with automatic port selection. The terminal output shows the actual URLs. Use `make dev-backend` or `make dev-web` when isolating one side.
The production-shaped local path is:
```bash
make build
make start
```
## Find the right layer
| Change | Start in |
|---|---|
| Task, workflow, repository, integration, persistence, or API behavior | `apps/backend/internal/<domain>/` |
| Agent process, ACP, MCP, terminal, Git, or remote runtime behavior | `apps/backend/internal/agent/`, `agentctl/`, or the executor package |
| User interface, state, routing, or browser API calls | `apps/web/` |
| CLI launch/install behavior | `apps/cli/` and `apps/backend/internal/launcher/` |
| Desktop shell behavior | `apps/desktop/` |
| Public user documentation | `docs/public/` |
| CI/release behavior | `.github/workflows/` and `scripts/` |
Read the nearest tests and existing domain types before adding a new abstraction. Prefer an established handler/service/repository or API/state/component path over a parallel framework.
## Develop with focused checks
During iteration, run the narrowest relevant command. Before opening a PR, run:
```bash
make fmt
make typecheck
make test
make lint
```
Any change under `apps/web/` must add or update Playwright coverage in `apps/web/e2e/` and run `make test-e2e`. See [Testing](testing.md) for targeted commands and fixture rules.
## Update public behavior and docs together
If a change affects commands, configuration, settings, workflows, executors, integrations, APIs, screenshots, status language, or user-facing terminology, update `docs/public/**` in the same PR.
When adding a page:
1. create a flat, stable Markdown slug in `docs/public/`;
2. add title and description frontmatter;
3. add the slug once to `docs/public/meta.json`;
4. link it from the relevant overview and related pages;
5. run `node scripts/validate-public-docs.mjs`.
The full publication contract is in the [docs contribution guide](README.md).
## Prepare the pull request
- Keep one logical change per PR.
- Explain user impact and the technical boundary.
- List exact automated and manual verification.
- Include screenshots or a short recording for UI behavior.
- Call out migrations, new credentials, security changes, or compatibility risks.
- Do not mix generated artifacts, local databases, recordings, or unrelated formatting into the diff.
- Understand and be able to explain any agent-generated code you submit.
The root `CONTRIBUTING.md` contains the community and licensing policy. By contributing, you agree to the repository's AGPL-3.0 license.
## Next guides
- [Architecture](architecture.md)
- [Backend development](backend-development.md)
- [Web development](web-development.md)
- [Testing](testing.md)
- [Extending Kandev](extending-kandev.md)
- [Release process](release-process.md)
+94
View File
@@ -0,0 +1,94 @@
---
title: "Coordinate Work"
description: "Split work across subtasks, dependencies, repositories, branches, plans, messages, and pull requests."
---
# Coordinate Work
Kandev supports both human-guided workflows and coordinator-led agent patterns. Both use the same task model: explicit repository scope, workflow state, profiles, dependencies, messages, and review surfaces.
## Subtasks
A child task is appropriate when a parent goal contains work that should have its own conversation, status, branch, or pull request.
By default, a subtask inherits the parent task's:
- workspace and workflow;
- agent and executor profiles;
- repository attachments and base branches;
- materialized task workspace when `workspace_mode` is `inherit_parent`.
Use inherited workspace mode when the child is a focused phase or collaborator that must see the same uncommitted files. Concurrent writers can conflict because they are editing the same worktrees.
Use a new materialized workspace when the child needs independent branches and filesystem state. A coordinator can also target a sibling repository explicitly so a frontend or infrastructure subtask stays under one parent while working in another repo.
## Dependencies
Blocker relationships express order independently of the board column. Use them when a task cannot produce a valid result until another task finishes. Related-task views and task MCP expose parent, child, sibling, blocker, and blocked-by context.
A dependency is coordination metadata, not a merge queue. The receiving task still needs to fetch, rebase, cherry-pick, or otherwise consume the prerequisite code according to the repository workflow.
## Multiple repositories and branches
One task can attach several repositories. Kandev materializes one workspace per attachment and groups files, diffs, review, and pull requests by repository.
One task can also attach another branch from the same repository. Use that when the task intentionally produces separate PRs or needs to compare/work across branch lines. Each attachment records its own base branch; changing a diff base changes review context and ahead/behind calculations, not the actual commits.
Before an agent works across attachments, state:
- which repository owns each deliverable;
- whether worktrees are shared or isolated;
- the expected base and PR target for every branch;
- the order in which dependent PRs should merge;
- which tests must run in each repository.
## Shared plans and handoffs
Task plans are versioned documents that humans and agents can edit. A coordinator can create or update the parent plan, then give each child a scoped description and file-ownership boundary.
Handoffs can move a task to another workflow step with a prompt for the next agent. Keep the handoff factual: completed work, current branch/commit, tests run, known failures, required inputs, and files that must not be overwritten.
Do not rely on conversation summaries as the only durable state. Put decisions in the plan or repository and make commits before switching isolated branches.
## Cross-task messages and conversations
Task MCP can send a message to another task's primary session and read task conversations with pagination and message-type filters. A running task queues the message for a subsequent turn; an idle task can receive it immediately.
Use messages for bounded requests or status, not as an implicit shared-memory bus. Include the task/repository/branch identifiers and the expected response. Avoid sending secrets or large source dumps through cross-task messages.
## Coordinator-led pattern
A typical coordinator flow is:
1. Inspect workspace, workflow, repositories, available profiles, and related tasks.
2. Record a plan with clear deliverables and ownership.
3. Create child tasks with the correct repository and workspace mode.
4. Add dependencies where order matters.
5. Monitor conversations and associated PR state.
6. Ask blocked children for concrete status or provide missing context.
7. Integrate and verify each branch in dependency order.
8. Signal workflow completion with a summary, handoff, and blockers.
The coordinator has only the tools and permissions exposed to its selected profile and Kandev task MCP. It does not bypass branch protection, GitHub approval, executor credentials, or human workflow gates.
## Human-guided pattern
The same primitives support a more controlled process:
- a human creates and scopes each task;
- Plan or Review steps pause for explicit approval;
- agents can propose subtasks but a human reviews their scope and profile;
- protected credentials stay outside broad agent profiles;
- a human decides what merges and what ships.
Choose the level of autonomy per workflow and repository risk. The task model does not force one operating style.
## Limits and safety
- Shared workspaces do not prevent file conflicts between agents.
- Separate worktrees do not isolate host credentials or processes unless the executor does.
- Cross-repository work still needs compatible credentials for every remote.
- Associated PR data depends on configured GitHub/GitLab access and branch association.
- Office mode is a separate feature-flagged autonomy workspace; do not assume its persistent teams, budgets, or routines are part of regular task MCP coordination.
Related: [Automation and MCP](automation-and-mcp.md), [Tasks and workflows](tasks-and-workflows.md), and [Sessions and review](sessions-and-review.md).
+95
View File
@@ -0,0 +1,95 @@
---
title: "Developer Tools"
description: "Use quick chat, utility agents, voice input, editors, terminals, prompts, notifications, and personal settings."
---
# Developer Tools
Kandev combines task coordination with the developer surfaces needed to inspect and finish work. Most tools operate in the current task environment, while quick chat and utility agents handle shorter work that does not need a full workflow.
## Quick chat
Quick chat opens a focused agent conversation without first creating a kanban task. Use it for short questions, repository orientation, command help, or other disposable interactions.
Use a normal task when the work needs durable workflow state, a dedicated branch or worktree, structured documents, review gates, dependencies, or a pull request. Quick chat is not a substitute for that delivery record.
## Utility agents
**Settings > Utility Agents** configures small agent-backed jobs used by Kandev itself. Built-in uses include generating or refining:
- task prompts;
- branch names;
- commit messages;
- pull-request descriptions;
- session summaries.
Each utility can select an agent/profile and prompt template. These jobs can send repository or task context to the configured model provider, so choose credentials and profiles with the same care as a normal session. Keep the fallback behavior usable when a utility agent or provider is unavailable.
## Prompts
**Settings > Prompts** manages reusable prompt templates. Workflows, utility agents, and task actions can reference them so a team can standardize planning, implementation, review, and handoff instructions.
Prompts are process policy, not enforcement. Pair them with workflow gates, scoped executor permissions, tests, and branch protection when those controls matter.
## Voice mode
**Settings > Voice Mode** configures dictation in the chat composer. Available engines depend on browser and deployment support:
- browser Web Speech;
- local in-browser Whisper Web;
- server-side Whisper transcription.
Settings include language, click-to-toggle or hold-to-talk activation, and optional auto-send. Server-side transcription requires its configured provider credential and sends audio outside the browser. Review the privacy and retention policy of the selected engine before using customer or proprietary content.
## Files, editor, and language servers
The task workbench can browse and edit files, search the workspace, preview images, and show diagnostics or language features when a matching language server is installed. **Settings > General > Editors** controls editor integrations and discovery.
The file tree reflects the selected task repository or attachment. In a multi-repository task, check the repository label before editing or reviewing. Agent changes can arrive while a file is open, so refresh the diff before commenting on line numbers.
## Terminal and shell
The integrated terminal runs in the task environment. For local/worktree executors that is the host; for Docker, SSH, or Sprites it is the selected runtime through agentctl.
**Settings > General > Terminal** controls shell behavior. A command that works in your login shell may fail under a service account, container, or remote environment because PATH, credentials, working directory, or startup files differ.
## Changes, review, and walkthroughs
The Changes panel groups repository state, staged/unstaged files, commits, branches, and pull requests. Review comments can be attached to exact lines and sent back to the agent. A generated code walkthrough presents an ordered tour of relevant file ranges.
See [Sessions and review](sessions-and-review.md) for the full review loop and [Git operations](git-operations.md) before rebasing or resolving conflicts.
## Personal settings
General settings include:
- appearance, panel layout, and resource-metric visibility;
- keyboard shortcuts;
- desktop/browser notifications;
- task-action confirmations;
- terminal and editor preferences;
- named secrets used by profiles.
Keyboard shortcuts are editable in **Settings > General > Keyboard Shortcuts**. Avoid assigning the same chord to global browser, terminal, editor, and Kandev actions.
Notifications depend on browser/desktop permission and operating-system policy. Treat them as convenience signals rather than the only alert path for an unattended workflow.
## Resource and usage visibility
Kandev can show host or environment CPU, memory, disk, load, and other supported metrics. It can also surface task/session statistics and provider usage hints where an integration exposes them.
These values help diagnose capacity and activity; they are not quotas, billing guarantees, or security controls. Configure hard limits in the executor, provider, or host platform.
## Choose the right surface
| Need | Use |
|---|---|
| Short disposable question | Quick chat |
| Branch, review, or delivery state | Normal task and workflow |
| Repeatable model-assisted metadata | Utility agent |
| Shared process instructions | Prompt template and workflow |
| Inspect or edit task files | Workbench editor |
| Run project commands | Task terminal |
| Explain a change to a reviewer | Changes panel and code walkthrough |
Related: [Get started](use-kandev.md), [Tasks and workflows](tasks-and-workflows.md), and [Agents and profiles](agents-and-profiles.md).
+75
View File
@@ -0,0 +1,75 @@
---
title: "Executors"
description: "Choose and configure local, worktree, Docker, SSH, remote Docker, or Sprites task environments."
---
# Executors
An executor decides where Kandev materializes a task workspace and runs agentctl, terminals, Git operations, and the agent subprocess. An executor profile stores reusable environment policy for that runtime.
## Runtime choices
| Executor | Workspace and process location | Isolation and prerequisites |
|---|---|---|
| Local | Selected local checkout; process runs on the Kandev host. | Lowest setup cost and lowest isolation. Avoid concurrent writers. |
| Worktree | Dedicated Git worktree on the Kandev host. | Isolates branches/files between tasks, but shares the host OS, user, and accessible credentials. |
| Local Docker | Container managed by the host Docker engine. | Requires Docker and an image/profile. Container is a stronger process/filesystem boundary than a worktree. |
| Remote Docker | Container managed through a configured remote Docker host. | Requires remote daemon connectivity and credential/network planning. |
| SSH | Workspace and agentctl on a reachable Linux host. | Requires SSH authentication, remote dependencies, and enough disk/process capacity. |
| Sprites | Remote sandbox provided through Sprites. | Requires provider credentials and network access; environment lifetime and billing follow the provider. |
Kandev also has mock executor types for tests. They are not production runtime choices.
## Executor profiles
A profile can contain:
- a name and runtime-specific configuration;
- prepare script run while creating/preparing the environment;
- cleanup script run during teardown where supported;
- environment variables as plaintext or Kandev secret references;
- MCP policy;
- image, host, credential, or provider settings specific to the executor.
Scripts run with the executor's permissions and can modify the task environment. Keep them idempotent, fail loudly, avoid interactive input, and pin important tooling. A cleanup script should not delete paths outside the environment it owns.
## Pick an executor by risk and workload
Use **Worktree** for normal parallel coding on one trusted machine. It prevents two task branches from writing the same checkout but does not protect the host from agent commands.
Use **Local Docker** when repository setup is reproducible in an image and you want a container boundary. Plan how source, caches, credentials, ports, and Docker socket access are mounted; mounting the host Docker socket grants powerful host control.
Use **SSH**, **Remote Docker**, or **Sprites** when local CPU, memory, architecture, network placement, or long-running availability is unsuitable. The remote host must be able to fetch every attached repository and reach required package registries/integrations.
Use **Local** only when intentionally operating the selected checkout. It can be correct for no-repository tasks or a controlled single task, but it is easy for concurrent work to collide.
## Task environments and sessions
Kandev tracks task environment state as creating, ready, stopped, or failed. The environment owns the workspace and agentctl control server. Multiple sessions can share it, and each session has an executor-running record with runtime, process/container identifiers, worktree path/branch, health timestamps, and errors.
Stopping a session does not always delete the task environment. Resumable runtimes can retain it for a later turn. Archive/delete/cleanup behavior depends on task action, profile, and runtime.
## Repository and credential behavior
- Git operations execute inside the task environment through agentctl.
- Multi-repository tasks materialize every attachment and address repositories by subpath.
- Worktree tasks can copy selected ignored files, such as `.env` files, from the source repository. Configure this narrowly; ignored files often contain secrets.
- Local host credentials are not automatically available in a container or remote machine. Use scoped secret/profile configuration or the runtime's supported credential copy flow.
- SSH credential-copy options can expose local auth files to the remote environment. Review the selected files and remote host trust first.
## Resource metrics and capacity
Kandev can show host CPU, memory, disk, temperature, and load plus execution-environment metrics for supported remote/container runtimes. Enable the desired metrics in General settings. Metrics are observability, not hard resource limits; set limits in Docker/provider/host policy where needed.
Parallel agents can saturate CPU, memory, disk I/O, process limits, network, or provider quotas. Prefer several bounded remote environments over one overloaded host when tasks are large.
## Troubleshooting
- **Prepare failed:** inspect the environment error and logs, then run the script in the same shell/runtime with noninteractive settings.
- **Agentctl unavailable:** confirm the helper was built/copied for the remote architecture and that its control port is reachable inside the environment.
- **Repository clone fails:** test remote URL, branch, DNS, SSH known hosts, and token scope from the execution host.
- **Container starts but tools are missing:** rebuild/pin the image or install tools in the prepare script.
- **SSH task dies after disconnect:** verify remote process supervision and inspect the stored remote PID/agentctl logs.
- **No disk space:** remove stale task environments/worktrees after confirming branch state, and inspect **Settings > System > Disk usage**.
Related guides: [Docker](docker.md), [Windows](windows-support.md), and [Operations](operations.md).
+68
View File
@@ -0,0 +1,68 @@
---
title: "Extending Kandev"
description: "Add an agent, executor, integration, workflow capability, MCP tool, or settings surface using established extension points."
---
# Extending Kandev
Kandev has extension seams for agents, executors, integrations, workflow behavior, MCP tools, and UI settings. An extension is complete only when discovery/configuration, runtime behavior, failure handling, tests, and public documentation agree.
## Add an agent CLI
Agent definitions and protocol behavior live under `apps/backend/internal/agent/agents/` and register through `internal/agent/registry`. An integration describes install/discovery, ACP launch, optional passthrough, login, models/modes/capabilities, permission behavior, and MCP materialization.
Follow [Adding a new agent CLI](add-agent-cli.md). Test command construction, missing installation, login requirements, model/mode updates, permissions, resume, and the selected passthrough MCP strategy.
## Add an executor
Executor types are shared in `internal/agent/executor`; lifecycle implementations and registration live around `internal/agent/runtime/lifecycle`. Runtime-specific packages handle Docker, SSH, Sprites, worktrees, or host execution.
A production executor needs:
- profile models and secure credential fields;
- environment create/prepare/stop/cleanup behavior;
- agentctl delivery and control-channel connectivity;
- repository and multi-repository materialization;
- terminal, Git, files, ports, and metrics as supported;
- durable runtime IDs/status/errors for recovery;
- settings UI and validation;
- lifecycle, failure, and cleanup tests.
Do not advertise an executor before remote architecture, restart, cancellation, partial-create cleanup, and credential boundaries are documented.
## Add an integration
Provider packages such as `internal/github`, `gitlab`, `jira`, `linear`, `sentry`, and `slack` demonstrate the pattern: workspace-scoped config, secret storage, connection testing, provider client, service, handlers, optional watches/events, and settings UI.
Keep provider payloads behind a domain adapter. Validate server URLs and token types, redact errors, handle pagination/rate limits, and treat external text as untrusted agent input. A polling or webhook integration also needs deduplication and a visible health/run state.
## Add workflow or automation behavior
Workflow models, service, engine, adapters, and events live under `internal/workflow/`. Workspace automations live under `internal/automation/`. Preserve the distinction between task-local transitions and rules that create new work.
New events/actions need durable semantics, import/export representation when applicable, cycle/duplicate protection, UI editing, and tests for old workflow definitions.
## Add an MCP tool
Task/config MCP handlers and server registration live under `internal/mcp/handlers` and `internal/mcp/server`. Define a strict schema, enforce caller/task/workspace policy, return actionable structured errors, and test over the actual MCP transport.
Do not trust caller-supplied task identity when the server can inject it. Consider destructive-action confirmation, relationship reachability, pagination, and concurrent task state. Update [Automation and MCP](automation-and-mcp.md) when user capability changes.
## Add a settings or workbench surface
Backend configuration should have a typed API and durable ownership before a web form is added. Web settings route through `apps/web/src/settings-routes.tsx`; task surfaces live in the relevant workbench components and state slices.
Cover initial load, no dependency, invalid credential, save, test, error, reconnect, and mobile behavior. Use status text in addition to color and make every control keyboard-accessible.
## Extension completion checklist
- Registry/startup wiring cannot silently omit the extension.
- Config and secrets have clear scope and redaction.
- Capability detection is truthful when optional dependencies are absent.
- Failures persist enough state for the user to recover.
- Cleanup is idempotent and does not delete unrelated state.
- Unit, integration, and user-visible E2E coverage exists.
- Public docs include setup, trust boundary, troubleshooting, and status.
- Release packaging contains every required binary, asset, or platform variant.
Related: [Architecture](architecture.md), [Backend development](backend-development.md), [Web development](web-development.md), and [Testing](testing.md).
+59
View File
@@ -0,0 +1,59 @@
---
title: "Feature Status"
description: "Understand which Kandev capabilities are supported, dependency-bound, experimental, or still in progress."
---
# Feature Status
These docs describe the current `main` branch and are not versioned yet. A released binary can be older than this page. Check **Settings > System > About** or `kandev --version`, then compare the release notes when a screen or option differs.
## Status meanings
| Status | Meaning |
|---|---|
| Supported | Shipped in the normal product path and covered by maintained source/tests. |
| Dependency-bound | Shipped, but availability depends on an agent, provider, platform, credential, or executor. |
| Experimental | Available behind a toggle or with a deliberately limited operating contract. |
| In progress | Present in source or planning, but not documented as a supported production workflow. |
| Internal | Engineering material, test support, or implementation detail rather than a user feature. |
## User-facing capability matrix
| Area | Status | Notes |
|---|---|---|
| Workspaces, repositories, kanban, workflows, tasks, labels, and documents | Supported | Core coordination model. See [Tasks and workflows](tasks-and-workflows.md). |
| Parallel sessions and integrated files, terminal, changes, preview, plans, and PR review | Supported | Exact panels vary by viewport and task context. See [Sessions and review](sessions-and-review.md). |
| Code walkthroughs with anchored review feedback | Supported | Requires a compatible agent session with task MCP and matching files. |
| Subtasks, dependencies, multi-repository tasks, and additional task branches | Supported | Shared workspaces can still conflict; see [Coordination](coordination.md). |
| ACP agents and bring-your-own TUI agents | Dependency-bound | Installation, login, models, modes, resume, usage, and MCP capabilities vary by CLI. |
| Local, worktree, Docker, remote Docker, SSH, and Sprites executors | Dependency-bound | Each runtime has platform, host, image, credential, and lifecycle prerequisites. |
| GitHub, GitLab, Jira, Linear, Sentry, and Slack integrations | Dependency-bound | Provider API, account scope, and workspace configuration determine behavior. |
| Workflow import/export and GitHub-backed workflow sync | Supported | Imported profiles may require local mapping; sync applies guarded updates. |
| Task MCP and external backend MCP | Supported | External MCP has no Kandev user-auth boundary and must be network-protected. |
| Scheduled, webhook, GitHub PR/push/CI automations | Supported | Begin with narrow filters, credentials, and concurrency. |
| Desktop app, CLI, service, Docker, and remote-host deployment | Supported | Platform-specific installation and signing details vary by release channel. |
| Kubernetes deployment guide | Experimental | The guide describes deploying Kandev; a first-class Kandev Kubernetes executor/operator is not shipped. |
| Resource metrics, statistics, backups, logs, updates, and task Gist shares | Supported | Some provider metrics and update actions depend on install channel. |
| Voice engines and language-server/editor integration | Dependency-bound | Browser APIs, models, binaries, credentials, and platform support vary. |
| Feature toggles | Experimental | Intended for unfinished or diagnostic behavior and may require restart. |
| Office mode | In progress | Feature-flagged autonomy work; persistent agent teams, routines, budgets, and related UX are not yet a supported public contract. |
| Kubernetes executor/operator | In progress | Listed as a future remote runtime direction, not a current executor choice. |
## Source and publication boundary
User-ready pages live in `docs/public/**` and are published at `kandev.ai/docs`. Other files under `docs/**` can be architecture notes, ADRs, plans, specifications, test procedures, release internals, or historical context. Their presence does not change a capability's public status.
When behavior changes, update the implementation, tests, relevant public page, and this matrix in the same pull request. See [Contributing to the docs](README.md) and [Contributing to Kandev](contributing.md).
## Verify behavior in your installation
For a feature you intend to rely on:
1. confirm the running Kandev version;
2. inspect the relevant settings screen and health status;
3. verify the selected agent/executor/provider dependency;
4. test the smallest representative task without production credentials;
5. confirm failure, retry, review, and cleanup behavior;
6. keep a human gate until the workflow has proven safe for its repository.
Open a bug with the version, platform, executor, agent profile, reproduction steps, expected behavior, logs, and screenshots when the current release disagrees with these docs.
+33 -69
View File
@@ -1,85 +1,49 @@
---
title: "Overview"
description: "Start building with Kandev agentic development workflows."
title: "Kandev Documentation"
description: "Choose a guide for running agentic development work or contributing to Kandev itself."
---
# Kandev Feature Guide
# Kandev Documentation
This page expands the short feature list in the README without turning the README into a catalog.
Kandev is an open-source workbench for planning, running, coordinating, and reviewing software work with coding agents. It runs on infrastructure you control, works with multiple agent providers, and keeps the human review surface close to the repository state.
## Agent And Task Workflows
Choose the path that matches what you are doing now.
- **Parallel task execution:** run and review multiple agent tasks at once.
- **Kanban and pipeline workflows:** define workflow steps, prompts, automations, and agent handoffs per step.
- **Workflow import/export:** export one workflow or every workflow in a workspace as portable YAML, then import it into another workspace or Kandev install. See [workflow-import-export.md](workflow-import-export.md).
- **Workflow sync from GitHub:** keep a workspace's workflows in sync with definition files in a GitHub repo — Kandev polls the repo on an interval, with a force-sync option and warnings when a change can't be applied. See [workflow-sync.md](workflow-sync.md).
- **Subtasks:** split work into child tasks that inherit the parent task's workspace, workflow, agent profile, executor, and repositories by default.
- **Multi-repository tasks:** attach several repositories to one task. Each repository gets its own worktree and is grouped separately in changes, review, and PR surfaces.
- **Multi-branch tasks:** attach multiple branches from the same repository to one task when the work needs to produce several PRs.
- **Task documents:** tasks can hold multiple markdown documents with revision history, including plans, specs, notes, reviews, and custom documents.
- **Task labels:** workspace labels are reusable, filterable, and visible on task cards and task detail.
- **Public share links:** publish a redacted task conversation snapshot as a secret GitHub Gist after previewing exactly what will be shared. Existing shares can be revoked.
## Use Kandev
## Agent Interfaces
Start here when you want to install Kandev, connect repositories and tools, run agents, or design a team workflow.
- **ACP agents:** Kandev supports ACP-native and ACP-adapter agents such as Claude Code, Codex, GitHub Copilot, Gemini CLI, Amp, Auggie, OpenCode, Cursor, Qwen, Factory Droid, iFlow, Kilocode, Pi, Kimi, Kiro, Qoder, Trae, Oh My Pi, and Grok.
- **Bring-your-own TUI agents:** any agent CLI can run in a PTY terminal through CLI passthrough, even without ACP support.
- **Voice mode:** dictate chat prompts from the composer. Supported engines include browser Web Speech, local in-browser Whisper Web, and server-side Whisper. Settings include language, click-to-toggle or hold-to-talk activation, auto-send, Whisper model size, and keyboard shortcut.
- **Utility agents:** one-shot helpers can generate or improve prompt text, branch names, commit messages, commit descriptions, PR titles, PR descriptions, and session summaries. Users can choose a default model, override models per action, and add custom utility agents.
- **Custom prompts:** reusable prompts can be created in settings and invoked from chat.
- **Secrets:** named secrets can be stored once and reused by profiles or integrations without pasting values into every task.
- [Get started](use-kandev.md): install Kandev and complete a first task.
- [Tasks and workflows](tasks-and-workflows.md): choose a workflow, create tasks, and move work through gates.
- [Sessions and review](sessions-and-review.md): use chat, files, terminal, changes, plans, pull requests, and code walkthroughs.
- [Coordinate work](coordination.md): use subtasks, dependencies, multiple repositories, multiple branches, plans, and handoffs.
- [Agents and profiles](agents-and-profiles.md): select models and modes, configure CLI flags and environment, and understand permission controls.
- [Executors](executors.md): choose local, worktree, Docker, SSH, or Sprites execution.
- [Integrations](integrations.md): connect GitHub, GitLab, Jira, Linear, Sentry, and Slack.
- [Developer tools](developer-tools.md): quick chat, prompts, utility agents, voice, editors, terminal, shortcuts, and notifications.
- [Automation and MCP](automation-and-mcp.md): automate workflow transitions and let agents coordinate Kandev tasks.
- [Feature status](feature-status.md): see what is supported, optional, experimental, or still in progress.
## Executors And Runtime
For installation and deployment details, use the [CLI reference](cli.md), [desktop guide](desktop-app.md), [configuration reference](configuration.md), or one of the runtime guides under **Run and Operate**.
- **Desktop app:** install Kandev as a Tauri desktop app that starts the local backend and shows the existing Kandev UI without requiring Node.js at runtime. See [desktop-app.md](desktop-app.md).
- **Executor types:** run agents as local host processes, git worktrees, Docker containers, remote SSH sessions, or Sprites cloud environments.
- **Executor profiles:** save per-runtime configuration, including prepare scripts, environment variables, credentials, and profile-specific settings.
- **Worktree isolation:** concurrent agents work in isolated git worktrees so their changes do not collide.
- **Per-task repository setup:** repositories can copy selected ignored files, such as `.env` files, into newly created worktrees.
- **Resource monitor:** optionally show CPU, memory, disk, CPU temperature, and load metrics in desktop task and kanban topbars. Kandev can also collect execution-environment metrics for Docker, SSH, Sprites, and other remote runtimes.
## Contribute to Kandev
## Integrations And MCP
Start here when you are changing Kandev, extending an integration, or maintaining its public documentation.
- **Integrations:** GitHub, GitLab, Jira, Linear, Sentry, and Slack connect external work back into Kandev tasks.
- **External MCP:** Kandev exposes streamable HTTP and SSE MCP endpoints so external coding agents can manage Kandev from outside the app. Settings include copyable snippets for Claude Code, Cursor, Codex, Auggie CLI, OpenCode, and GitHub Copilot CLI.
- **Automatic session MCP:** agents launched normally inside Kandev receive the Kandev task MCP automatically.
- **Passthrough MCP:** passthrough agents can also use the Kandev MCP endpoint while keeping their native CLI interface.
- [Contribution workflow](contributing.md): prepare a development environment and open a focused pull request.
- [Architecture](architecture.md): understand the unified Go backend, embedded web app, persistence, events, agent runtime, and external boundaries.
- [Backend development](backend-development.md): follow handler, service, repository, event, migration, and WebSocket conventions.
- [Web development](web-development.md): work with the Vite/React app, state slices, API clients, WebSocket handlers, responsive task UI, and design system.
- [Testing](testing.md): choose targeted Go, Vitest, CLI, desktop, or Playwright coverage and use isolated fixtures.
- [Extension guides](extending-kandev.md): add agents, executors, integrations, settings, MCP tools, prompts, and workflow behavior.
- [Adding an agent CLI](add-agent-cli.md): implement a new ACP or TUI integration end to end.
- [Release process](release-process.md): understand versioning, release automation, runtime bundles, desktop artifacts, npm, Homebrew, and containers.
- [Public docs guide](README.md): update a page or add a new entry to this navigation.
## What Task Agents Can Do Through Kandev MCP
## Product Boundary
Agents running on regular kanban tasks receive a task-scoped MCP surface. The available tools let agents coordinate work without leaving Kandev:
The regular task workbench and task-scoped Kandev MCP are shipped features. **Office mode is separate and remains feature-flagged and in progress.** Internal plans, ADRs, and experiments can explain direction, but they are not promises that a feature is generally available. The [feature status page](feature-status.md) records that boundary explicitly.
- **Discover workspace context:** list workspaces, workflows, workflow steps, repositories, agents, executor profiles, and tasks.
- **Work with multi-repo tasks:** task responses include attached repositories, base branches, checkout branches, and positions so agents can reason about each worktree separately.
- **Create tasks and subtasks:** create top-level tasks or child tasks, optionally auto-starting an agent. Subtasks inherit the parent workspace, workflow, agent profile, executor, and repositories unless the agent supplies an override.
- **Target sibling repositories:** create a subtask in a different repository while keeping it under the same parent task and workspace.
- **Coordinate dependencies:** create tasks with blocker relationships and inspect related parent, child, sibling, blocker, and blocked-by tasks.
- **Attach more branches:** add another `(repository, branch)` worktree to an existing worktree task. Use this for multiple PRs from one task, either in the same repository or across repositories.
- **Adjust diff bases:** update a task repository's base branch so changes, ahead/behind counts, and review context compare against the right target branch.
- **Move, archive, or delete tasks:** move tasks across workflow steps, including optional handoff prompts for the next agent, or clean up tasks when appropriate.
- **Message other tasks:** send a prompt to another task's primary session. Running tasks queue the message for the next turn; idle tasks receive it immediately; created sessions start with it.
- **Read conversations:** fetch a task's conversation history, with pagination and message-type filters.
- **Record structured plans:** create, read, update, and delete task plans.
- **Signal completion:** explicitly tell Kandev that a workflow step is complete, with summary, handoff notes, and blockers.
- **See associated PRs:** task-listing and related-task responses include associated GitHub pull requests when available, including PR number, URL, title, state, and merge time.
## Current Version
## In Progress: Office Mode
Office mode is currently feature-flagged and not documented as a live supported feature yet. The planned direction is a higher-level autonomy workspace with:
- Persistent agent instances with roles, permissions, skills, instructions, memory, status, and executor preferences.
- Agent dashboards, run history, inbox items, approvals, and human review gates.
- Task delegation across agent teams, including parent/child task coordination.
- Routines and scheduler-driven recurring work.
- Cost tracking, model usage visibility, and budget guardrails.
- Workspace configuration import/export and sync for agent/team setup.
We'll move Office into the live feature inventory after it ships.
## System Management
- **Feature toggles:** runtime feature flags can be viewed and overridden from Settings > System, with restart prompts when required.
- **Updates:** Kandev can check for newer releases and apply signed, confirmed updates from the desktop app or supported service installs.
- **Backups and restore:** Kandev creates snapshots before version upgrades and supports manual snapshots, download, restore, and deletion from the system settings page.
- **Disk usage:** inspect storage used by worktrees, repositories, sessions, tasks, quick chat, and backups.
- **Logs, database status, about, and licenses:** system settings include operational views useful for self-hosted installs.
These docs describe the current `main` branch and are not versioned yet. Commands and configuration are verified against source, but a released build can lag `main`. Check the version in **Settings > System > About** or run `kandev --version`, then consult the corresponding GitHub tag when exact historical behavior matters.
+64
View File
@@ -0,0 +1,64 @@
---
title: "Integrations"
description: "Connect workspace-scoped GitHub, GitLab, Jira, Linear, Sentry, and Slack accounts to Kandev."
---
# Integrations
Integrations bring repository, ticket, incident, and notification context into a Kandev workspace. They do not replace the credentials used by an executor or agent process. A GitHub integration can let Kandev inspect and create pull requests, for example, while the task environment still needs its own Git credentials to fetch or push.
## Configure an integration
Open **Settings > Workspaces**, select the workspace, and open **Integrations**. The same providers also appear under the top-level **Settings > Integrations** route for the active workspace.
1. Choose a provider.
2. Enter its server or organization details and a scoped credential.
3. Save and run the available connection test.
4. Confirm the integration reports healthy before relying on it in a workflow.
5. Create a small test task or notification before enabling an unattended automation.
Integration configuration and secrets are workspace-scoped. Configure each workspace independently when teams or repositories use different accounts.
## Supported providers
| Provider | Kandev uses it for | Configuration notes |
|---|---|---|
| GitHub | Repository discovery, issues, pull requests, reviews, checks, branches, Gist task shares, and GitHub-triggered automations. | Prefer a fine-grained token or app access limited to the required repositories and actions. |
| GitLab | Repository and merge-request context for GitLab-hosted work. | Set the correct GitLab base URL for self-managed instances and scope the token to the projects Kandev needs. |
| Jira | Ticket lookup, project/status discovery, transitions, and issue-watch triggers. | Jira Cloud uses API-token authentication. Personal access tokens are for Jira Server or Data Center. |
| Linear | Issue/team context and watches that can create Kandev work from matching issues. | Verify the selected workspace/team and token permissions before enabling a watch. |
| Sentry | Issue and project context for debugging and task creation flows. | Limit the token to the organizations and projects used by the Kandev workspace. |
| Slack | Workspace communication and Slack-triggered agent runs where configured. | Treat channel access, bot permissions, and any exposed MCP endpoint as part of the deployment trust boundary. |
The settings screen in the running release is authoritative for fields and supported operations. Provider APIs and token formats can change independently of Kandev.
## Repository access versus provider access
There are three distinct credential paths:
- **Kandev integration credentials** let the backend call a provider API.
- **Git credentials in the task environment** let Git fetch and push repository data.
- **Agent credentials** let the selected coding agent call its model provider and any tools it owns.
One does not automatically grant the others. A task can display a pull request while its executor cannot push, or an agent can edit a worktree while Kandev cannot read CI checks. Diagnose the failing path separately.
## Use external context safely
Issue bodies, pull-request comments, commit messages, chat messages, and incident details are untrusted input. If a workflow forwards that content to an agent, it can contain instructions intended to influence the agent.
- Keep write credentials out of read-only triage workflows.
- Review generated branches, comments, transitions, and notifications before broad automation.
- Restrict repository and channel scope instead of using account-wide tokens.
- Do not include secrets in task descriptions or provider comments.
- Use explicit human gates for production changes and sensitive issue queues.
## Troubleshooting
- **Connection test fails:** check the provider base URL, token type, expiration, scopes, and network access from the Kandev backend host.
- **Repository or project is missing:** confirm the authenticated account can see it and that workspace filters do not exclude it.
- **Kandev can read but not write:** add only the specific write scope needed, then repeat the test.
- **Pull request state is stale:** refresh the task and inspect provider health; webhook and polling behavior differs by integration.
- **Task environment cannot push:** fix its Git/SSH credential path. Changing the backend integration token may not affect Git running inside an executor.
- **Automation creates unexpected work:** disable the automation, inspect its provider filters and run history, then narrow repositories, branches, authors, labels, or issue query.
Related: [Tasks and workflows](tasks-and-workflows.md), [Automation and MCP](automation-and-mcp.md), and [Executors](executors.md).
+27 -5
View File
@@ -1,23 +1,45 @@
{
"title": "Kandev Docs",
"pages": [
"---Start---",
"---Choose Your Path---",
"index",
"---Use Kandev---",
"use-kandev",
"tasks-and-workflows",
"sessions-and-review",
"coordination",
"agents-and-profiles",
"executors",
"integrations",
"developer-tools",
"automation-and-mcp",
"feature-status",
"---Install and Configure---",
"cli",
"configuration",
"desktop-app",
"---Execution---",
"configuration",
"---Run and Operate---",
"docker",
"k8s",
"run-as-a-service",
"remote-cloud-environment",
"windows-support",
"---Workflows---",
"operations",
"---Workflow Reference---",
"workflow-tips",
"workflow-import-export",
"workflow-sync",
"git-operations",
"---Contribute to Kandev---",
"contributing",
"architecture",
"backend-development",
"web-development",
"testing",
"extending-kandev",
"add-agent-cli",
"---Reference---",
"release-process",
"---Protocol Reference---",
"websocket-api"
]
}
+99
View File
@@ -0,0 +1,99 @@
---
title: "Operations"
description: "Operate, back up, update, monitor, and recover a local or self-hosted Kandev installation."
---
# Operations
Kandev can run as a local developer application or an always-on service. In both cases the backend owns durable task state, worktree metadata, credentials, logs, and the static web application. Treat its data directory as stateful application storage.
## Start with system status
Open **Settings > System > Status** to inspect health issues, build/version information, disk usage, and UI state. Use this page before debugging an individual task: a database, filesystem, process-limit, or disk problem can affect every executor.
The backend also exposes health checks for service managers and deployment probes. Use the endpoints documented by the selected deployment guide rather than checking only whether the web page returns HTML.
## Data and database
SQLite is the default database and fits local or single-instance service deployments. The database and managed workspaces live under the configured Kandev data directory, `~/.kandev` by default.
PostgreSQL is optional for deployments that configure it. Do not point multiple Kandev processes at one SQLite file or assume that switching database drivers migrates existing state automatically.
**Settings > System > Database** shows the active driver, size, and supported maintenance operations. Take a verified backup before reset, migration, upgrade, or destructive cleanup.
## Backups
For SQLite, **Settings > System > Backups** creates consistent snapshots with SQLite `VACUUM INTO` under `<data-dir>/backups/`. Kandev can also create safety snapshots around update flows.
A complete recovery plan also accounts for:
- repository branches and unpushed commits in managed worktrees;
- executor-specific remote state;
- service configuration and environment variables;
- secrets stored outside or alongside the database;
- provider-side pull requests, issues, and Gist shares.
Copy backups off the host and test restoration on a separate instance. A backup that has never been restored is not a verified recovery path.
## Logs
**Settings > System > Logs** shows recent backend output and downloadable rotated log files. The CLI flags `--verbose` and `--debug` increase detail; debug mode can include agent message dumps, so avoid it on sensitive workloads unless the storage and retention are acceptable.
For a service deployment, capture stdout/stderr in the service manager as well. Correlate task ID, session ID, execution ID, repository, and timestamp across Kandev, agentctl, executor, reverse-proxy, and provider logs.
## Disk and stale environments
Repositories, worktrees, task files, agent logs, package caches, container layers, and backups all consume disk. System status reports Kandev-managed usage, but remote hosts and Docker storage need their own monitoring.
Before removing a stale worktree or environment:
1. inspect uncommitted and untracked files;
2. confirm commits were pushed to the intended remote;
3. record any associated pull request;
4. stop active sessions using it;
5. remove it through Kandev when possible so database state stays consistent.
## Updates
**Settings > System > Updates** reports the current and latest release and shows changelog information. For persistent installations, update through the install channel:
```bash
brew upgrade kandev
npm install -g kandev@latest
```
If you run Kandev transiently with npx, invoke the latest release with `npx kandev@latest`; this does not update a persistent installation.
For a service or container, follow that deployment's replacement and restart process. Read release notes, create a backup, drain or stop active sessions, update the runtime, and check status before resuming automation.
## Runtime metrics
Kandev can show supported host and task-environment resource metrics. Use them to identify CPU, memory, load, temperature, and disk pressure. Configure alerting and hard limits in the host, container platform, or remote provider; the UI is observability, not a scheduler quota.
## Feature toggles and diagnostics
**Settings > System > Feature Toggles** controls experimental or diagnostic features that are compiled into the running release. A toggle can require a restart and can expose unfinished behavior. Record non-default toggles in incident reports and disable them when isolating a regression.
Office mode is feature-flagged and in progress. Do not use its internal presence as evidence that persistent autonomous teams are supported for production use.
**Settings > System > Licenses** lists shipped Go and npm dependency licenses. **About** shows build metadata useful in support reports.
## Remote deployment security
- Put the web/backend behind a private network or an authenticated ingress appropriate to your organization.
- Do not expose the unauthenticated external MCP endpoint to the internet.
- Run Kandev under a dedicated service user with only the repository and executor access it needs.
- Store provider and Git credentials in the deployment secret system and rotate them independently.
- Restrict Docker socket, SSH keys, forwarded ports, and prepare scripts as privileged interfaces.
- Back up state before changing versions, database drivers, or data-directory ownership.
See [Run as a service](run-as-a-service.md), [Docker](docker.md), [Remote environments](remote-cloud-environment.md), and [Configuration](configuration.md) for concrete deployment settings.
## Incident checklist
1. Disable the affected automation or stop new task starts.
2. Preserve logs and note version/build metadata.
3. Inspect database, disk, process, executor, and integration health.
4. Protect unpushed repository state before cleanup or rollback.
5. Restore or roll back only from a verified backup and compatible version.
6. Re-enable one workflow or executor at a time and monitor run history.
+61
View File
@@ -0,0 +1,61 @@
---
title: "Release Process"
description: "Understand Kandev's automated version, changelog, runtime bundle, desktop, npm, GitHub, and Homebrew release flow."
---
# Release Process
Kandev uses one semantic version for the CLI, native runtime bundles, desktop artifacts, npm packages, Git tag, GitHub release, and Homebrew formula. Releases are driven by the **Release** GitHub Actions workflow, not by manually publishing individual channels.
## Before a release
1. Confirm required checks pass on `main`.
2. Review user-visible changes and update `docs/public/**` plus changelog inputs.
3. Verify platform-sensitive launcher, agentctl, and desktop changes on their target systems.
4. Confirm publishing credentials, signing/notarization secrets, npm access, and Homebrew tap access are healthy.
5. Avoid starting a release while another version or release PR is active.
## Run the workflow
In GitHub Actions, open **Release**, choose **Run workflow**, select `patch`, `minor`, or `major`, and optionally enable dry-run validation.
The workflow validates the requested bump, computes the next version, updates the package version and changelog, opens and merges the release PR, creates the `vX.Y.Z` tag, then builds and publishes the release channels.
Do not create a competing tag or edit generated release files while the workflow is running.
## Artifacts and channels
The release produces platform runtime bundles containing the unified `kandev` binary and agentctl helpers. npm installs a small launcher plus one platform-selected `@kdlbs/runtime-*` optional package. Homebrew consumes GitHub release tarballs. The Tauri desktop build embeds the matching runtime before packaging and signing.
Supported runtime targets and artifact shapes are maintained in `apps/cli/README_internal.md` and the release scripts. When adding a platform, update build matrices, npm optional dependencies, archive names, launcher mapping, tests, checksums, desktop resources, and Homebrew handling together.
## Signing and publishing
Desktop signing/notarization and package publishing depend on repository secrets. Logs and artifacts must not expose signing material. A failure after the tag exists is a release-repair incident: inspect which channels published before rerunning or changing tags.
Never overwrite an already published semantic version. Fix the pipeline and publish a new patch when immutable package registries or release assets require it.
## Verify the release
After publication:
- check the GitHub release, notes, checksums, and expected platform archives;
- install with `npx kandev@latest` in a clean directory;
- verify a Homebrew install or upgrade;
- launch the desktop artifact on signed target platforms;
- run `kandev --version` and a minimal first task;
- confirm the Updates screen sees the new release;
- verify public docs describe the shipped behavior rather than unreleased `main` where it matters.
## Rollback and repair
Published artifacts are immutable evidence. If a release is broken:
1. stop or disable the failing publication stage if it is still running;
2. record which channels and architectures are affected;
3. preserve logs and release metadata;
4. fix on `main` with focused tests;
5. publish a new patch release;
6. document upgrade or mitigation steps for affected users.
For the exact workflow implementation, inspect `.github/workflows/release.yml`, `scripts/release/`, `apps/cli/README_internal.md`, and the desktop signing documentation in the repository. These internal files are more detailed but are not the user-facing product contract.
+89
View File
@@ -0,0 +1,89 @@
---
title: "Sessions and Review"
description: "Work with agent chat, files, terminals, diffs, plans, pull requests, and code walkthroughs in one task."
---
# Sessions and Review
A Kandev session is an agent conversation attached to a task and its execution environment. The workbench keeps conversation, repository state, commands, files, and review feedback visible together so a final agent message is never the only evidence of completion.
## Start and resume sessions
The first workflow action can create a primary session automatically. You can also start another session from task detail and choose a compatible agent profile, model, mode, and executor context.
Structured ACP sessions can resume when the agent/runtime provides a resume identifier. SSH and Sprites environments are treated as resumable runtimes at the environment level. A stopped process, removed worktree, expired cloud environment, or agent that does not support session resume can still require a fresh turn.
Multiple sessions on one task can share its task environment. They also share the underlying files, so do not run two writers concurrently unless the prompts and file ownership make that safe.
CLI passthrough is different from structured chat: Kandev hosts the agent's native terminal interface in a PTY. It retains task/worktree tracking and can expose task MCP, but message rendering and resume behavior depend on the CLI.
## Workbench surfaces
Desktop task detail can combine these panels:
- **Agent chat:** prompts, tool calls, permission requests, clarification questions, todos, usage, and session status.
- **Files and editor:** browse, search, open, edit, and inspect text or image files. Language servers can be configured under Editors settings.
- **Terminal:** run repository commands in the task environment; remote/container executors route the shell through agentctl.
- **Changes:** inspect working-tree, staged, commit, branch, and pull-request diffs, grouped by repository for multi-repo tasks.
- **Plan/documents:** read and edit the task's structured plan and other documents.
- **Preview/browser:** open a forwarded application port when the executor and task expose one.
- **Pull request:** inspect linked PR state and review feedback when the integration is available.
Panel presets and layout are user preferences. Mobile uses task-native sheets and bottom navigation for sessions, files, terminal, and changes instead of shrinking the desktop dock layout.
## Give review feedback with context
Feedback can be attached to:
- changed lines in a diff;
- selected editor content or files;
- plan text;
- pull-request review comments;
- a code-walkthrough step;
- images or file attachments.
Kandev formats those context items into the next message so the agent sees the relevant path, line range, source text, and comment. Review the composed prompt before sending; stale line numbers or a changed diff base can make old comments ambiguous.
## Plan before implementation
Plan mode asks the agent to analyze and record an implementation plan rather than modify the repository immediately. In workflows such as Plan & Build or Feature Dev, the plan is a shared task document and the next step can be blocked on human review.
Use plan mode when requirements, architecture, migrations, or cross-repository ownership need agreement. It is not a sandbox: the selected agent still has the executor permissions configured for that session, so permission policy remains relevant.
## Request a code walkthrough
The Changes and expanded review surfaces can ask the agent to create an anchored walkthrough of the current change. Kandev sends the built-in `changes-walkthrough` prompt, and an agent with task MCP calls `show_walkthrough_kandev` with a title and ordered file/range steps.
When the walkthrough arrives:
1. Open the walkthrough launcher.
2. Move through the ordered steps.
3. Kandev opens the referenced file and highlights the anchored range when it can match the path.
4. Add feedback to an individual step; the next agent message includes the walkthrough explanation and anchor context.
5. Close the walkthrough to keep it available, or discard it after confirmation to remove the persisted tour.
The mobile UI presents the same walkthrough as a bottom sheet with an anchored editor range. A walkthrough is agent-authored explanation, not proof that the change is correct; validate the diff and tests separately.
## Review Git and pull-request state
The Changes panel can issue pull, push, rebase, merge, and abort operations through agentctl. These operations run in the task workspace and are serialized per environment. Read [Git operations](git-operations.md) before resolving conflicts or rewriting branch history.
For a multi-repository task, select the correct repository before committing, pushing, or opening a pull request. Each repository has its own base, task branch, diff, and PR association.
Before marking a task done:
- inspect all changed and untracked files;
- run the project's required checks in the task environment;
- confirm the diff base and branch are correct;
- review agent-generated commit and PR text;
- check linked CI and review feedback;
- keep human approval outside the agent when policy requires it.
## Common failures
- **No terminal or file data:** the environment may still be preparing, agentctl may be unavailable, or the task has no repository.
- **Resume starts fresh:** the agent or runtime did not retain a usable resume token, or its environment was removed.
- **Changes are empty:** select the right repository and diff target, then confirm the agent wrote inside the materialized task path.
- **Preview does not load:** start the application on a reachable interface, confirm the port, and create/inspect the forward for remote executors.
- **Walkthrough does not appear:** the agent must have task MCP, call the walkthrough tool successfully, and reference files Kandev can match.
- **Permission prompt blocks the turn:** answer it in chat, or change the profile policy only after assessing the command and trust boundary.
+95
View File
@@ -0,0 +1,95 @@
---
title: "Tasks and Workflows"
description: "Model development work with workspaces, workflows, steps, tasks, sessions, automations, and review gates."
---
# Tasks and Workflows
Kandev separates the thing being delivered from the process used to deliver it. A **task** holds the goal and repository context. A **workflow** defines the steps, prompts, events, and agent behavior that move that task from intake to completion.
## Core concepts
| Concept | Purpose |
|---|---|
| Workspace | Scope for repositories, workflows, integrations, labels, settings, and tasks. |
| Workflow | Reusable process made of ordered steps and transition rules. |
| Workflow step | Current process state, such as Todo, Plan, Work, Review, or Done. |
| Task | Goal, description, labels, repository/branch attachments, documents, dependencies, and sessions. |
| Task repository | One base branch and one materialized task branch/worktree within the task. A task can have several. |
| Session | One agent conversation or passthrough terminal run attached to the task. |
| Task environment | Executor-owned workspace that can be reused by multiple sessions for the same task. |
The board and pipeline are two views of the same workflow state. Moving a card changes its workflow step; it does not by itself prove that code was committed, pushed, reviewed, or merged.
## Create a task deliberately
The task dialog requires a title, workspace workflow, and repository selection unless **No repository** is chosen. Depending on the workflow and task kind, it also selects:
- starting workflow step;
- one or more repositories and base branches;
- agent and agent profile;
- executor and executor profile;
- initial prompt or description;
- labels and integration context.
Use **No repository** for research, planning, ticket triage, or other work that genuinely does not need a checkout. Repository-aware tools, Changes, branch operations, and pull-request creation are naturally unavailable in that mode.
For local repositories, Kandev checks branch state before materializing a fresh branch. Read the warning if the selected checkout is dirty or the requested base cannot be resolved. For remote repositories, the chosen credentials must be able to clone and fetch the base branch.
## Workflow events and automations
A step can react to events such as:
- a task entering the step;
- the user sending a message;
- an agent turn completing;
- a task or session reaching a relevant state.
Actions can start or stop an agent, send a configured prompt, move the task, or run a workflow automation. This is why a card can move without a manual drag and why sending feedback in Review can return a task to Work.
Review every step's events before enabling a workflow for a team. A loop that starts an agent on entry and moves back into the same start condition can spend compute repeatedly. Keep an explicit human gate where a person must inspect or approve the result.
For complete built-in examples, see [Workflow tips](workflow-tips.md). Workflows can be [exported and imported](workflow-import-export.md) or [synchronized from GitHub](workflow-sync.md).
## Plans and task documents
Tasks can hold multiple Markdown documents with revision history. Built-in document kinds include plans and reviews, and workflows or agents can create additional structured notes.
In a planning workflow:
1. The agent inspects the repository and records a plan through Kandev task MCP.
2. The plan appears as a task document rather than disappearing into chat history.
3. A human can edit the shared plan before implementation.
4. The implementation agent retrieves the current revision, including those edits.
Documents are coordination state, not executable guarantees. Confirm that the implementation and review still match the accepted plan.
## Labels, filters, and task lists
Workspace labels can classify tasks by area, urgency, owner, or any team convention. Labels are visible on cards and task detail and can be used with board/list filters.
The Tasks view supports sorting and grouping independently of the kanban board. Use it to find archived or cross-workflow work without changing task state.
## Sharing a task snapshot
Kandev can publish a redacted conversation snapshot as a secret GitHub Gist. The flow presents a preview before creation and lets you revoke an existing share.
"Secret" Gists are unlisted, not access-controlled. Anyone with the URL can read one. Inspect the preview for source code, credentials, customer data, repository names, and agent tool output before publishing. Revoke the share when its purpose is complete.
## Archive, unarchive, and delete
- **Archive** hides completed or parked work while preserving its task history.
- **Unarchive** restores the task. If its local branches no longer exist, the next session can start from the configured base rather than recreating deleted local state automatically.
- **Delete** removes task records and associated runtime state according to the confirmation flow. Use it for disposable tasks, not as a substitute for understanding the branch or pull request.
Kandev can warn before archive through the task-action preference in General settings. Keep that safeguard enabled when unfinished branches or open pull requests are common.
## Troubleshooting workflow behavior
- If no agent starts, inspect the step events and confirm the task has a compatible agent and executor profile.
- If the task moves unexpectedly, inspect every automation attached to the source and destination steps.
- If a workflow imported but profiles are unresolved, map its portable agent reference to an installed profile.
- If a synchronized workflow cannot update, read its warning; tasks in renamed or removed steps can block a destructive change.
- If an agent runs but cannot see the expected repository, inspect all task-repository attachments and the executor's materialized paths.
Related: [Sessions and review](sessions-and-review.md), [Coordination](coordination.md), and [Workflow import/export](workflow-import-export.md).
+113
View File
@@ -0,0 +1,113 @@
---
title: "Testing"
description: "Choose the right Kandev test layer and run backend, web, CLI, script, desktop, and end-to-end checks."
---
# Testing
Kandev tests behavior at several boundaries. Use the narrowest test that proves a rule, then add an end-to-end scenario when the user-visible path crosses processes or protocols.
## Standard checks
From the repository root:
```bash
make fmt
make typecheck
make test
make lint
```
`make test` includes backend, web, CLI, and repository-script tests. The browser E2E suite is separate:
```bash
make test-e2e
```
Every change under `apps/web/` must add or update Playwright coverage.
## Backend tests
Go unit and integration tests live next to their packages. Use `-tags fts5` to match the SQLite build path:
```bash
cd apps/backend
go test -tags fts5 ./internal/workflow/...
go test -tags fts5 ./internal/agent/runtime/lifecycle -run TestName
```
Prefer table tests for validation and state transitions. Use temporary databases, fake clocks/providers, `httptest`, and the existing test helpers. A persistence change needs repository coverage; a handler change needs malformed-input and transport coverage; a background flow needs retry/cancellation/status coverage.
Agent adapter E2E tests under `internal/agentctl/server/adapter/e2e` exercise protocol lifecycle behavior without requiring the full browser stack.
## Web unit tests
Web tests run with Vitest:
From a fresh worktree, install the locked workspace dependencies first:
```bash
cd apps
pnpm install --frozen-lockfile
cd ..
```
Then run the full web test target or a focused test from the repository root:
```bash
make test-web
cd apps && pnpm --filter @kandev/web test -- path/to/file.test.tsx
```
Test state transitions, interaction, accessibility semantics, and failure paths rather than snapshots of incidental markup.
## Playwright E2E
The suite under `apps/web/e2e/` starts production-shaped backend/web services and uses isolated seed APIs and test fixtures. Setup:
```bash
make bootstrap-e2e
make test-e2e
```
Useful modes include `make test-e2e-headed` and `make test-e2e-ui`.
- Seed only the data the story needs.
- Use unique test identifiers and repositories.
- Do not connect to a developer's normal Kandev database or task workspace.
- Assert persisted/user-visible outcomes, not fixed sleeps.
- Preserve traces/screenshots for failures.
- Cover native mobile routes when the mobile experience differs from desktop.
The internal `docs/test_e2e_web.md` contains fixture and debugging detail for contributors working directly on the suite.
## Agent and executor E2E
Agent tests use mock agents and executor-specific harnesses to cover launch, permission, MCP, resume, terminal, and lifecycle behavior. Docker and Sprites suites have additional prerequisites and are not implied by a fast local unit run.
When changing runtime code, test the relevant local path and a remote/container-shaped path. Include failure during prepare, process start, reconnect, and cleanup where the change can affect them.
## CLI, desktop, and scripts
```bash
make test-cli
make test-scripts
```
Desktop tests live under `apps/desktop/`; the script suite also includes a desktop launch smoke test. Shell, Python, workflow-lint, release, and documentation validators are part of `make test-scripts` because failures there can block packaging or deployment even when application tests pass.
## Windows coverage
`make test-windows` runs the curated cross-platform subset used by Windows CI. Do not assume POSIX shell commands, symlink behavior, process signals, or delete-while-open semantics apply on Windows. Add platform guards only for genuinely platform-specific behavior; prefer portable fixtures where possible.
## Before requesting review
Record:
- exact commands and test counts;
- manual paths, viewport/platform, and executor used;
- any suite not run and why;
- known flaky or dependency-bound behavior;
- screenshots, traces, or logs needed to understand a failure.
A green unit test does not replace manual review of a generated diff, provider side effect, migration, or security boundary.
+91
View File
@@ -0,0 +1,91 @@
---
title: "Get Started"
description: "Install Kandev, connect a repository, run a first agent task, and review the result."
---
# Get Started with Kandev
Kandev coordinates coding-agent work around real repositories, branches, tasks, and review state. The fastest useful setup is one local repository, one agent profile, and the built-in Kanban workflow.
## Prerequisites
- Git and access to the repository you want to use.
- Credentials for at least one supported coding agent. The agent CLI must be installed or installable by the command shown in **Settings > Agents**.
- Node.js/npm only when using the npm or `npx` distribution. The desktop and Homebrew bundles include the Kandev runtime.
- Docker only when you choose a Docker executor.
## Install and start
Choose one channel:
```bash
# macOS or Linux with Homebrew
brew install kdlbs/kandev/kandev
kandev
# One-off latest npm release
npx kandev@latest
# Global npm install
npm install -g kandev@latest
kandev
```
Kandev starts its backend, serves the web UI, and opens it in your browser. By default, persistent data lives under `~/.kandev`; the exact paths and startup options are in the [CLI reference](cli.md).
The [desktop app](desktop-app.md) is another local entry point. For an always-on or remote installation, see [Run as a service](run-as-a-service.md), [Docker](docker.md), or [Remote environments](remote-cloud-environment.md).
## Complete the initial setup
1. Open **Settings > Workspaces** and create or select a workspace. A workspace owns repositories, workflows, integrations, labels, and task history.
2. Under the workspace, add a repository by local path or remote URL. Confirm the default branch and authentication before starting work.
3. Open **Settings > Agents**. Select an installed agent and create or inspect a profile. Choose its model, mode, CLI flags, environment variables, passthrough behavior, and permission policy deliberately.
4. Open **Settings > Executors**. For the first run, use a worktree profile when you want branch isolation or a local profile when you explicitly want the agent to work in the selected checkout.
5. Keep the built-in **Kanban** workflow for the first task. Use [Workflow tips](workflow-tips.md) after the basic loop is familiar.
## Run a first task
1. Select **New task** from the board or command panel.
2. Give the task a concrete outcome and enough acceptance criteria to review it.
3. Select the repository and base branch. Kandev creates or uses the execution workspace required by the selected executor.
4. Select a workflow, agent profile, executor, and executor profile. The dialog remembers compatible recent choices, but review them when changing repositories or trust boundaries.
5. Create and start the task. Workflow events can move it to the running step and launch the agent automatically.
6. Follow the session in the integrated workbench. Inspect chat, terminal commands, files, and the live Changes panel rather than relying only on the final message.
7. Review the diff. Add line, plan, pull-request, or walkthrough feedback to the next prompt when changes are needed.
8. Run the repository's tests, create or inspect commits, and open the pull request from the task when the result is ready.
9. Move the task through its review gate and archive it only after the branch and pull request state are understood.
## Choose the right workflow
- **Kanban** is the shortest run-review loop.
- **Plan & Build** pauses after a structured plan so a human can edit or approve the approach before implementation.
- **Feature Dev** separates planning, implementation, review, QA, PR creation, and CI repair into focused steps.
- **PR Review** gives an existing branch or pull request a dedicated review pass.
- **Architecture** produces a design without implying that implementation is complete.
Workflow steps can select different agent profiles and prompts. See [Tasks and workflows](tasks-and-workflows.md) for the operating model and [Workflow import/export](workflow-import-export.md) for portable definitions.
## Credentials and trust
Kandev does not make an agent safer than the permissions of its process. An agent can use the files, network, credentials, environment variables, MCP tools, and approval policy exposed by its selected profiles and executor.
- Prefer scoped tokens and secret references over plaintext environment values.
- Treat **Auto approve** and permission-skipping CLI flags as trust-boundary changes, not convenience toggles.
- A local executor inherits more of the host environment than an isolated container or remote sandbox.
- A worktree isolates Git changes from other Kandev tasks, but it is not an operating-system security boundary.
- Review prepare and cleanup scripts before sharing an executor profile with a team.
See [Agents and profiles](agents-and-profiles.md), [Executors](executors.md), and [Configuration](configuration.md) before operating Kandev on shared infrastructure.
## If the first task does not start
Check these in order:
1. **Settings > System > Status** for backend, database, filesystem, and runtime health.
2. The agent profile's install/login status and model selection.
3. Repository access by running `git fetch` with the same user or remote credentials.
4. Executor-profile prerequisites such as Docker, SSH connectivity, a Sprites token, image availability, or prepare-script success.
5. The session and system logs under **Settings > System > Logs**.
6. Disk usage under system settings; worktrees, repositories, sessions, and backups all consume the Kandev data directory.
The [operations guide](operations.md) covers backups, updates, logs, resource metrics, and recovery in more detail.
+90
View File
@@ -0,0 +1,90 @@
---
title: "Web Development"
description: "Develop Kandev's Vite and React web client, state, routes, settings, workbench surfaces, and responsive UI."
---
# Web Development
The web application lives in `apps/web/`. It is a Vite-built React 19 single-page application served by the Go backend in production.
## Run the web client
```bash
make dev
```
Use the combined command for normal feature work so API and WebSocket behavior are present. To isolate the client:
```bash
make dev-web
```
The development command chooses available ports and prints the URLs. Do not hardcode a port in tests or documentation unless the relevant command guarantees it.
## Code layout
- `apps/web/app/` contains route/page-level features.
- `apps/web/components/` contains reusable and feature components.
- `apps/web/lib/api/` contains HTTP clients organized by backend domain.
- `apps/web/lib/state/` contains Zustand state and slices.
- `apps/web/lib/routing/` contains client routing and bootstrap helpers.
- `apps/web/e2e/` contains Playwright fixtures, seed helpers, page objects, and specs.
- `apps/web/src/` contains the application entry, shell, and route dispatch.
Follow an existing nearby feature from API client through state to UI before introducing a new data-fetching or routing pattern.
## Backend state is authoritative
Use typed domain clients for mutations and reconcile the result into state. WebSocket events keep connected screens current, but the client must tolerate reconnects, duplicates, and events arriving while a route is changing.
Do not duplicate workflow transition, executor lifecycle, provider permission, or Git rules in the component layer. The UI can explain why an action is unavailable; the backend must enforce it.
## Settings routes
Settings pages are assembled through `apps/web/src/settings-routes.tsx` and page/components under `apps/web/app/settings/` and `apps/web/components/settings/`. Workspace integrations and automations require an active workspace and should preserve that scope in links and API requests.
When adding a setting, cover initial bootstrap, loading, empty, error, saved, and permission/dependency states. Make restart requirements or experimental status visible.
## Workbench UI
Task detail combines chat, documents, file editor, terminal, changes, preview, and pull-request context. These surfaces share task/session/repository selection, so test a new action with:
- no-repository tasks;
- multi-repository tasks;
- preparing, running, stopped, failed, and completed sessions;
- desktop and mobile navigation;
- delayed WebSocket or API responses.
Keep controls compact and state-aware. Kandev's product principles in `PRODUCT.md` require orientation before controls, density without clutter, familiar developer affordances, keyboard access, visible focus, and reduced-motion support.
## Accessibility and responsive behavior
- Use semantic buttons, links, labels, tabs, dialogs, and headings.
- Keep icon-only controls named for assistive technology and tooltips.
- Preserve visible focus and complete keyboard interaction.
- Do not encode status only with color.
- Respect reduced motion.
- Verify narrow mobile viewports without horizontal overflow or desktop-only assumptions.
## Tests
```bash
make test-web
make typecheck-web
make lint-web
make test-e2e
```
Component/unit tests use Vitest. Any change under `apps/web/` must add or update a Playwright E2E scenario. Use established E2E seeding APIs and isolated test data rather than an operator's local database.
## Review checklist
- Uses the existing domain API and state path.
- Covers loading, empty, error, and stale/reconnect behavior.
- Works for every relevant task/session/repository state.
- Keyboard and screen-reader names are correct.
- Desktop and mobile layouts are manually verified.
- Unit tests and a truthful E2E scenario cover the behavior.
- Public docs and screenshots use current terminology and UI.
Related: [Architecture](architecture.md), [Testing](testing.md), and [Developer tools](developer-tools.md).
+6 -1
View File
@@ -1,4 +1,9 @@
# Workflow Sync — Manage Workflows from a GitHub Repo
---
title: "Workflow Sync"
description: "Keep workspace workflows synchronized with reviewed definitions in a GitHub repository."
---
# Workflow Sync - Manage Workflows from a GitHub Repo
Kandev can keep a workspace's workflows in sync with definition files stored
in a GitHub repository. Point a workspace at a repo directory, commit workflow
+283 -1
View File
@@ -22,9 +22,11 @@ export async function validatePublicDocs(
const pagesBySlug = new Map();
for (const file of files) {
const markdown = await fs.readFile(path.join(docsDir, file), "utf8");
await assertLocalLinks(docsDir, file, markdown);
if (path.posix.basename(file).toLowerCase() === "readme.md") continue;
const markdown = await fs.readFile(path.join(docsDir, file), "utf8");
assertFrontmatter(file, markdown);
const slug = file.replace(/\.mdx?$/, "").replace(/\/index$/, "");
@@ -126,6 +128,286 @@ function assertFrontmatter(file, markdown) {
}
}
/**
* Require every relative Markdown link or image to resolve on disk.
*
* @param {string} docsDir Published docs root.
* @param {string} file Relative source path used in validation errors.
* @param {string} markdown Page source.
* @returns {Promise<void>}
*/
async function assertLocalLinks(docsDir, file, markdown) {
const source = stripMarkdownCode(markdown);
const definitionPattern = /^\s{0,3}\[([^\]\n]+)\]:\s*(\S.*)$/gm;
const referencePattern = /!?\[([^\]\n]+)\]\[([^\]\n]*)\]/g;
const shortcutReferencePattern = /(?<![!\\\[\]])\[([^\]\n]+)\](?![\[(:])/g;
const destinations = collectInlineLinkDestinations(source);
const definitions = new Map();
for (const match of source.matchAll(definitionPattern)) {
if (match[1].startsWith("^")) continue;
const label = normalizeReferenceLabel(match[1]);
definitions.set(label, match[2]);
destinations.push(match[2]);
}
for (const match of source.matchAll(referencePattern)) {
const label = normalizeReferenceLabel(match[2] || match[1]);
if (!definitions.has(label)) {
throw new Error(`${file} uses undefined Markdown reference: ${label}`);
}
}
for (const match of source.matchAll(shortcutReferencePattern)) {
const label = normalizeReferenceLabel(match[1]);
// Admonitions, footnotes, and task boxes use brackets but are not links.
if (
!label ||
label.startsWith("!") ||
label.startsWith("^") ||
/^(?:x|-)$/i.test(label)
) {
continue;
}
if (!definitions.has(label)) {
throw new Error(`${file} uses undefined Markdown reference: ${label}`);
}
}
for (const destination of destinations) {
const href = parseMarkdownDestination(destination);
if (!href || href.startsWith("#") || isExternalDestination(href)) {
continue;
}
if (href.startsWith("/")) {
throw new Error(
`${file} uses a site-root link instead of a relative source link: ${href}`,
);
}
const pathOnly = href.split(/[?#]/, 1)[0];
if (!pathOnly) continue;
let decoded;
try {
decoded = decodeURIComponent(pathOnly);
} catch {
throw new Error(`${file} contains an invalid encoded local link: ${href}`);
}
const target = path.resolve(
path.dirname(path.join(docsDir, file)),
decoded.replace(/\\([\\() ])/g, "$1"),
);
try {
await fs.access(target);
} catch {
throw new Error(`${file} links to missing local target: ${href}`);
}
}
}
/**
* Collect inline Markdown destinations while preserving balanced parentheses.
*
* @param {string} markdown Markdown with code regions removed.
* @returns {string[]} Raw content inside each link's parentheses.
*/
function collectInlineLinkDestinations(markdown) {
const destinations = [];
for (let start = 0; start < markdown.length; start += 1) {
if (markdown[start] !== "[" || isEscaped(markdown, start)) continue;
let bracketDepth = 1;
let labelEnd = -1;
for (let cursor = start + 1; cursor < markdown.length; cursor += 1) {
const character = markdown[cursor];
if (character === "\n" || character === "\r") break;
if (character === "\\") {
cursor += 1;
} else if (character === "[") {
bracketDepth += 1;
} else if (character === "]") {
bracketDepth -= 1;
if (bracketDepth === 0) {
labelEnd = cursor;
break;
}
}
}
if (labelEnd === -1 || markdown[labelEnd + 1] !== "(") continue;
let parenthesisDepth = 1;
for (let cursor = labelEnd + 2; cursor < markdown.length; cursor += 1) {
const character = markdown[cursor];
if (character === "\n" || character === "\r") break;
if (character === "\\") {
cursor += 1;
} else if (character === "(") {
parenthesisDepth += 1;
} else if (character === ")") {
parenthesisDepth -= 1;
if (parenthesisDepth === 0) {
destinations.push(markdown.slice(labelEnd + 2, cursor));
break;
}
}
}
}
return destinations;
}
/**
* Return whether punctuation is preceded by an odd number of backslashes.
*
* @param {string} value Source text.
* @param {number} index Character index.
* @returns {boolean} Whether the character is escaped.
*/
function isEscaped(value, index) {
let backslashes = 0;
for (let cursor = index - 1; cursor >= 0 && value[cursor] === "\\"; cursor -= 1) {
backslashes += 1;
}
return backslashes % 2 === 1;
}
/**
* Remove fenced, indented, and inline code so examples are not treated as
* live links.
*
* @param {string} markdown Page source.
* @returns {string} Markdown with code regions removed.
*/
function stripMarkdownCode(markdown) {
let fence = null;
let indentedCodeIndent = null;
let canStartIndentedCode = true;
const listContentIndents = [];
const lines = markdown.split(/\r?\n/).map((line) => {
const marker = line.match(/^\s*(`{3,}|~{3,})/)?.[1];
if (marker) {
if (!fence) {
fence = marker;
} else if (marker[0] === fence[0] && marker.length >= fence.length) {
fence = null;
}
canStartIndentedCode = true;
return "";
}
if (fence) return "";
const blank = /^\s*$/.test(line);
const indent = leadingIndentWidth(line);
if (indentedCodeIndent !== null) {
if (blank || indent >= indentedCodeIndent) {
canStartIndentedCode = blank;
return "";
}
indentedCodeIndent = null;
}
if (blank) {
canStartIndentedCode = true;
return line;
}
while (
listContentIndents.length > 0 &&
indent < listContentIndents.at(-1)
) {
listContentIndents.pop();
}
const requiredCodeIndent = (listContentIndents.at(-1) ?? 0) + 4;
if (canStartIndentedCode && indent >= requiredCodeIndent) {
indentedCodeIndent = requiredCodeIndent;
canStartIndentedCode = false;
return "";
}
const listMarker = line.match(
/^([ \t]*)(?:[-+*]|\d{1,9}[.)])([ \t]+)/,
);
if (listMarker) {
listContentIndents.push(columnWidth(listMarker[0]));
}
canStartIndentedCode = /^(?: {0,3}#{1,6}(?:[ \t]+|$)| {0,3}(?:=+|-+)[ \t]*$| {0,3}\[[^\]\n]+\]:)/.test(
line,
);
return line;
});
return lines.join("\n").replace(/`+[^`\n]*`+/g, "");
}
/**
* Count indentation columns, expanding tabs to four-column stops.
*
* @param {string} value Source line or prefix.
* @returns {number} Leading indentation width in columns.
*/
function leadingIndentWidth(value) {
return columnWidth(value.match(/^[ \t]*/)[0]);
}
/**
* Count source columns, expanding tabs to four-column stops.
*
* @param {string} value Source text.
* @returns {number} Width in columns.
*/
function columnWidth(value) {
let width = 0;
for (const character of value) {
if (character === "\t") {
width += 4 - (width % 4);
} else {
width += 1;
}
}
return width;
}
/**
* Apply CommonMark's case-insensitive, whitespace-collapsing reference label rules.
*
* @param {string} label Raw reference label.
* @returns {string} Normalized reference label.
*/
function normalizeReferenceLabel(label) {
return label.trim().replace(/\s+/g, " ").toLowerCase();
}
/**
* Read the destination portion before an optional Markdown link title.
*
* @param {string} raw Raw content inside link parentheses.
* @returns {string} Link destination.
*/
function parseMarkdownDestination(raw) {
const value = raw.trim();
if (value.startsWith("<")) {
const end = value.indexOf(">");
return end === -1 ? value : value.slice(1, end);
}
return value.split(/\s+/, 1)[0];
}
/**
* Return whether a destination has a URL scheme or protocol-relative host.
*
* @param {string} href Link destination.
* @returns {boolean} Whether the destination is external.
*/
function isExternalDestination(href) {
return href.startsWith("//") || /^[a-z][a-z\d+.-]*:/i.test(href);
}
/**
* Return whether a metadata entry is a navigation heading.
*
+296
View File
@@ -145,3 +145,299 @@ test("rejects published pages without title and description frontmatter", async
/index.md must start with YAML frontmatter containing title and description/,
);
});
test("accepts existing relative page and asset links", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
"[Guide](guide.md)\n\n![Diagram](assets/diagram.png)",
),
"guide.md": validPage,
"assets/diagram.png": "not-a-real-png",
},
{ pages: ["index", "guide"] },
);
await assert.doesNotReject(validatePublicDocs(dir));
});
test("rejects a broken local page link", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace("Page body.", "[Missing](missing.md)"),
},
{ pages: ["index"] },
);
await assert.rejects(
validatePublicDocs(dir),
/index.md links to missing local target: missing.md/,
);
});
test("rejects a broken local image", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
"![Missing](assets/missing.png)",
),
},
{ pages: ["index"] },
);
await assert.rejects(
validatePublicDocs(dir),
/index.md links to missing local target: assets\/missing.png/,
);
});
test("rejects a broken local image nested inside a link", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
"[![Missing](assets/missing.png)](guide.md)",
),
"guide.md": validPage,
},
{ pages: ["index", "guide"] },
);
await assert.rejects(
validatePublicDocs(dir),
/index.md links to missing local target: assets\/missing.png/,
);
});
test("ignores external, anchor-only, and fenced-code links", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
`[External](https://example.com/docs)\n\n[Section](#section)\n\n\`\`\`md
[Example only](does-not-exist.md)
\`\`\``,
),
},
{ pages: ["index"] },
);
await assert.doesNotReject(validatePublicDocs(dir));
});
test("ignores links inside inline code and nested shorter fences", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
`Use \`[example](inline-missing.md)\` in prose.
\`\`\`\`md
\`\`\`md
[Example only](fenced-missing.md)
\`\`\`
\`\`\`\``,
),
},
{ pages: ["index"] },
);
await assert.doesNotReject(validatePublicDocs(dir));
});
test("ignores links inside indented code blocks", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
`Example only:
[Missing](indented-missing.md)`,
),
},
{ pages: ["index"] },
);
await assert.doesNotReject(validatePublicDocs(dir));
});
test("ignores indented code blocks after a heading", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
`## Example
[Missing](heading-code-missing.md)`,
),
},
{ pages: ["index"] },
);
await assert.doesNotReject(validatePublicDocs(dir));
});
test("ignores indented code blocks nested in list items", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
`- Example only:
[Missing](list-code-missing.md)`,
),
},
{ pages: ["index"] },
);
await assert.doesNotReject(validatePublicDocs(dir));
});
test("validates links in indented list paragraphs", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
`- Related material:
[Missing](list-paragraph-missing.md)`,
),
},
{ pages: ["index"] },
);
await assert.rejects(
validatePublicDocs(dir),
/index.md links to missing local target: list-paragraph-missing.md/,
);
});
test("accepts escaped parentheses in local link destinations", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace("Page body.", "[Guide](guide\\(1\\).md)"),
"guide(1).md": validPage,
},
{ pages: ["index", "guide(1)"] },
);
await assert.doesNotReject(validatePublicDocs(dir));
});
test("accepts balanced parentheses in local link destinations", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace("Page body.", "[Guide](guide(1).md)"),
"guide(1).md": validPage,
},
{ pages: ["index", "guide(1)"] },
);
await assert.doesNotReject(validatePublicDocs(dir));
});
test("validates reference-style link definitions", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
"[Guide][user guide]\n\n[user guide]: missing.md",
),
},
{ pages: ["index"] },
);
await assert.rejects(
validatePublicDocs(dir),
/index.md links to missing local target: missing.md/,
);
});
test("rejects undefined full reference-style links", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace("Page body.", "[Guide][missing guide]"),
},
{ pages: ["index"] },
);
await assert.rejects(
validatePublicDocs(dir),
/index.md uses undefined Markdown reference: missing guide/,
);
});
test("validates collapsed reference-style links", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
"[Guide][]\n\n[guide]: missing.md",
),
},
{ pages: ["index"] },
);
await assert.rejects(
validatePublicDocs(dir),
/index.md links to missing local target: missing.md/,
);
});
test("rejects undefined shortcut reference-style links", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace("Page body.", "Read the [Guide]."),
},
{ pages: ["index"] },
);
await assert.rejects(
validatePublicDocs(dir),
/index.md uses undefined Markdown reference: guide/,
);
});
test("ignores non-reference bracket syntax", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace(
"Page body.",
"> [!WARNING]\n\n- [x] Done\n\n[^note]\n\n\\[Literal]",
),
},
{ pages: ["index"] },
);
await assert.doesNotReject(validatePublicDocs(dir));
});
test("checks local links in README files", async () => {
const dir = await createDocs(
{
"README.md": "# Contributing\n\n[Missing](missing.md)",
"index.md": validPage,
},
{ pages: ["index"] },
);
await assert.rejects(
validatePublicDocs(dir),
/README.md links to missing local target: missing.md/,
);
});
test("rejects site-root links because public docs use relative sources", async () => {
const dir = await createDocs(
{
"index.md": validPage.replace("Page body.", "[Guide](/docs/guide)"),
},
{ pages: ["index"] },
);
await assert.rejects(
validatePublicDocs(dir),
/index.md uses a site-root link instead of a relative source link: \/docs\/guide/,
);
});