# Buffer CLI

Schedule posts, manage channels, and access account data directly from your terminal. Built for developers and AI agents.

Every command is generated from Buffer’s public GraphQL schema, with structured JSON output and predictable error handling, making it easy to integrate into scripts, CI pipelines, and agent tooling.

The CLI ships with markdown skill files for Claude Code and Codex, allowing AI agents to interact with Buffer without requiring custom prompts or manual setup.


## Install the CLI

Install the CLI and verify the version. Requires Node.js 18 or later.

```bash
npm install -g @bufferapp/cli
buffer --version
```

## Quick start

### 1. Run interactive setup

`buffer init` writes your API token, default organization, and timezone to the global config. It also offers to install a Buffer skill into Claude Code or Codex.

```bash
buffer init
```

> Don't have an API key? See [Authentication](authentication.html) for how to generate one.

### 2. Verify your environment

`buffer doctor` checks your Node version, config, token, and network access.

```bash
buffer doctor
```

### 3. Run your first command

Fetch your account, then list your connected channels.

```bash
buffer account
buffer channels list
```

If you prefer not to persist a token to disk (CI, containers, ephemeral environments), skip `buffer init` and export `BUFFER_API_KEY` instead:

```bash
export BUFFER_API_KEY=your-token-here
```



## Use with AI agents

The CLI ships markdown skill files (workflows, pitfalls, rate limits, idempotency) designed to be loaded into an AI agent's context window.

```bash
# Print all topics as concatenated markdown
buffer context

# Or list available topics
buffer context --list
```

Install the skill into your agent so it can call the CLI without a custom system prompt:

```bash
buffer install claude   # writes ~/.claude/skills/buffer/SKILL.md
buffer install codex    # appends a managed block to ~/.codex/AGENTS.md
```

Both targets are idempotent — re-running keeps the file current. Reverse with `buffer uninstall <agent>`. No API call, no auth required.

## Core commands

Every command follows the same shape: `buffer <group> <command> [flags]`. You can run the help command to get the information about supported commands.

```bash
buffer --help
```



### Account & channels

```bash
buffer account
buffer channels list
buffer channels get --id <channel-id>
```

### Posts

```bash
# List posts on a channel
buffer posts list --channel-id <channel-id>

# Get a single post
buffer posts get --id <post-id>

# Create a post with flags
buffer posts create \
  --channel-id <channel-id> \
  --scheduling-type automatic \
  --mode addToQueue \
  --text "Hello from the CLI"

# Or pass the input as JSON
buffer posts create --json '{
  "channelId": "...",
  "schedulingType": "automatic",
  "mode": "addToQueue",
  "text": "Hello"
}'
```

Input can also come from a file or stdin:

```bash
buffer posts create --input post.json
cat post.json | buffer posts create --input -
```

### Ideas

```bash
buffer ideas create --organization-id <org-id> --text "Idea body"

buffer ideas create --json '{
  "organizationId": "...",
  "content": { "text": "Idea body" }
}'
```

### Dry run

All mutations support `--dry-run`. The CLI validates input locally and prints the payload that _would_ be sent, without calling the API.

```bash
buffer posts create --json '{"channelId": "abc"}' --dry-run
```

## Field selection

Each command ships with a curated default field set so responses stay small. Use `--fields` to override it with a comma-separated list of dot-notation paths — the CLI builds a minimal GraphQL request from those paths so the API only returns what you ask for.

```bash
# Default subset (small, still useful)
buffer posts get --id post_123

# Cherry-pick fields, including nested paths
buffer posts get --id post_123 --fields id,text,channel.name

# Connections expose items.* and pageInfo.*
buffer posts list --fields items.id,items.text,pageInfo.endCursor

# Brace expansion for sibling fields. Quote it so the shell
# doesn't expand the braces before the CLI sees them.
buffer posts list --fields 'items.{id,text,status},pageInfo.endCursor'

# Opt back into the full response
buffer posts get --id post_123 --fields all
```

## Schema introspection

The CLI is generated from the GraphQL schema, so you can discover commands and validate payloads at runtime.

```bash
buffer schema list
buffer schema describe posts create
```

`buffer schema describe` returns a full method signature as JSON — input types, output shape, required fields, enum values.

## Global flags

| Flag | Purpose |
| --- | --- |
| `--output <json\|pretty\|auto>` | Rendering. `auto` pretty-prints to a TTY, JSON otherwise. Use `json` for scripts and agents. |
| `--quiet` | Suppress spinners, completion lines, update notices, and rate-limit warnings on stderr. |
| `--verbose` | Print a one-line rate-limit summary to stderr after every request. |
| `--no-color` | Disable ANSI colors in pretty output. |
| `--timeout <ms>` | Per-command timeout (default 30000ms). `0` disables. |
| `--dry-run` | Validate locally and print the payload that would be sent. Mutations only. |

## Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Success |
| `1` | General error |
| `2` | Usage error (bad flags, missing fields, validation failure) |
| `3` | API error |
| `4` | Auth error (missing or invalid token) |
| `130` | Interrupted by SIGINT (Ctrl-C) |
| `143` | Terminated by SIGTERM |

When stdout is closed by the consumer (`buffer ... | head`), the CLI exits `0` silently instead of printing an EPIPE stack trace.

## Configuration

The CLI reads config from two files. Repo config overrides global config per key.

| Scope | Path | Notes |
| --- | --- | --- |
| Global | `$XDG_CONFIG_HOME/buffer/config.json` (or `~/.config/buffer/config.json`) | User-level defaults. Only place `apiKey` can be stored. |
| Repo | `.buffer/config.json` (walking up from the cwd) | Project-level overrides. `apiKey` is stripped on load. |

```bash
# Inspect
buffer config get --all
buffer config path

# Write (defaults to global; use --repo for repo-scoped)
buffer config set outputFormat pretty
buffer config set timeout 60000

# Remove (idempotent)
buffer config unset outputFormat
```

Resolution order for any value: command flag → environment (`BUFFER_API_KEY` for `apiKey`) → repo config → global config → built-in default.


## Shell completion

```bash
buffer completion bash --install
buffer completion zsh  --install
buffer completion fish --install
```

`--install` appends a sourcing block to `~/.bashrc` or `~/.zshrc` (idempotent); for fish it writes to `~/.config/fish/completions/buffer.fish`. Restart your shell to pick it up.

## Troubleshooting

Run `buffer doctor` to diagnose setup issues. It checks Node version, config validity, API token, default organization, network reachability, rate-limit headroom, and CLI version freshness.

```bash
buffer doctor            # only failing checks
buffer doctor --verbose  # include passing checks
```
