# From curl to the Backlog CLI 'bee' — Making AI Agent Integration One Step Easier

> Source: <https://codenote.net/en/posts/backlog-cli-bee-for-ai-agents/>
> Published: 2026-08-04 14:43:59+00:00

Last time, in [Issuing a Backlog API Key to Drive It from AI Agents](https://codenote.net/en/posts/backlog-api-key-for-ai-agents/), I walked through issuing a Backlog API key and letting Claude Code or Codex hit the REST API through curl. It works, but once you actually live with it, small frictions pile up:

- Even if the API key sits in an environment variable, it still shows up as
`apiKey=...`

in the URL query, and that leaks into command history and shared scripts - The response is raw JSON, so before handing it to the agent I keep re-deciding whether to pipe it through
`jq`

- Common lookups like “my open issues” force me to reassemble the endpoint and query parameters every time

A Nulab volunteer project has taken care of that abstraction layer: [bee](https://github.com/nulab/bee). This post is what I got out of putting it in front of my Backlog + AI-agent setup.

## What bee Is

In one sentence, [bee](https://github.com/nulab/bee) is [GitHub CLI](https://cli.github.com/) (`gh`

) for Backlog. It exposes Backlog’s core resources (projects, issues, wikis, notifications, the dashboard) through a `gh issue list`

-style command surface.

One important caveat: bee is not an officially supported Nulab product. As the [README](https://github.com/nulab/bee) itself calls out, it is volunteer-maintained OSS ([MIT licensed](https://github.com/nulab/bee/blob/main/LICENSE)). That said, it is driven by Nulab folks, and it goes through the same [official Backlog REST API](https://developer.nulab.com/docs/backlog/) I described last time, so the auth story does not change. The previous conclusion, “run an agent-only Backlog user and issue an API key for it,” carries over directly onto bee.

## Install and First-Time Auth

bee ships as an npm package and requires [Node.js](https://nodejs.org/) 20.18 or later.

First-run auth is per space. Both browser-based OAuth and the API key from the previous post work; for agent use, the API key path is usually the easier fit.

If you juggle multiple Backlog spaces, `bee auth switch`

flips the active one. Once auth is in place, every other subcommand picks up the credentials implicitly.

## How bee Changes the Agent Story

The biggest shift versus raw curl is that the API key stops showing up on the command line. bee’s credentials live in a local config file, so any shell command handed to Claude Code or Codex no longer needs `apiKey=xxx`

in it. The structural risk of an API key leaking into an agent prompt or shell history drops sharply.

The second shift is output handling. The default output is human-readable, but most subcommands accept `--json`

and return machine-readable JSON. Even if you still let the agent parse the output, the shape is far more stable than hand-rolled REST.

For the times you still want raw REST (poking at a newer Backlog endpoint, say), `bee api <endpoint>`

lets you hit any endpoint while reusing the stored credentials. Safer than a fresh curl one-liner, and shorter.

## Common Use Cases

The subcommands listed by `bee --help`

(`auth`

, `project`

, `issue`

, `document`

, `notification`

, `pr`

, `repo`

, `team`

, `user`

, `wiki`

, `category`

, `milestone`

, `issue-type`

, `space`

, `status`

, `star`

, `watching`

, `dashboard`

, `browse`

, `api`

, `completion`

) map almost one-to-one onto Backlog’s resources. The operations you actually want an agent to do usually fall inside that list.

For a “what is on my plate” glance across notifications and issues, one line is enough:

To inspect a single issue, pass the Backlog issue key directly:

Creating an issue or leaving a comment reads much like `gh issue create`

:

Wiki reads stay in the terminal too:

## The Gotcha: `--status open`

Does Not Work

With all that said, the first thing I tripped over in production was `bee issue list`

’s status filter. GitHub-CLI reflexes make you want to write:

That does not work. bee’s `--status`

expects a numeric status ID, so passing `"open"`

fails with `Invalid type: Expected number but received NaN`

.

Backlog’s built-in statuses are `1 = Open`

, `2 = In Progress`

, `3 = Resolved`

, `4 = Closed`

. To get the equivalent of “open” (unfinished issues), pass `-S`

(status ID) multiple times:

`-a @me`

is a nice CLI-only shorthand for “issues assigned to me.” Projects can define custom statuses outside the standard four, so it is worth pinning down the IDs beforehand:

Watch the letter casing too. `-S`

is status ID and `-a`

is assignee, which diverges slightly from [the gh conventions](https://cli.github.com/manual/). If you plan to store agent prompts or snippets, templating this makes future you happier.

## Wrap-Up

Driving Backlog from AI agents already works on the “agent-only user + API key” approach from the previous post. Layering [bee](https://github.com/nulab/bee) on top of that keeps the API key off the command line, gives you structured output, and still lets you drop down to raw REST via `bee api`

when you need to.

bee is volunteer-maintained OSS from Nulab, not an officially supported product, so it should not be treated with the same expectations as a paid tool. But as a CLI it is polished, and it takes one clear step of friction out of AI-agent-driven Backlog operations. For now my baseline setup is “dedicated agent user + bee,” and I will keep an eye on both bee and Backlog’s own API-key implementation as they mature.

That’s all from moving off raw curl onto the Backlog CLI ‘bee’ and making AI agent integration one step easier, from the Gemba.
