Skip to content

feat: the "kiqr agent" — a persistent, inspectable background service - #22

Merged
kjellberg merged 1 commit into
kiqr:mainfrom
kjellbergzoey:feat/kiqr-agent-service
Jun 7, 2026
Merged

feat: the "kiqr agent" — a persistent, inspectable background service#22
kjellberg merged 1 commit into
kiqr:mainfrom
kjellbergzoey:feat/kiqr-agent-service

Conversation

@kjellbergzoey

Copy link
Copy Markdown
Contributor

The kiqr agent

The Traefik reverse proxy and the splash fallback page used to be a standalone stack: started on kiqr up, torn down via stopTraefikIfIdle() whenever no project was running. Switching between projects (or running kiqr down then kiqr up) churned the proxy up and down.

This PR promotes that shared infrastructure into a first-class, named, persistent background service: the "kiqr agent." It is kiqr core, managed explicitly, and runs as a single Docker Compose project (kiqr-agent) that persists independently of any individual project. It's the natural home for the shared infra we want to grow into next: a dashboard, a mail catcher, and the future collaboration tunnel client.

Lifecycle change (the key behavior fix)

The agent is now persistent by default:

  • kiqr up / kiqr restart call ensureAgentRunning() (idempotent; step label is now "Starting kiqr agent...").
  • The agent runs with Docker's restart: unless-stopped policy.
  • kiqr down and kiqr destroy no longer stop the shared infra — they only affect the current project. The previous stopTraefikIfIdle() calls have been removed.
  • The agent starts on the first kiqr up and stays up across projects until you explicitly run kiqr agent stop.

This eliminates the start/stop churn and matches how a background service should behave.

New command group: kiqr agent

  • kiqr agent start — ensure the agent is running (shows the proxy URL).
  • kiqr agent stop — stop the agent.
  • kiqr agent restart — restart the agent.
  • kiqr agent status — render getAgentStatus(): running?, each container, and the port.
  • kiqr agent logs — stream the agent containers' docker compose logs (stdio inherit).

Refactor

  • src/lib/traefik.tssrc/lib/agent.ts, with an agent-oriented API: generateAgentCompose, writeAgentCompose, ensureAgentRunning, stopAgent, restartAgent, ensureKiqrNetwork, isAgentRunning, and a new dependency-injected getAgentStatus(deps) returning {running, containers, port} for testability.
  • Tests migrated to tests/lib/agent.test.ts and expanded (compose generation incl. the name: kiqr-agent project identity + container-name compatibility, and getAgentStatus logic with a mocked container check).

Backward compatibility

Container names (kiqr-traefik, kiqr-splash) and the kiqr Docker network are deliberately unchanged, so existing setups keep working. Only the compose project gains a name: kiqr-agent identity.

Not in this PR (planned follow-up)

kiqr agent install (systemd/launchd daemon registration) is intentionally deferred — it needs a real host to verify. Persistence via Docker restart: unless-stopped is sufficient here.

Rebase note

This branch touches src/commands/up.tsx and src/commands/restart.tsx, which are also edited by the open PR #17. It will need a trivial rebase relative to that PR (just the proxy/agent step in those two files).

Verification

All gates pass locally: npm run typecheck, npm test (117 tests), npm run build, npm run lint. node dist/cli.js agent --help, agent (group help), and agent status all render correctly. The actual agent start Docker path could not be exercised here (no Docker daemon); agent status correctly reports "stopped" with no daemon.

🤖 Generated with Claude Code

…rvice

The Traefik reverse proxy and the splash fallback page were previously a
standalone stack that was started on `kiqr up` and torn down whenever no
project was running, causing start/stop churn when switching between
projects.

This refactors that shared infrastructure into a single, named, persistent
background service — the "kiqr agent" — managed as the `kiqr-agent` Docker
Compose project. It is kiqr core, persists independently of any project,
and is the home for future shared infra (dashboard, mail catcher, the
collaboration tunnel client).

Changes:
- Rename src/lib/traefik.ts -> src/lib/agent.ts with agent-oriented API:
  generateAgentCompose, writeAgentCompose, ensureAgentRunning, stopAgent,
  restartAgent, ensureKiqrNetwork, isAgentRunning, and a testable
  getAgentStatus(deps) returning {running, containers, port}.
- Container names (kiqr-traefik, kiqr-splash) and the `kiqr` network are
  unchanged for backward compatibility; the compose file now carries a
  `name: kiqr-agent` project identity.
- New `kiqr agent` command group: start, stop, restart, status, logs.
- Lifecycle change: `kiqr up`/`kiqr restart` call ensureAgentRunning(); the
  agent runs with `restart: unless-stopped` and is no longer auto-stopped by
  `kiqr down`/`kiqr destroy`. It persists across projects until the user runs
  `kiqr agent stop`.
- Migrate/expand tests (tests/lib/agent.test.ts), update README and help.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kjellberg
kjellberg merged commit c0fcbfc into kiqr:main Jun 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants