Skip to content

Bob Plugin Mode

By default, kiln generate handles everything: it runs bob internally to read your schema, then generates the API layer. This is the recommended approach for most projects.

For teams already using bob's code generation pipeline, kiln is also available as a bob plugin. This lets you run bob and kiln in a single pass - one command, one process - instead of running them separately.

When to use the plugin

  • You already have a custom main.go that runs bobgen-psql (or bobgen-mysql/bobgen-sqlite)
  • You want bob models and kiln's API layer generated together
  • You want to add other bob plugins alongside kiln

If you're starting fresh, use kiln generate instead. It's simpler and does the same thing.

Install

The plugin is part of the main kiln module:

go get github.com/fisayoafolayan/kiln@latest

Setup

Create a gen/main.go in your project. This replaces running bobgen-psql directly - you need a custom entrypoint to load plugins.

package main

import (
    "context"
    "log"
    "os"
    "os/signal"

    "github.com/stephenafamo/bob/gen"
    "github.com/stephenafamo/bob/gen/bobgen-psql/driver"
    "github.com/stephenafamo/bob/gen/plugins"
    kilnplugin "github.com/fisayoafolayan/kiln/plugin"
)

func main() {
    ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
    defer cancel()

    // Bob config
    driverConfig := driver.Config{DSN: os.Getenv("DATABASE_URL")}
    config := gen.Config{} // or load from file

    // Bob's default plugins (models, factory, etc.)
    bobPlugins := plugins.Setup[any, any, driver.IndexExtra](
        plugins.Config{}, gen.PSQLTemplates,
    )

    // Kiln plugin - generates API layer
    kiln := kilnplugin.New[any, any, driver.IndexExtra](kilnplugin.Options{
        ConfigPath: "kiln.yaml",
    })

    state := &gen.State[any]{Config: config}
    allPlugins := append(bobPlugins, kiln)

    if err := gen.Run(ctx, state, driver.New(driverConfig), allPlugins...); err != nil {
        log.Fatal(err)
    }
}

Then run:

export DATABASE_URL="postgres://..."
go run gen/main.go

This generates bob models and kiln's API layer in a single pass.

Plugin options

kilnplugin.Options{
    // Path to kiln.yaml. Defaults to "kiln.yaml".
    ConfigPath: "kiln.yaml",

    // Override the Go module path. If empty, read from go.mod.
    ModulePath: "",

    // Overwrite user-modified files (same as --force flag).
    Force: false,

    // Where status messages are written. Defaults to os.Stdout.
    Output: os.Stdout,
}

How it works

kiln implements bob's DBInfoPlugin interface:

type DBInfoPlugin[T, C, I any] interface {
    Plugin
    PlugDBInfo(*drivers.DBInfo[T, C, I]) error
}

Bob calls PlugDBInfo after database introspection, passing the full schema. kiln converts it into its internal representation and runs the same generators that kiln generate uses. The output is identical.

Other databases

Replace the driver import for MySQL or SQLite:

MySQL:

import "github.com/stephenafamo/bob/gen/bobgen-mysql/driver"

SQLite:

import "github.com/stephenafamo/bob/gen/bobgen-sqlite/driver"

The rest of the setup is the same.

Plugin vs CLI

kiln generate Bob plugin
Setup kiln.yaml only Custom gen/main.go + kiln.yaml
Bob models Generated internally Generated by your pipeline
Other bob plugins Not supported Add as many as you want
Recommended for Most projects Teams with existing bob pipelines

Both produce identical output. The plugin just changes how bob and kiln are orchestrated.

Example

See the Team Task Tracker for a complete working example using kiln as a bob plugin.