Caraer CLI
Developer CLI for building Caraer apps: serverless functions, webhooks, schedules, inbound routes, lifecycle hooks, and CMS modules.
The CLI is a thin client of the Caraer API. You do not need GCP credentials on your machine.
Docs: developer.caraer.com
Requirements
- Python 3.10+ (the CLI itself)
- Node.js 22 and npm (default
nodejs22runtime and the starter CMS module) - A Caraer account that can create apps in a company
Install
pipx install caraer-cli
# or: uv tool install caraer-cli
# or: pip install caraer-cli
Confirm:
caraer --version
caraer profile current # prod, https://api.caraer.com
A new install uses the prod profile. caraer profile use local, dev, or
staging switches API host.
Install from source
git clone https://github.com/Caraer-HQ/caraer-cli.git
cd caraer-cli
python3 -m venv .venv
source .venv/bin/activate
./scripts/install.sh
caraer --version
If install fails with requires a different Python, create the venv with
python3.10, python3.11, or python3.12. Restart the terminal so tab
completion loads.
Prompt for an AI coding agent
Paste this into Cursor, Claude Code, or a similar agent. It installs the CLI, logs you into production, and scaffolds an app. It does not deploy.
Set up the Caraer CLI on this machine and scaffold a Caraer app. Do not push,
deploy, install, or publish the app unless I explicitly ask.
1. Check Python is 3.10 or newer (`python3 --version`). If it is older, stop
and tell me how to install it.
2. Check Node.js 22 is available (`node --version`). The default `nodejs22`
runtime and starter CMS module need it. If it is missing, stop and tell me.
3. If `caraer --version` fails, install the CLI:
prefer `pipx install caraer-cli`, else `uv tool install caraer-cli`,
else `pip install caraer-cli`. Confirm with `caraer --version`.
4. Confirm the active profile is production before login:
`caraer profile current`
base_url must be https://api.caraer.com. If it is not, run `caraer profile use prod`.
5. Install the agent skills so later edits follow Caraer app conventions:
`caraer skill install`
Tell me to start a new chat before relying on those skills.
6. Log in with `caraer auth login` and stop so I can approve the device code
in the browser. Do not ask for or type my password. If device login is
unavailable, ask me to run `caraer auth login --email <my-email>` myself.
7. Browser login lets the user choose the default CLI company. If no company
was selected, run `caraer company select` to choose one.
8. Ask whether the app is private to that company or a public marketplace app,
and what label to use. Then scaffold with platform 2026.2.1 (the default):
- Private: `caraer apps init --private --label "<Label>" --auth-method NONE`
- Public: `caraer apps init --label "<Label>"`
Do not pass `--platform 2026.1`.
9. Change into the new folder and run `caraer apps validate`. Fix only errors
the scaffold itself reported.
10. Summarize the folder, how to run it locally (`caraer apps local dev`), and
that `caraer apps push` deploys and installs on the selected company.
Wait for me before pushing.
After that chat, open a new agent chat in the app folder. The installed
skills (caraer-apps, caraer-cms) are what teach the agent the app layout.
caraer skill install # ~/.cursor/skills/caraer-apps and caraer-cms
caraer skill install --project # ./.cursor/skills in the current directory
caraer skill list
Quick start
caraer auth login
# Choose the default CLI company in the browser after signing in.
# CI or password login: caraer auth login --email you@example.com
caraer company select
Browser login saves the chosen company as the default for the active CLI profile.
Use caraer company select to change it later.
Use ↑/↓ to highlight a company and Enter to select it. The current company is
highlighted by default. Scripts can still pass a UUID with
caraer company select <company-uuid>.
Create a local app:
caraer apps init --label "My App"
# company-only app:
caraer apps init --private --label "Internal Tool" --auth-method NONE
cd my_app
caraer apps validate
caraer apps local dev # local server: POST /functions/<name>
Deploy only when you mean to. caraer apps push syncs the manifest, functions,
webhooks, schedules, inbound routes, and OAuth providers, deploys the function
build, publishes CMS modules, and installs the app on the selected company.
caraer apps push --dry-run
caraer apps push # add --wait to block until the runtime is READY
caraer apps status
caraer apps local logs # the only local function, or a prompt
caraer apps local logs --all
caraer apps push validates the local app before planning or pushing, including
with --dry-run and --no-deploy. Validation errors cancel the command with a
non-zero exit code; fix the reported issues before retrying. Warnings are shown
and allow the push to continue, as with caraer apps validate.
Only the company that created the app (or a super-admin) can push builds.
caraer apps init creates an unlinked app even when another app is selected.
To link the new folder to an existing remote app, pass --app-uuid <uuid> explicitly.
caraer apps push uses the current folder's app link; a selected app in another
folder does not override it. An unlinked folder creates its own remote app.
caraer apps init and the create-app wizard show each setup step, with elapsed-time
updates every five seconds during long waits. Dependency installation also streams
npm informational logs. Progress messages go to stderr, including when output is
redirected.
--no-deploy syncs without a build. Private apps (caraer apps init --private,
or privateApp: true in caraer.json) use the private app API and cannot be
submitted with caraer publish.
New apps use workspace platformVersion: 2026.2.1 (one container per app). Use
--platform 2026.1 only for the legacy per-function model. See
docs/platform_versioning.md.
Add pieces
Run these inside the app folder:
caraer apps add function my-action
caraer apps add options-function list-items # dynamic select options
caraer apps add webhook --topic record.candidate.created --function my-action
caraer apps add webhook --mode HTTP --topic record.candidate.updated --url https://example.com/hooks/caraer
caraer apps add schedule heartbeat --cron "0 0 */12 * * *"
caraer apps add inbound echo --auth NONE --sync
caraer apps add setting
caraer apps add lifecycle-hook
caraer apps add module hello --kind section
On 2026.2.1 those write code files (see
examples/example):
- Webhook:
manifest.webhookson the exportedmanifestobject onsrc/app/functions/<name>.js(HTTP:src/app/webhooks/<name>.yaml) - Schedule:
src/app/schedules/<name>.js - Inbound:
src/app/inbound/<name>.js
On 2026.2 add webhook|schedule|inbound still write JSON under
src/app/webhooks/, schedules/, and inbound/.
caraer apps init already creates lifecycle files
(src/app/lifecycle/{install,uninstall,rotate,update}.js) and a complete CMS
website starter: site_header, hero, features, call_to_action,
site_footer, and a home page that composes the content sections. Features
and Call to action reuse modules/_components/FeatureCard.astro. The generated
README explains how to preview Home with npm run dev, customize editable
fields, and configure site chrome. Use --template default for the minimal
hello_world section, or --template website to select the full starter explicitly.
A 2026.2 app is rewritten to 2026.2.1 on the
next caraer apps push unless you decline the prompt (default yes) or
pass --no-upgrade. caraer apps upgrade does the same rewrite without
deploying. See docs/platform_versioning.md.
add schedule and add setting open a wizard when you omit flags.
add setting writes into src/app/settings.yaml.
Project layout
my_app/
caraer.json # platformVersion 2026.2.1, appUuid, privateApp
package.json
src/app/
app.caraer.yaml # identity, scopes, auth, details
settings.yaml # installer setting fields (optional section grouping)
functions/<name>.js # name is the filename; serverless webhooks live in export const manifest
appbars/<name>.js # appBars on this file; Caraer runs it for app.bar.triggered
lifecycle/<hook>.js # install | uninstall | rotate | update
schedules/<name>.js
inbound/<name>.js
webhooks/<name>.yaml # HTTP webhooks (POST to a URL, no function)
shared/ # import { helper } from "../shared/index.js" from each of the above
modules/<name>/<name>.astro
A function is a file named after the function, with export const handler (Node) or
def handler (Python). Helpers live in shared/.
Node handlers export handler. Payload types come from @caraer/client
(LifecyclePayload, WebhookPayload, SchedulePayload):
export const handler = async (req, res) => {
const body = req.body || {};
res.status(200).json({ ok: true, event: body.event || null });
};
Python handlers use caraer-client for the same payload types:
def handler(request):
return {"statusCode": 200, "body": {"ok": True}}
Shared helpers live in src/app/shared/ and are imported with the same relative
path locally and when deployed, for example import { helper } from "../shared/index.js" from
functions/<name>.js.
See examples/example for a full 2026.2.1 app
(named files, settings list, inbound, schedule, app bars, CMS module, and
setting-targeted record and due-date webhooks).
A private app can be removed from the company that created it:
caraer apps delete # selected private app; asks first
caraer apps delete --yes # no prompt
Uninstall is a different action: it removes one company's install and leaves the app in place. Delete is creator-company only, and only for private apps.
App pieces
Each piece is a file under src/app/ that points at a function, except CMS
modules, which are Astro components published with the app.
| Piece | What it does | Guide |
|---|---|---|
| Serverless functions | The code that runs | docs/functions.md |
| CMS modules | Blocks for the website builder | docs/modules.md |
| Webhooks | Run a function when a record or relation changes | docs/webhooks.md |
| Lifecycle | Run a function on install, update, uninstall, or credential rotate | docs/app_lifecycle.md |
| Schedules | Run a function on a cron | docs/schedules.md |
| Inbound routes | Public HTTP from an outside system into a function | docs/inbound.md |
Settings
Installation settings are filled in by the admin who installs the app.
src/app/settings.yaml is a single-level list of fields. Group related
fields into installer cards with section / sectionSubtitle on the field.
Caraer lays cards out left to right, top to bottom, at most 3 across.
Fields without section stay schema-only (no section card).
- name: candidate_mapping
type: MAPPING
label: Candidate mapping
section: Candidate
sectionSubtitle: Map CV fields and parsing behavior
- name: parse_on_cv_change
type: SWITCH
label: Parse when a CV changes
section: Candidate
- name: custom_mapping
label: Custom mapping for work experience
type: SWITCH
defaultValue: false
- name: work_experience_mapping
type: MAPPING
visibleWhen:
- field: custom_mapping
operator: EQUALS
value: true
A field with visibleWhen is shown, required, and submitted only while every
condition holds. Hidden fields are dropped.
Operators: EQUALS (default), NOT_EQUALS, IN, NOT_IN, IS_SET,
IS_NOT_SET.
Do not ask the installer for the Caraer API base URL. The runtime injects
body.caraerApiBase.
records.<setting:field>.all on requiredScopes follows the installer's
object pick. A path reads one key: <setting:due_date.objectName> and
<setting:due_date.propertyName> for a property single-select, and
<setting:field_map.email> for the mapping row whose fieldName is email.
A property scope is
records.<setting:due_date.objectName>.property.<setting:due_date.propertyName>.all.
The same placeholders work on webhook topics. See
docs/webhooks.md.
Profiles
Config is stored in the user config directory (config.toml). Built-in
profiles:
| Profile | API |
|---|---|
prod (default) |
https://api.caraer.com |
staging |
https://v2.staging.api.caraer.com |
dev |
https://v2.dev.api.caraer.com |
local |
http://localhost:8080 |
prod is the Cloudflare edge. staging and dev are DNS aliases on Vercel
(v2.staging.api → staging.api.caraer.com, v2.dev.api → dev.api.caraer.com)
and are not proxied through Cloudflare.
caraer profile list
caraer profile use staging
caraer profile set --base-url https://api.caraer.com --output json
--profile <name> overrides the active profile for a single command.
Sandboxes
A sandbox clones the selected company's Neo4j database. The company stays the same. Each company can have at most 3 active sandboxes.
caraer company select <company-uuid>
caraer sandbox create --name my-test
caraer sandbox use <sandbox-uuid>
caraer sandbox clear
Sandboxes isolate Neo4j data. Function runtime code is still the deployed
build. Preview a push with caraer apps push --dry-run before you deploy.
Command groups
auth,company,profile— session and which API you talk toapps— scaffold, validate, push, logs, local dev, delete (private apps)webhooks— formats, events, and test helperspublish— marketplace review for public appssandbox— Neo4j clone of the selected companyskill— install the Cursor agent skills shipped with the CLI
Further reading
- Serverless functions
- CMS modules
- Webhooks
- App lifecycle hooks
- Scheduled functions
- Inbound routes
- Platform versioning
- Backend contract
- Changelog
- Security
- Agent skills:
skills/caraer-apps,skills/caraer-cms
License
Proprietary — see LICENSE.
Metadata
Release files for caraer-cli 0.1.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| caraer_cli-0.1.8.tar.gz | 362.8 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| caraer_cli-0.1.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 633.8 kB
Release files / caraer_cli-0.1.8.tar.gz
| Download URL | caraer_cli-0.1.8.tar.gz |
|---|---|
| Size | 362.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8fe0387c6ec8a6bd5b0439779d20cf88304a21119993f159534d9fc6ef741873
|
|
BLAKE2b-256 checksum How to use checksums |
ca2387edd1533ffeb4432d359854586aebe0dcd120464ef777f1c2548a5e0e80
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / caraer_cli-0.1.8-py3-none-any.whl
| Download URL | caraer_cli-0.1.8-py3-none-any.whl |
|---|---|
| Size | 271.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1a9c54bf351b7d6ce25543cf96510f1ddca9a7b114fe51fe2430eee8b0db9578
|
|
BLAKE2b-256 checksum How to use checksums |
c8f99980ddab8e0f2fef049ecff6c69d95f47fcd116016f3ddc33cd871f45423
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for caraer-cli 0.1.8
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.