Doc daemon
Agach orchestrates AI coding agents for your team. Define features through structured conversations. Agents execute the work in isolated environments, one task at a time, on your codebase.
npx -y skills add JLugagne/agach --skill doc-daemonAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Agach daemon agent: onboarding, WebSocket reconnect, Docker builds, chat sessions (Claude CLI), git worktrees, SQLite persistence
SKILL.md
4.6 KB, ~1.2k tokens by cl100k_base, as published. Nobody here has run it
Agach Daemon (internal/daemon/)
Overview
Background agent that onboards with the server, maintains a WebSocket connection, manages Docker image builds, spawns Claude CLI chat sessions, and manages git worktrees.
Domain Types (domain/)
types.go
OnboardingResult— AccessToken, RefreshToken, NodeID, NodeName, ModeProjectInfo— ID, Name, GitURLDaemonState— StateDisconnected, StateOnboarding, StateConnectedBuildID,BuildStatus— pending, building, success, failedDockerBuild— ID, DockerfileSlug, Version, ImageHash, ImageSize, Status, BuildLog, timestamps
ports.go (interfaces)
ServerAuth— RefreshDaemonToken(nodeID, refreshToken) → accessTokenServerOnboarding— CompleteOnboarding(code, nodeName) → OnboardingResultServerConnection— RunWithReconnect(ctx), Send(msg)ProjectFetcher— GetProject(token, projectID) → ProjectInfoChatUploader— UploadJSONL(token, projectID, featureID, sessionID, filePath)
Configuration (config/config.go)
- File:
~/.config/agach/daemon.yml(or AGACH_SERVER_URL env var) - Fields: base_url, node_name
- Env-only: AGACH_ONBOARDING_CODE (6-digit code)
- Derived: SQLitePath() → daemon.db, WebSocketURL() → ws:// or wss://
App Layer (app/)
Main Loop (app.go)
States: Init → Onboarding → Connected → Reconnecting → Stopped
Run(ctx)— onboard → connect WS → handle events until stopped- WebSocket event routing: docker.list, docker.rebuild, docker.logs, docker.prune, chat.start, chat.user_msg, chat.end, chat.ping
Token Store (tokens.go)
- Persists to
~/.config/agach-daemon/tokens.json(0600 permissions) - Fields: access_token, refresh_token, node_id, node_name
Chat Manager (chat.go)
- Spawns Claude CLI with
--output-format stream-json - Captures stdout/stderr, writes JSONL log
- 30-minute idle TTL with 25-minute warning broadcast
- Stats broadcaster every 5 seconds (token counts, cost, duration)
- Session lifecycle: StartSession → SendMessage → EndSession (stop process, upload JSONL)
ChatSessiontracks: ID, FeatureID, ProjectID, ClaudeSessionID, WorktreePath, token counts, model, message count, timestamps
Docker Service (docker.go)
ListImages(ctx)— groups builds by dockerfile slugRebuild(ctx, slug, eventCh)— creates build record, streams eventsGetBuildLogs(ctx, buildID)— returns build logPruneNonLatest(ctx, eventCh)— removes all but latest per slug
Git Service (git.go)
- Cache dir:
~/.cache/agach EnsureWorktree(projectID, gitURL, mainBranch)— clone or fetch+pull- Auth: SSH keys or GITHUB_TOKEN for HTTPS
Client Layer (client/)
AuthClient— POST /api/daemon/refreshOnboardingClient— POST /api/onboarding/complete (error codes: CODE_NOT_FOUND, CODE_EXPIRED, CODE_ALREADY_USED)ProjectClient— GET /api/projects/{projectID}WSClient— WebSocket with exponential backoff reconnect (1s → 30s max)ChatUploadClient— POST multipart JSONL upload
Inbound WebSocket Hub (inbound/ws/)
- Local hub for TUI clients connecting to the daemon
- Handlers: HandleListDockerfiles, HandleRebuild (async), HandleGetLogs, HandlePrune (async)
- Build/prune events forwarded to hub as they occur
- HandlerFunc signature:
func(ctx, daemonws.Message) (daemonws.Message, error)
Outbound SQLite (outbound/sqlite/)
- Database: daemon.db (local)
buildstable: id, dockerfile_slug, version, image_hash, image_size, status, build_log, timestamps- Repository: Create, FindByID, ListByDockerfile, ListAll, UpdateStatus, Delete, DeleteNonLatest
WebSocket Protocol (pkg/daemonws/)
Docker Messages
docker.list/docker.rebuild/docker.logs/docker.prune- Events:
build.event(slug, build_id, status, log),prune.event(slug, removed, total)
Chat Messages
chat.start→ ChatStartRequest (session_id, feature_id, project_id, node_id, resume_session_id)chat.user_msg→ ChatUserMessage (session_id, content)chat.end→ EndSessionchat.ping→ RefreshActivity- Events:
chat.message,chat.stats,chat.end,chat.error,chat.ttl_warning
Init (init.go)
- Parse
-initflag (create default config) - Load config from file or env
- Create SQLite database + migrations
- Create build repository
- Instantiate daemon app
- Signal handling (SIGINT, SIGTERM)
- Run with reconnect logic