tide generate writes a typed Go client into your repository, scoped to
the namespaces your caller consumes. The generated code is committed: a
schema change appears in review as a diff of the API your application
calls, and the application builds from a clean checkout with no atlantis
server, no buf, and no shared SDK.
What gets generated
With output_dir and generate: set in tide.yaml, tide generate
fetches the canonical schema from the server, so proto field numbers match
the server exactly. It filters that schema to the generate: namespaces.
A cross-namespace foreign key is a scalar column, so referencing another
namespace’s entity does not require generating its types. It then emits
proto sources and typed wrappers under output_dir, inside your own
module with your own import paths, running buf generate for the wire
types.
Each entity gets a client interface with its six RPCs (Get, BatchGet,
Create, Update, Delete, Query) and a typed method per custom query
and procedure. A keyless entity gets no client: without a key there is
nothing to address a row by. A namespace declaring jobs also gets a
jobs.go with a typed Args struct, handler interface, and
Register<Job> helper per job.
generate owns only the roots it writes — atlantis/, pb/, client/,
and the two buf config files — and leaves everything else under
output_dir alone. It refuses a tree generated by a different caller.
Why a stale client still works
Proto field numbers are preserved by field name across applies. A removed field’s number is retired and reserved for as long as the entity exists, and a new field takes the smallest free number. An old client therefore keeps sending a shape the server understands. It cannot see fields added since it was generated, and code using a new entity will not compile until you regenerate. A column whose type changes keeps its number with a new proto type, so regenerate after a type change before relying on that field.
tide apply never regenerates the client; it refreshes only the
.tide-cache/ mirror. Its success message reminds you to run
tide generate.
The manifest and --check
tide generate writes tide.manifest.json beside the code: the caller,
the namespaces, the module prefix, and a committed hash per generated
file.
tide generate --checkverifies the tree against the manifest with no server, no credentials, and nobuf. It catches hand-edited, missing, and leftover files.tide generate --check --against-serveralso reports whether the schema has moved since this client was generated. It needs credentials for that.
The manifest records no timestamp and no checkpoint hash, so two runs that produce identical code produce an identical manifest.
Related
- The typed query surface — what the generated
Querycan express. tide generate— flags and exit codes.- Set up CI — where
--checkbelongs in a pipeline.