Plugins¶
sqlite-utils supports plugins, which can be used to add extra features to the software.
The plugin directory lists plugins that are available to install.
Plugins can add new commands, for example sqlite-utils some-command ...
Plugins can be installed using the sqlite-utils install command:
sqlite-utils install sqlite-utils-name-of-plugin
You can see a JSON list of plugins that have been installed by running this:
sqlite-utils plugins
Plugin hooks such as prepare_connection(conn) affect each instance of the Database class. You can opt-out of these plugins by creating that class instance like so:
db = Database(memory=True, execute_plugins=False)
Building a plugin¶
Plugins are created in a directory named after the plugin. To create a “hello world” plugin, first create a hello-world directory:
mkdir hello-world
cd hello-world
In that folder create two files. The first is a pyproject.toml file describing the plugin:
[project]
name = "sqlite-utils-hello-world"
version = "0.1"
[project.entry-points.sqlite_utils]
hello_world = "sqlite_utils_hello_world"
The [project.entry-points.sqlite_utils] section tells sqlite-utils which module to load when executing the plugin.
Then create sqlite_utils_hello_world.py with the following content:
import click
import sqlite_utils
@sqlite_utils.hookimpl
def register_commands(cli):
@cli.command()
def hello_world():
"Say hello world"
click.echo("Hello world!")
Install the plugin in “editable” mode - so you can make changes to the code and have them picked up instantly by sqlite-utils - like this:
sqlite-utils install -e .
Or pass the path to your plugin directory:
sqlite-utils install -e /dev/sqlite-utils-hello-world
Now, running this should execute your new command:
sqlite-utils hello-world
Your command will also be listed in the output of sqlite-utils --help.
See the LLM plugin documentation for tips on distributing your plugin.
Plugin hooks¶
Plugin hooks allow sqlite-utils to be customized.
register_commands(cli)¶
This hook can be used to register additional commands with the sqlite-utils CLI. It is called with the cli object, which is a click.Group instance.
Example implementation:
import click
import sqlite_utils
@sqlite_utils.hookimpl
def register_commands(cli):
@cli.command()
def hello_world():
"Say hello world"
click.echo("Hello world!")
New commands implemented by plugins can invoke existing commands using the context.invoke mechanism.
As a special niche feature, if your plugin needs to import some files and then act against an in-memory database containing those files you can forward to the sqlite-utils memory command and pass it return_db=True:
@cli.command()
@click.pass_context
@click.argument(
"paths",
type=click.Path(file_okay=True, dir_okay=False, allow_dash=True),
required=False,
nargs=-1,
)
def show_schema_for_files(ctx, paths):
from sqlite_utils.cli import memory
db = ctx.invoke(memory, paths=paths, return_db=True)
# Now do something with that database
click.echo(db.schema)
prepare_connection(conn)¶
This hook is called when a new SQLite database connection is created. You can use it to register custom SQL functions, aggregates and collations. For example:
import sqlite_utils
@sqlite_utils.hookimpl
def prepare_connection(conn):
conn.create_function(
"hello", 1, lambda name: f"Hello, {name}!"
)
This registers a SQL function called hello which takes a single argument and can be called like this:
select hello("world"); -- "Hello, world!"