Skip to content

CLI Reference

Every command reads .env in the current directory automatically (never clobbering variables already set in your shell), and most read [deploy] in cordless.toml for defaults. Flags always win over cordless.toml, which wins over environment variables.

Every command also accepts an environment name (via --environment/-E, --env, or the $ENV variable), which loads .env.<name> over .env, so environment-specific keys win while everything else in .env still applies. See Environment variables for the full picture.

Scaffolds lambda_function.py, cordless.toml, and .env.example in the current directory. name sets the function value in the generated cordless.toml (defaults to the current directory’s name). Skips any file that already exists rather than overwriting it.

Asks how Discord should reach your bot: a direct Lambda Function URL (default, lower latency, no custom domain support) or an API Gateway HTTP API (needed if you want a custom domain). This is a required question when run interactively; pass --endpoint api_gateway or --endpoint function_url to skip the prompt, which is also required for non-interactive use (scripts, CI).

Runs your bot locally with hot reload. bot is MODULE:ATTRIBUTE (auto-detected from cordless.toml or by scanning source files if omitted).

Flag Default
--port, -p 8787 Local port to listen on
--source, -s . Project directory
--no-tunnel off Serve on localhost only, skip the cloudflared public tunnel
--environment, -E, --env $ENV Loads .env.<NAME> over .env

Deferred (defer=True) handlers run in-process on a background thread rather than invoking a real worker Lambda, so the whole flow, including file attachments, works without deploying anything.

Runs a single @bot.cron(...) handler locally by name, without waiting for its EventBridge schedule. bot is auto-detected if omitted.

Terminal window
cordless cron daily_rewards
Flag Default
--source . Source directory
--environment, -E, --env $ENV Loads .env.<NAME> over .env

Pushes your slash commands to Discord.

Flag Default
--token $DISCORD_BOT_TOKEN Bot token
--client-id $DISCORD_CLIENT_ID App client id (OAuth2 client-credentials auth)
--client-secret $DISCORD_CLIENT_SECRET App client secret
--guild-id $DISCORD_GUILD_ID Register to one guild instead of globally (instant, no propagation delay)
--environment, -E, --env $ENV Loads .env.<NAME> over .env before resolving the above

Authenticate with a bot token, or with --client-id/--client-secret via OAuth2 client credentials. The latter needs no bot user at all, which suits apps that only ever respond to HTTP interactions. If both are given, the bot token wins.

Omit --guild-id and each command registers to its own scope: global by default, or whichever guild(s) it named via guild_ids= on its decorator. Passing --guild-id overrides that and pushes every command to just the one guild, for instant updates during development.

Packages your source, publishes the cordless Lambda layer, creates or updates your function(s), wires a Function URL or API Gateway (whichever endpoint resolves to), and (if your bot has @bot.cron handlers, or keep-warm is set) wires EventBridge. See Deploying to AWS for the full walkthrough and the complete cordless.toml reference.

Flag cordless.toml key Default
--function, -f function - Lambda function name (required)
--source, -s - . Source directory to package
--role-name role_name <function>-role IAM role name to create or reuse
--handler handler lambda_function.handler Handler string
--runtime runtime python3.12 Lambda runtime
--layer-name layer_name cordless Cordless layer name
--region, -r region $AWS_DEFAULT_REGION AWS region
--environment, -E - $ENV Loads .env.<NAME> over .env
--env KEY=VALUE or --env NAME [deploy.env] - Environment variable (repeatable), or a bare name to pick .env.<NAME> like --environment
--timeout timeout 10 Main Lambda timeout, seconds
--setup MODULE:FUNCTION setup - Run a no-argument setup function locally before deploying (e.g. db:create_tables)
--bundle-cordless bundle_cordless false Embed local cordless source in the zip instead of using a Lambda layer
--defer-worker NAME defer_worker - Worker Lambda name for deferred commands
--defer-handler defer_handler lambda_function.worker_handler Worker handler string
--defer-timeout defer_timeout 30 Worker Lambda timeout, seconds
--architecture architecture arm64 for a new function, unchanged for an existing one x86_64 or arm64
--endpoint endpoint function_url for a new function, unchanged for an existing one function_url or api_gateway (needed for a custom domain)
--register - off Also push slash commands to Discord after deploying

--setup runs locally, with your own AWS credentials, before packaging or touching Lambda, useful for one-time provisioning like creating a DynamoDB table that your bot’s code assumes already exists.

Publishes a fresh cordless Lambda layer and attaches it to an existing function, without repackaging or redeploying your code. Handy right after bumping the cordless version, when your function code hasn’t otherwise changed.

Flag Default
--function, -f - Lambda function name or ARN (required)
--layer-name cordless Layer name
--region, -r - AWS region
--runtime python3.12 Lambda runtime the layer targets

Unlike deploy, which reuses an existing layer version if the cordless version and Python version already match, upload always publishes a new layer version.

Tails CloudWatch logs for a deployed function.

Flag Default
--function, -f function in cordless.toml Lambda function name
--worker off Tail the worker Lambda instead (defer_worker in cordless.toml)
--region, -r $AWS_DEFAULT_REGION AWS region
--follow off Keep tailing, like tail -f
--since MINUTES 10 How far back to start
Terminal window
cordless logs --follow
cordless logs --worker --since 60

Read-only diagnostics for AWS credentials, the IAM role, Discord app config, and deployed function state. bot is MODULE:ATTRIBUTE (auto-detected if omitted) - only needed so cron rule targets can be checked against your @bot.cron handlers.

Flag Default
--function, -f function in cordless.toml Lambda function name
--role-name <function>-role IAM role name
--region, -r $AWS_DEFAULT_REGION AWS region
--environment, -E, --env $ENV Loads .env.<NAME> over .env
Terminal window
cordless doctor

Runs section by section (AWS → Discord → IAM → Lambda), printing each section’s checks as it finishes rather than one silent wait followed by a dump at the end. Each check reports ✓ (ok), ⚠ (warning), or ✗ (fail).

Works incrementally: run it right after cordless init, before anything is deployed, and it checks AWS credentials and Discord app config only, skipping the IAM and Lambda sections with an informational note instead of failing. Once deployed, it also verifies the function (and worker, if configured) are Active, the endpoint (Function URL or API Gateway) is wired correctly, cron rules target the right function, the keep-warm rule (if enabled) is present, and the deployed function’s environment variables match your local config - reporting only presence and match/mismatch for secret-shaped keys (DISCORD_BOT_TOKEN, DISCORD_CLIENT_SECRET, DISCORD_PUBLIC_KEY), never the actual value.

Exits nonzero if any check comes back failing (warnings alone don’t), so it doubles as a CI gate - run it after cordless deploy to catch a misconfigured endpoint or a stale env var before it becomes an incident.

Deletes everything deploy created: the function(s), its endpoint (Function URL or API Gateway, whichever is in use), cron rules, the keep-warm rule (if any), CloudWatch log groups, and the IAM role. If ratelimit = true is still set in cordless.toml, the rate-limit DynamoDB table is deleted too. Prompts for confirmation unless --yes is passed.

Flag Default
--function, -f function in cordless.toml Lambda function name
--role-name <function>-role IAM role name
--region, -r $AWS_DEFAULT_REGION AWS region
--defer-worker NAME - Also delete this worker Lambda
--layer [NAME] - Also delete the cordless Lambda layer (defaults to layer_name in cordless.toml, or cordless)
--yes, -y off Skip the confirmation prompt
Terminal window
cordless destroy --yes --defer-worker my-bot-worker --layer