Skip to content
ReferenceCommand line

rent init

Add Rent to an existing crate

rent init --database postgres User Post Comment
Created ./rent.toml
Created User in ./rent/schema.rsl
Created Post in ./rent/schema.rsl
Created Comment in ./rent/schema.rsl
Generated ./rent/generated
Declared the generated client in ./src/lib.rs
        #[allow(dead_code, unused_imports)]
        #[rustfmt::skip]
        #[path = "../rent/generated/mod.rs"]
        pub mod generated;
Next: Edit the schema, then run `rent migrate dev --name describe_the_change`.

One command records the configuration, creates the model declarations, generates the typed client, and declares that client in the crate root so it can be used immediately.

Keep the client in its own crate

rent init --crate --database postgres User Post
Created crate ./ledger-db
Declared a workspace in ./Cargo.toml with ledger-db as a member
Added a dependency on ledger-db to the package
Created ./rent.toml
Created User in ./ledger-db/rent/schema.rsl
Created Post in ./ledger-db/rent/schema.rsl
Generated ./ledger-db/rent/generated

--crate puts the schema, the migrations, and the generated client in a sibling crate, named <package>-db unless you pass --crate=DIR, and records that crate in rent.toml. The package depends on it and reaches the client as ledger_db::generated. An edit to the package then never recompiles the generated code, which is what keeps incremental builds fast as the schema grows. rent new uses the same layout.

At a workspace root this is the default: the new crate joins the member list, and the root package, when there is one, gains the dependency. A standalone package only does it when asked, because it becomes a workspace root in the process. A package that belongs to a workspace declared elsewhere is refused with the directory to run the command in, since the member list to edit lives there.

--database records the dialect and backend in a new rent.toml. It is refused when the project already configures a different database, so an existing configuration is never silently rewritten. Repeating the same database is a no-op. Omit the flag to accept the sqlite default.

Each model starts with a database-generated identity and an explicit table mapping:

model User {
  id BigInt @id @default(autoincrement())

}

Rent refuses to add a model whose name already exists.

How the crate reaches the client

Generated code lives under rent/, outside the source tree, so the declaration carries a #[path] attribute. That single attribute resolves the whole generated subtree. The declaration is placed after any inner attributes and inner doc comments, which must precede every item, and it is never inserted between a comment block and the item that comment documents.

The module takes its name from the final component of generated, so rent/generated becomes crate::generated. When the crate already declares a module by that name, rent init reports it and writes nothing but rent.toml:

Created ./rent.toml
Error: `./src/lib.rs` already declares a different `generated` module; change the final component of
       `generated` in rent.toml to name this client something else

Set generated = "rent/db" in that file and run the same command again to reach the client as crate::db. Because the failure happens before any schema or generated code is written, re-running is clean.

A crate with no conventional root prints the declaration to place by hand rather than failing:

Action no crate root found; add the generated client to your module tree:
        #[allow(dead_code, unused_imports)]
        #[rustfmt::skip]
        #[path = "../rent/generated/mod.rs"]
        pub mod generated;

Add models to an existing project

Once rent.toml exists, rent init only adds declarations and regenerates:

rent init Comment

Run rent generate after later manual schema edits, or keep rent dev running to regenerate automatically.

Initialize another directory

rent --root services/blog init User Post Comment