Configuration
Config file
bsky-cli supports a TOML config file for setting persistent defaults. This lets you avoid passing the same flags on every command.
The config file is located at the platform default config directory:
| Platform | Path |
|---|---|
| Linux | ~/.config/bsky-cli/config.toml |
| macOS | ~/Library/Application Support/bsky-cli/config.toml |
| Windows | %APPDATA%/bsky-cli/config.toml |
If $XDG_CONFIG_HOME is set, it takes priority: $XDG_CONFIG_HOME/bsky-cli/config.toml.
Creating the config file
bsky config init
This creates the config file with all available options documented and commented out. Uncomment any option to activate it.
Managing the config
# Print the config file path
bsky config path
# Print the config file contents
bsky config show
# Open in your editor ($EDITOR, falls back to vi)
bsky config edit
Using a custom config file
Override the config file path with -c / --config or the BSKY_CONFIG environment variable:
# Flag (highest priority)
bsky -c /path/to/config.toml timeline
# Environment variable
export BSKY_CONFIG=/path/to/config.toml
bsky timeline
Precedence for config path: -c flag > BSKY_CONFIG env var > default location.
Config file format
The config file uses TOML format. Global options go at the top, and each command has its own [section]:
# Global options
json = false
profile = "work"
verbose = false
# Per-command options
[create-thread]
thread-label = true
no-preview = true
[timeline]
count = 50
[schedule.list]
count = 10
order = "desc"
CLI flags always win
Any flag passed on the command line overrides the config file value. For example, if your config sets json = true, running bsky tl --no-json will still output plain text.
Full schema reference
Below is the complete config file with all available options and their defaults. All values are commented out by default — uncomment to activate.
# bsky-cli configuration
# CLI flags always override these values.
# Uncomment and modify options as needed.
# ── Global ──────────────────────────────────────
# json = false
# profile = ""
# verbose = false
# ── Commands ────────────────────────────────────
[post]
# stdin = false
# draft = false
[reply]
# draft = false
[quote]
# draft = false
[create-thread]
# stdin = false
# draft = false
# thread-label = false
# prepend-thread-label = false
# no-preview = false
# skip-validation = false
# media-all = false
[timeline]
# count = 30
[stream]
# pattern-flags = "gi"
[search]
# count = 100
[search-users]
# count = 100
[thread]
# count = 30
[notifs]
# all = false
[login]
# host = "https://bsky.social"
# bgs = "https://bsky.network"
[invite-codes]
# used = false
[mod-list]
# name = "NewList"
# desc = ""
[bookmarks.get]
# count = 50
[dm.list]
# count = 50
[dm.read]
# count = 30
[schedule.list]
# count = 5
# order = "asc"
[schedule.watch]
# interval = "* * * * *"
[schedule.enable]
# interval = 1
[schedule.post]
# stdin = false
Session data
Credentials and session tokens are stored separately from the config file, in the same config directory. Each profile gets its own session file.
The session directory is created automatically on first bsky login.
Environment variables
All configuration can be set via environment variables. This is useful for CI pipelines, scripts, and Docker containers.
| Variable | Description | Default |
|---|---|---|
BSKY_HANDLE |
Bluesky handle | — |
BSKY_PASSWORD |
App password | — |
BSKY_HOST |
PDS host URL | https://bsky.social |
BSKY_BGS |
BGS host URL | https://bsky.network |
BSKY_PROFILE |
Profile name | — |
BSKY_CONFIG |
Path to config file | — |
Example: CI pipeline
BSKY_HANDLE=bot.bsky.social BSKY_PASSWORD=my-app-password bsky post "Build passed!"
Example: Docker
docker run --rm \
-e BSKY_HANDLE=bot.bsky.social \
-e BSKY_PASSWORD=my-app-password \
bsky-cli post "Hello from Docker"
Precedence
When the same setting is configured in multiple places, the highest-priority source wins:
- CLI arguments (highest priority)
- Environment variables
- Config file (
config.toml) - Defaults (lowest priority)
For example, if your config file sets profile = "work" but BSKY_PROFILE=personal is in the environment, the environment variable takes precedence. And if you pass -p other on the command line, that wins over both.
Profiles
Profiles let you manage multiple Bluesky accounts from a single machine.
Create profiles
bsky login alice.bsky.social -p personal
bsky login bob.bsky.social -p work
Use a profile
bsky tl -p personal
bsky post "From work account" -p work
Set a default profile
Instead of passing -p every time, set a default in your config file:
profile = "work"
Or use the environment variable:
export BSKY_PROFILE=work
bsky tl # uses the "work" profile
List profiles
bsky -p ? tl