


Make Small Changes to an App Built on a Local Background Service (Daemon)
Use when an AI codes in a project where a command-line tool and a desktop app both use a local background service. It reads the docs first, runs the project's own checks, keeps the network and data rules, and opens one change request (pull request) per issue.
To use this AI rule
## Read the Design Docs and Learn What Each Folder Does Before Coding
Keep changes small, match the architecture the repository currently targets, and prefer the documented daemon/API boundaries over behavior inherited from an older implementation that is being replaced.
Learn the layout by role, not by filename:
- The backend holds the command-line client, the loopback HTTP daemon, services, embedded-database storage, lifecycle/reaper logic, runtime and workspace adapters, and their tests.
- The desktop or web front end is a thin supervisor and UI surface wired to the daemon through a generated typed client. Do not move daemon logic into it.
- The docs directory holds the current architecture and status notes. Read them before changing lifecycle, client, agent, storage, or daemon behavior.
- A separate test directory holds external smoke and end-to-end assets, including fresh-install container checks.
- The CI workflow definitions are the reference for what must pass. Mirror those commands locally when possible.
Read in this order before a non-trivial change: the quickstart README, the docs index, the architecture document (mental model, package layout, lifecycle/session/service boundaries, and load-bearing rules), the status document (what is shipped on the main branch today versus what is still in flight), and the client document (its intended shape). If the repository also carries compatibility pointer files for other agent tools, treat them as redirects to the one canonical guide rather than as separate rule sets.
Locate entry points by responsibility rather than by searching blindly: command implementations, HTTP controllers and DTOs, service read/write boundaries, domain vocabulary, port contracts, database queries and migrations, and generated database code each live in their own package. Follow the nearby command and test patterns before introducing a new style.
## Run the Project's Own Checks and Look at Screen Changes Yourself
Use the repository's own aggregate commands rather than inventing ad-hoc ones. From the repository root these typically cover: lint (backend tests plus a pinned linter version), front-end type checking, regeneration of database access code from queries and schema, regeneration of the API spec and front-end types, and a local workflow runner that validates CI definitions (which may require a container socket).
Component-level checks are still worth running directly while iterating: build, test, race-enabled test, static analysis (vet), and starting the service for the backend; type check and build for the front end.
When a change is visible in the UI, actually render it inside the session using the project's preview command and look at the result. Do not merely describe what the change should look like.
## Point Users to the Auto-Updating Desktop App as the One Install Method
When a project has more than one install path, only one is canonical, and guidance must point there.
- The auto-updating desktop build published through releases is the canonical install path. Point users there first.
- A legacy package-manager channel may still function while being no longer recommended. If a final version has been published and the package is frozen, it receives no further updates. It remains an on-ramp only for users who already have the command on their PATH, where launching it fetches and opens the canonical build.
- Do not add features, documentation, or flows that treat a frozen legacy channel as the intended way to install the product.
## Change Only What the Task Needs and Follow the Existing Code Layout
- Keep every change directly tied to the task. Avoid drive-by cleanup, broad renames, formatting churn, speculative abstractions, and architectural refactors unless the task explicitly asks for them.
- Follow the existing package boundaries. Client code calls daemon HTTP routes through the shared client helpers; it must not open the database, spawn runtimes, or call adapters directly.
- Keep each command in its relevant command file and table-test it in the style of the neighboring command tests.
- Mirror request and response DTOs on the client side instead of importing server controller packages into client code, unless that dependency is already established in the package.
- Return usage errors through the dedicated usage-error type so that client misuse exits with its own status code (for example 2), while runtime and daemon failures exit with the general failure code (for example 1).
- Preserve API error envelopes and request IDs when surfacing daemon errors instead of flattening them into plain strings.
- Pass a cancellation/deadline context as the first argument of any function that performs I/O or blocking work.
- Do not add abstractions for one-off use cases. Introduce a helper only when it removes duplication across real call sites.
- Tests should cover the user-visible behavior and the boundary being changed: the happy path, validation and missing arguments, daemon error envelopes, and any destructive confirmation path.
## Do Not Change or Add Network Entry Points to the Background Service
- The daemon's primary listener stays bound to the loopback address and stays unauthenticated. Do not change its bind host and do not add authentication to it.
- The daemon may run a second, opt-in listener that binds all interfaces for local-network access, but only while explicitly enabled, only behind the bearer-password authentication middleware, and only serving the application API. That listener must never serve the loopback-gated control routes such as shutdown, telemetry, and remote control.
- Where such a listener is plaintext and intended for a trusted home network only, that is a deliberate, documented decision recorded in an architecture decision record. Read that record before touching it.
- Do not add any other network-facing bind.
- The command-line client stays a thin client. Do not port older in-process behavior that bypasses the daemon's HTTP routes.
## Protect Saved Data and Never Hand-Edit Generated Database Code
- Do not store derived or display-oriented status. Derive status from durable facts (activity state, termination flag, pull-request/check/comment facts) at service read time.
- Do not treat a failed or unknown runtime probe as proof that a session is dead.
- Do not force-delete registered worktrees that still have uncommitted changes.
- Do not modify migrations that have already been merged. Add a new migration instead.
- Do not hand-edit generated database code. Change the queries or migrations and re-run the generator.
- Change events flow from database triggers into the change log. Do not add a parallel, manual change-emission path from store methods unless the architecture changes explicitly.
- Watch for drift between generated API artifacts and hand-written DTOs. Controller response shapes live in a single DTO file, and tests may assert wire compatibility between the client and HTTP layers.
- Do not add network calls to tests unless the package already has an integration or end-to-end pattern for them. Prefer in-process test servers, fakes, and injected dependencies.
- Do not commit local run state, daemon data, temporary worktrees, build outputs, or credentials.
- Keep all application state under the single dedicated state directory, overridable through the documented environment variables. The daemon data directory, the running-process file, worktrees, and the desktop shell's user-data (browser cache, cookies, local and session storage, crash dumps) must all resolve under it. Never read from or write to the operating system's default application-data location. The desktop entry point pins the shell's user-data path to that directory; do not remove that override or rely on the default path.
## Change the API in the Hand-Written Files, Then Regenerate Its Description
The daemon API is code-first. The OpenAPI specification and the front-end types are generated artifacts, so edit the source and regenerate rather than editing the outputs.
- Edit the DTO file that defines request and response shapes.
- Edit the specification-builder operation registry, adding a schema-name entry for any newly named type.
- Regenerate with the repository's aggregate API command, which runs specification generation and type generation in sequence.
- Verify with the tests in the server HTTP package; they cover specification drift and route/specification parity. They do not cover the generated front-end types, which a separate CI drift job checks.
- Commit the generated specification and the generated front-end types together with the source changes. CI regenerates both and fails if the committed versions are stale.
- The hand-mirrored client DTOs remain a deliberate manual boundary and are not generated.
## Keep Each Change Request (Pull Request) to One Issue
- Branch from the main branch unless you are explicitly continuing an existing pull request.
- Keep one issue per pull request. If asked for separate work, create a separate branch and pull request.
- Use conventional commit message prefixes such as feat, fix, docs, test, and chore.
- Explain intentional omissions in the pull request body, especially when a predecessor implementation supported more behavior than the current rewrite's domain does.
- Run the narrowest relevant tests first, then the repository and CI commands that match the area you touched.
