快乐 (kuàilè) · happiness, joy
The issue tracker with no paid tier.
Keyboard-driven, self-hosted, and available in one public Apache 2.0 repository. v0.1.0
Kuayle v0.1.0 is a runnable MVP, not a mature enterprise platform. The repository includes the Go API, SvelteKit frontend, database migrations, development tooling, and reference self-hosting configuration.
| Area | State |
|---|---|
| Core tracker | Available: auth, workspaces, RBAC, teams, custom statuses, issues, multiple assignees, labels, comments, history, sub-issues, relations, triage, templates, favorites, saved views, notifications, public sharing, uploads, and WebSocket events. |
| Planning | Implemented: cycles with burndown/velocity charts, project management with Gantt view, and full cycle/project UI. |
| Integrations | Available: workspace webhooks and a GitHub App with repository linking, branch/commit/PR activity, configurable status transitions, and WebSocket refresh events. Private networks require a webhook relay or tunnel. |
| Analytics | Workspace and team overviews, burn-up trends, and configurable issue insights backed by durable lifecycle events. |
| Dev Machines | Specification/design only in this repo today. The runtime container manager and UI flow are not wired into the app yet; see TECHNICAL.md. |
| Self-hosting | Reference Docker Compose stack with Caddy, PostgreSQL, Redis, backend, frontend, an update script, and dedicated config in selfhosting/. |
Kuayle started with a narrow requirement: keep a fast, keyboard-oriented issue workflow while adding multiple assignees, self-hosting, and complete source access.
The distribution model is deliberately simple:
- one public repository under Apache 2.0;
- no paid tier or enterprise edition;
- no feature gate or license key;
- no per-user software fee;
- infrastructure, backups, monitoring, and updates remain the operator's responsibility.
The product is intentionally smaller than broad project-management suites. It covers issues, cycles, projects, saved views, analytics, GitHub automation, public sharing, and real-time events. It does not currently include import/export workflows, enterprise identity, a wiki, or modules.
| Feature | Description | |
|---|---|---|
| 🏢 | Workspaces | Multi-tenant with role-based access (owner, admin, member, guest) |
| 👥 | Teams | Custom workflows, each team gets its own statuses and triage settings |
| 📋 | Issues | Priority, due dates, sub-issues, multi-assignee, labels, comments, audit history |
| 🔗 | Issue Relations | Blocking/blocked, duplicate, and related issue links |
| 🔄 | Cycles | Sprint planning with burndown/velocity charts and time-boxed iterations |
| 📁 | Projects | Cross-team work grouped under a single umbrella with Gantt view |
| 🏷️ | Labels | Hierarchical, workspace-scoped, with soft delete and default labels on creation |
| 👁️ | Views | Saved views with personal/workspace/team scoping, drag-and-drop reorder |
| 🔔 | Notifications | Inbox with snooze, read status, and archive |
| 🔗 | Webhooks | Plug into external services and integrations |
| ⚡ | Real-time | Workspace WebSocket events for issues, comments, cycles, views, GitHub, and presence |
| 🖥️ | Dev Machines | Technical specification for on-demand, single-container development environments |
| 🐙 | GitHub | Link repos, match issue IDs in development activity, and apply status rules |
| 📊 | Analytics | Workspace/team overview, burn-up, and configurable insights |
| 🔗 | Public Sharing | Token-based read-only links for issues and views |
| 📦 | Asset Management | File uploads, signed URLs for prompt images, S3-compatible storage |
| ⌨️ | Command Palette | Global search with highlighting, keyboard shortcuts, and quick actions |
| 🎨 | Rich Text Editor | Tiptap-based with code blocks, slash commands, mentions, task lists |
| 🚀 | Release Changelog | Multi-release changelog modal with markdown rendering from static manifest |
The Dev Machines track is currently a technical specification for on-demand, single-container development environments on a VPS. The intended design is a disposable workspace with an IDE, agentic coding CLI, and a browser, accessible via auto-generated subdomains.
See
TECHNICAL.mdfor the full specification, architecture diagrams, and API reference.
You (browser)
│
├─ f8k2m9.kuayle.com → code-server (IDE + Claude Code)
├─ f8k2m9-browser.kuayle.com → Chromium (in-browser web navigation)
└─ f8k2m9-app.kuayle.com → Dev server preview
│
└── All routed through Kuayle auth — no port management needed
The proposed design would:
- Spawn a container with code-server, Claude Code CLI, Chromium, and the repository
- Assign random subdomains through wildcard DNS (
*.kuayle.com), without per-container port management - Authenticate users and agents through Kuayle's session layer
- Record activity from the development environment and attach it to project work
| Mode | Who | What happens |
|---|---|---|
| Agent-only | Kuayle assigns a task | Agent works autonomously, pushes results, machine tears down |
| Human + Agent | Developer clicks "Open Machine" | Gets a browser link to a full IDE with agentic tools, works interactively |
Machines would be configured from Kuayle's UI or via API: repo, branch, env vars, tools, and size. Configuration would resolve in order: project defaults → user preferences → spawn-time overrides.
| Size | CPU | Memory | Disk |
|---|---|---|---|
| Small | 2 cores | 4 GB | 20 GB |
| Medium | 4 cores | 8 GB | 50 GB |
| Large | 8 cores | 16 GB | 100 GB |
Here's what Kuayle runs on and what each piece does:
| Layer | Tech | Role |
|---|---|---|
| API | Go + Echo | High-performance HTTP server with middleware, routing, JWT auth |
| Database | PostgreSQL 17 | Primary data store, raw SQL via sqlx/pgx, no ORM |
| Redis | Redis 7 | Required configuration; reserved for future cache and job use |
| Frontend | SvelteKit + Svelte 5 | SPA with TypeScript, runes-based reactivity, static adapter |
| UI | Tailwind CSS + shadcn-svelte | Utility-first styling with accessible component primitives |
| Editor | Tiptap v3 + Yjs | Rich text with code blocks, mentions, slash commands, task lists |
| Real-time | WebSocket (nhooyr.io) | Workspace events, issue presence, and targeted notifications |
| Storage | Local FS or S3-compatible | AWS S3, Cloudflare R2, MinIO, SeaweedFS |
| Reverse Proxy | Caddy | Production HTTPS and routing |
| Dev Machines | code-server + Claude Code + Chromium | Technical specification for single-container agentic dev environments |
| Infra | Docker + Docker Compose | Local development and reference self-hosting stack |
cp .env.example .env
make docker-upApp at http://localhost:5173 · API at http://localhost:8080
cp .env.example .env
docker compose up postgres redis -d
make migrate-up && make seed
make dev| Command | What it does |
|---|---|
make dev |
Run backend + frontend (with migrate) |
make dev-backend |
Backend only |
make dev-frontend |
Frontend only |
make dev-full |
Backend + frontend + smee proxy |
make dev-smee |
Start webhook proxy (smee.io) |
make migrate-up |
Apply migrations |
make migrate-down |
Roll back migrations |
make seed |
Seed the database |
make reset-dev |
Reset dev database |
make test |
Run all tests |
make test-backend |
Backend tests only |
make test-frontend |
Frontend tests only |
make lint |
Lint everything |
make docker-up |
Start all (Docker) |
make docker-down |
Stop all (Docker) |
make scan |
Security scan backend + frontend |
Kuayle is designed to be self-hosted. The reference stack in selfhosting/ includes Caddy, PostgreSQL, Redis, the backend, the frontend, and an update script. Review secrets, backups, monitoring, and host security before production use.
- A Linux server with Docker + Docker Compose
- A domain pointing to your server (for HTTPS)
git clone https://github.com/carbogninalberto/kuayle.git
cd kuayle/selfhosting
cp .env.example .envEdit .env with your domain and production values:
DOMAIN=kuayle.yourcompany.com
POSTGRES_PASSWORD=<strong-random-password>
JWT_SECRET=<random-string-at-least-32-chars>docker compose up --build -dThis starts 5 containers: Caddy (auto TLS), PostgreSQL, Redis, backend API, and frontend.
docker compose exec backend /app/server migrate up
docker compose exec backend /app/server seedThe frontend serves the app and proxies /api/* to the backend, so one public origin is enough.
cd kuayle
bash selfhosting/update.shThe update script pulls the latest code, rebuilds images, recreates containers, and applies pending migrations.
Instance sysadmins can also enable one-click updates from Settings → Version:
- Copy your user ID from Settings → Profile.
- Add it to
SYSADMINSinselfhosting/.env. - Set a strong
SYSTEM_UPDATER_TOKENand keepSYSTEM_UPDATER_URL=http://updater:8081. - Apply the env and start the internal updater sidecar with
docker compose --profile updater up -d backend updaterfromselfhosting/.
The updater sidecar is internal-only and runs the same selfhosting/update.sh flow. If it is not configured, the Version page shows the manual update command instead.
By default, uploads use a local Docker volume. The alternative S3 backend accepts a configurable endpoint and path-style requests:
STORAGE_TYPE=s3
S3_ENDPOINT=https://s3.us-east-1.amazonaws.com
S3_BUCKET=kuayle-uploads
S3_REGION=us-east-1
S3_ACCESS_KEY=your-key
S3_SECRET_KEY=your-secretThe backend is intended for AWS S3 and compatible APIs such as R2, MinIO, and SeaweedFS. Test bucket creation, permissions, public URL behavior, and signed downloads with your chosen provider.
Kuayle connects to GitHub through a GitHub App. By default, each workspace uses GitHub's App Manifest flow and stores the returned credentials encrypted. Deployments with shared App credentials can let workspaces install a preconfigured App instead (see .env.example for the GITHUB_APP_* variables).
- Links development activity — mention
ENG-123in a branch name, PR title/body, or commit message (case-insensitive) - Auto-transitions — branch created → In Progress, PR opened → In Review, PR merged → Done (configurable)
- Activity feed — linked PRs, branches, and commits on the matching issue detail page
If GitHub can reach your Kuayle instance (for example https://kuayle.yourcompany.com), the manifest flow can populate the callback and webhook URLs:
- Go to Settings → GitHub in your workspace
- Click Set up GitHub App — redirects to GitHub with a pre-filled form
- Click Create GitHub App on GitHub
- Redirected back — credentials saved automatically, webhook URL configured
- Click Install on GitHub to grant access to your repos
- Select which repositories to link
GitHub events appear after the App is installed on repositories, webhook delivery succeeds, and an issue identifier is present in supported activity.
If your instance runs on a private network (for example behind a VPN), GitHub cannot send webhooks directly. Use a relay or expose only the webhook endpoint through a controlled tunnel.
Option A: Webhook proxy with smee.io
smee.io is a free webhook relay that forwards GitHub events to your private instance.
- Go to smee.io/new and copy your channel URL (e.g.
https://smee.io/abc123) - Run the proxy on your server:
npx smee-client --url https://smee.io/abc123 --target http://localhost:8080/api/github/webhook
- Set up the GitHub App from Settings → GitHub (same steps as above)
- After the app is created, go to its settings on GitHub: GitHub → Settings → Developer settings → GitHub Apps → your app → General
- Set Webhook URL to your smee channel URL (
https://smee.io/abc123) - Check Active and save
The smee client must stay running to receive events. You can run it as a systemd service:
# /etc/systemd/system/smee-kuayle.service
[Unit]
Description=Smee webhook proxy for Kuayle
After=network.target
[Service]
ExecStart=/usr/bin/npx smee-client --url https://smee.io/abc123 --target http://localhost:8080/api/github/webhook
Restart=always
User=kuayle
[Install]
WantedBy=multi-user.targetsudo systemctl enable --now smee-kuayleOption B: Reverse tunnel
Use a reverse tunnel to expose just the webhook endpoint. With cloudflared:
cloudflared tunnel --url http://localhost:8080Or with ngrok:
ngrok http 8080Then set the generated public URL as the webhook URL in your GitHub App settings (append /api/github/webhook).
For local development, the GitHub App is created without a webhook URL (since localhost isn't reachable). To receive webhook events during development:
- Set up the GitHub App from Settings → GitHub (works on localhost)
- Start a smee proxy:
npx smee-client --url https://smee.io/your-channel --target http://localhost:8080/api/github/webhook
- Update the webhook URL in your GitHub App settings to your smee channel URL
- Events will now flow through to your local instance
kuayle/
├── BE/ # Backend (Go)
│ ├── cmd/server/ # Entrypoint (server, migrate, seed)
│ └── internal/
│ ├── config/ # Configuration
│ ├── domain/ # Domain models
│ ├── dto/ # Data transfer objects
│ ├── handler/ # HTTP handlers
│ ├── service/ # Business logic
│ ├── repository/ # Data access (raw SQL)
│ ├── middleware/ # Auth and request middleware
│ └── realtime/ # WebSocket support
├── UI/ # Frontend (SvelteKit)
│ └── src/
│ ├── routes/ # Pages
│ └── lib/
│ ├── api/ # API client
│ ├── components/ # UI components
│ ├── features/ # Feature modules
│ ├── types/ # TypeScript types
│ └── utils/ # Utilities
├── WEB/ # Public marketing site (SvelteKit, statically generated)
├── selfhosting/ # Production Docker Compose + Caddy config
│ ├── docker-compose.yml
│ ├── Caddyfile
│ ├── update.sh
│ └── .env.example
├── scripts/ # Dev and maintenance scripts
├── docker-compose.yml # Dev Docker Compose
├── Makefile
├── TECHNICAL.md # Dev Machines specification
└── .env.example
Pull requests are welcome. Keep changes focused, explain the behavior being changed, and include relevant validation.
- Fork the repo
- Create your branch (
git checkout -b feature/cool-thing) - Commit your changes
- Push and open a PR
Apache 2.0, see LICENSE.
Alberto Carbognin, @carbogninalberto
View the full contributor graph on GitHub: contributors.
Project note: Kuayle has been developed with AI-assisted tooling under human direction and review. Version 0.1.0 is an MVP; evaluate and test it against your requirements before production use.
