Nekode is a self-hosted, Slock-style collaboration server and daemon runtime. It is a new implementation that reuses the daemon protocol work captured from Slock behavior, while keeping the codebase independent from Nekobot.
- Go backend entrypoint:
cmd/nekode - Go daemon entrypoint:
cmd/nekode-daemon - HTTP health endpoint:
GET /health - Protocol metadata endpoint:
GET /api/protocol - Phase 2 API docs:
docs/api.md - Reusable daemon IDL:
proto/nekode/daemon/v1/*.proto - Protocol capability review:
docs/protocol-capability-review.md - Implementation design:
docs/slock-style-daemon-runtime.md - IM channel integration and deployment notes:
docs/im-channel-integration.md - Web console assets:
web/src/assets-brand.pngandweb/public/* - Container and binary build:
Dockerfile,docker-compose.yml, andbuild.sh - Local references for future design comparison:
/home/czyt/code/go/references/open-agent-roomand/home/czyt/code/go/references/zano
Nekode's IM endpoint and channel-adapter work references
CherryHQ/stella, an MIT-licensed
self-hosted assistant with Telegram, QQ, Feishu, WeChat, and Terminal channel
runtimes.
The intended reuse is Stella's proven channel shape: platform-specific adapters
normalize inbound events, a shared coordinator handles identity/routing/session
behavior, and platform renderers handle streaming/output details. Nekode keeps
the implementation on its existing primitives: InteractionEndpoint,
storage.Message, SourceEndpointID, ExternalMessageID, message attachment
IDs, metadata JSON, and the existing attachment/message/notification storage
paths. Platform adapters and channel-add/binding UI for Telegram, QQ, Feishu,
WeChat, and Terminal may reuse Stella's channel configuration, validation,
onboarding, and runtime structure where compatible, with source attribution
retained in documentation.
The integration model is endpoint-centric rather than a separate IM chat system:
- Each IM channel instance is an
InteractionEndpoint, for examplekind=imwithprovider=feishu,weixin,telegram, orqq. - Platform adapters verify inbound events, deduplicate by platform message id, normalize sender/conversation/content into Nekode's inbound IM DTO, and use the existing attachment path for media.
- Message coordination maps endpoint identity and external conversations onto existing Nekode targets, threads, sessions, users, agents, and commands. IM adapters must not call daemon runtimes directly.
- Inbound messages persist as existing
storage.Messagerecords withSourceEndpointID,ExternalMessageID, attachment IDs, and metadata JSON so Web, daemon, tasks, runs, search, saved messages, and activity all see the same collaboration facts. - Outbound delivery renders existing Nekode messages, activities, and notifications back to bound IM endpoints through delivery records and retry state; platform adapters only translate the delivery into provider API calls.
- Group behavior starts conservative (
mentionby default, withalwaysanddisabledavailable) and can later add per-group agent, system prompt, and tool policy overrides.
go run ./cmd/nekode serve --addr :18790 --grpc-addr 127.0.0.1:18789
curl http://localhost:18790/healthRun the minimal daemon client against a local server:
go run ./cmd/nekode-daemon run --config ~/.nekode/daemon.json --onceDaemon enrollment is token based. Use the authenticated HTTP API to create an
enrollment; the server returns a generated install token and a short-lived
one-line install command. The copied URL contains only a one-time install code,
not the daemon token. When the script endpoint is fetched, the server rotates
the daemon token, writes only its hash, and embeds the new token in the script
body. The daemon sends that token to gRPC as authorization: Bearer <token>
metadata. The token is not a manually configured global server secret.
The daemon config is generated by the install/enrollment flow and contains the
server-issued install token. For local smoke tests, --token or
NEKODE_DAEMON_TOKEN can override the config value.
The daemon onboarding flow is:
- Create a Computer enrollment in Web; the server generates a device token and install command.
- Run the install command on the target machine. Web shows platform-specific
entries. Linux/macOS use a Teleport-style one-liner such as
sudo bash -c "$(curl -fsSL <server>/api/daemon/enrollments/<id>/install.sh?code=<code>)". Windows usesinstall.ps1. The script body contains the device token, server addresses, computer identity, and GitHub Releases daemon download source; the copied command URL does not expose the daemon token. Script responses areno-store, and install codes are one-time/short-lived. nekode-daemonstarts, reads the generated config, sends the token as gRPC bearer metadata, and registers/heartbeats automatically.- Web polls the enrollment/Computer state until the daemon connects, then allows the operator to continue.
Agent creation is separate from daemon installation. Web should use the connected Computer inventory to choose a runtime/capability and create one or more agent instances; a runtime kind is not unique and may back multiple agents.
Release builds publish nekode_${version}_${os}_${arch} and
nekode-daemon_${version}_${os}_${arch} artifacts for Linux, macOS, and
Windows. The default Docker image runs only the server; daemon installation
should download the platform-specific daemon artifact from GitHub Releases
instead of pulling it from the server runtime image. Private deployments can add
a download-source override without changing the server image.
Daemon management scripts are exposed without enrollment tokens for already installed machines:
GET /api/daemon/scripts/upgrade.shGET /api/daemon/scripts/reinstall.shGET /api/daemon/scripts/uninstall.shGET /api/daemon/scripts/upgrade.ps1GET /api/daemon/scripts/reinstall.ps1GET /api/daemon/scripts/uninstall.ps1
Upgrade and reinstall scripts keep the existing daemon config, download the
selected release artifact, verify SHA256SUMS.txt, replace the binary, and
restart the service. Uninstall removes the service and binary; set
NEKODE_PURGE_CONFIG=1 to also remove local daemon config. The scripts follow
the installer's Teleport-style shape: root/admin assertion, clear logging,
platform and architecture detection, checksum verification, service manager
integration, and explicit cleanup behavior.
Environment variables:
| Name | Default | Purpose |
|---|---|---|
NEKODE_ADDR |
:18790 |
HTTP listen address |
NEKODE_GRPC_ADDR |
127.0.0.1:18789 |
local daemon gRPC listen address |
NEKODE_DAEMON_CONFIG |
$HOME/.nekode/daemon.json |
daemon install config path |
NEKODE_DAEMON_TOKEN |
empty | local daemon token override for smoke tests |
NEKODE_BASE_URL |
http://localhost:18790 |
Public server URL |
NEKODE_WEB_DIST_DIR |
empty | Optional external Web console dist directory; the binary serves embedded assets by default |
NEKODE_DATA_DIR |
$HOME/.nekode |
Persistent data directory |
NEKODE_DB_TYPE |
sqlite |
Database type: sqlite, postgres, or mysql |
NEKODE_DB_DSN |
$NEKODE_DATA_DIR/nekode.db |
Database DSN |
NEKODE_DB_PATH |
empty | Legacy SQLite path alias if NEKODE_DB_DSN is unset |
NEKODE_CACHE_DRIVER |
badger |
Cache provider: badger, redis, or none |
NEKODE_CACHE_DIR |
$NEKODE_DATA_DIR/cache |
Badger cache directory |
NEKODE_CACHE_TTL |
5m |
Default projection/read-through cache TTL |
NEKODE_CACHE_REDIS_ADDR |
empty | Redis address when using the Redis cache provider |
The cache is a rebuildable projection/read-through layer. The database and durable event log remain authoritative for idempotency, leases, event sequence, task claims, sessions, secrets, and config.
Build the Web console and a release-style Go binary:
./build.sh
./dist/nekode version
./dist/nekode-daemon versionUseful build variables:
VERSION=v0.1.0 COMMIT="$(git rev-parse --short HEAD)" ./build.sh
GOOS=linux GOARCH=arm64 ./build.sh dist/nekode-linux-arm64Build and run the local container image:
docker build \
--build-arg VERSION=local \
--build-arg COMMIT="$(git rev-parse --short HEAD)" \
--build-arg BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
-t nekode:local .
docker compose up --buildThe Docker image and build.sh embed the Vite Web console into the nekode
binary. The server exposes the Web console and API from the same port
(18790). Set NEKODE_WEB_DIST_DIR or --web-dist-dir only when you want to
override the embedded assets with an external static directory during
development.
The first implementation target is the daemon/server control plane described in
docs/slock-style-daemon-runtime.md. Generate Go bindings with:
buf generateThe protobuf package is nekode.daemon.v1. Field numbers and RPC semantics are
kept aligned with the reusable Slock-style IDL produced from the Nekobot
protocol work.
buf lint
buf generate
go test ./...
go build ./...
git diff --check