Docs
Groups and local commands
Organize related functions into groups with shared secrets, and add local-only CLI commands.
A project can hold many functions. Put related ones in a Group. People see a group as one section of the project in the web app, and you run its functions as call <group> <action>.
from typing import Literal
from callables import Group
backups = Group(
"backups",
title="Database backups",
description="Postgres dumps to object storage",
secrets=["SPACES_KEY", "SPACES_SECRET"],
)
@backups.deploy(title="Back up now", secrets=["DATABASE_URL"])
def run(env: Literal["prod", "staging"] = "prod", keep: int = 7) -> str:
...
@backups.deploy(title="List backups")
def list_all(days: int = 30) -> list[dict]:
...call backups --help
call backups run --help
call backups run --env staging --keep 3Rules
- A group's
secretsgo to every action in it. Each action can declare more of its own. - A group name is lowercase letters, digits,
-or_, and can't be a built-in command such ascheckorlocal. - Define each group once and import it wherever you need it.
- An action's full name is
<group>.<name>, such asbackups.run. Use that withcall local. @group.deploytakes the same options as@deploy.- Moving an existing function into a group gives it a new name, so it starts with fresh run history and sharing settings.
- Plain
@deployfunctions still work. They appear in the project without a section.
Local commands
Some tools only make sense on your own machine: they read local files, write reports to disk or open a browser. Write them with @command (or @group.command) instead of @deploy, so the project has one CLI:
from callables import Group
audits = Group("audits", title="Audits")
@audits.command
def render(slug: str, open_browser: bool = False) -> str:
...- They run as
call audits render --slug x, and withcall local.call checklists them as "(local only)". - They're never deployed. Nobody can run them from the web app.
@commandtakesname,title,descriptionandnext, but nosecrets,scheduleortimeout. Read secrets from your own.env.- Their module is still imported when the platform builds, so keep imports that only work locally inside the function.
- Return the result instead of printing it. The CLI prints what you return: aligned columns in a terminal, JSON when piped.
- To deploy one later, change
@commandto@deploy. It keeps its name.