Command-line interface for Flux project management.
brew install eyra/tap/flux-cliOr with Go:
go install github.com/eyra/flux-cli@latestThe binary carries the flux skill for AI coding agents. Install it for the agents you use:
flux install claude # Claude Code: ~/.claude/skills/flux (CLAUDE_CONFIG_DIR replaces ~/.claude)
flux install omp # omp: ~/.omp/agent/skills/flux (PI_CODING_AGENT_DIR replaces ~/.omp/agent)
flux install codex # Codex: ~/.agents/skills/fluxomp also reads ~/.agents/skills, so flux install codex makes the skill
available to omp too. A SKILL.md that differs from the installed version is
first backed up to SKILL.md.bak-<time>. A symlinked skill folder or file is
left alone, and the command fails.
flux update refreshes the skill for every agent that has one, from the
updated binary, even when the binary is already up to date; --no-skill skips
this. A symlinked skill is skipped. Rerun flux install after brew upgrade
or go install.
# List all issues
flux issues list
# Filter by stage
flux issues list --stage development
# JSON output
flux issues list --jsonflux issues get 12345Use --project <key> (for example flux, next or feldspar; flux projects list shows all) to scope the lookup. The default is
next on production and flux on test. An issue outside the selected project
returns an error.
flux auth status --env test --jsonStatus verifies the active credentials with the server, rather than trusting a local credential file. On success it returns:
{"signed_in":true,"env":"test","basecamp_account_id":"123","basecamp_person_id":"456","display_name":"Alex"}The Basecamp account and person IDs are strings identifying the signed-in
person. No tokens are returned.
Missing, invalid, or unverifiable authentication exits nonzero without success
JSON. Sign in with flux auth login; the CLI uses the selected environment's
saved credentials.
flux issues get <id> --project flux --json retains the thread array. Each comment
includes its display name as author and, when supplied by Basecamp, its stable
string person ID as author_id:
{"id":"789","author":"Alex","author_id":"456","date":"2026-10-06","content":"Comment text"}When the creator ID is unavailable, author_id is omitted or null, exactly as
the server sends it: --json output repeats the server's JSON and keeps every
field, including ref, epic, milestone, use_case and url. Names are not unique;
compare author_id with verified basecamp_person_id to identify the signed-in
person's comments, within the same Basecamp account. Do not derive identity from
the name.
Scenes and use cases live in a project's Product to-do set (Next Platform:
--project next). The model is Scene → Use Case → Issue:
- A scene (formerly "User Journey") is an actor-centred view of the system
with one angle and one zoom level. Code:
SC-<Area>-NN. - A use case works out part of a scene as a complete software design.
Code:
UC-<AREA>-NN. - An issue implements (part of) a use case.
An issue belongs to at most one use case, and a use case to at most one scene;
linking to another parent moves the child. A use case is optional on an issue:
bugs, chores and triage findings may have none. IDs may be Basecamp IDs or
codes: SC-Next-02 (SCN-Next-02 and legacy UJ-Next-02 work too) or
UC-NEXT-01, in any case and with or without leading zeros. Unnumbered drafts
use xx; a code that several items share fails with ambiguous_code and lists
the matching IDs, so use one of those Basecamp IDs.
# Scenes
flux scenes list [--completed]
flux scenes get SC-Next-02 [--no-thread]
flux scenes create --title "Donate data" --area Next [--code SC-Next-04] [--status Refine] [--description ...]
flux scenes update SC-Next-02 [--title ...] [--code ...] [--status none] [--description ...]
flux scenes comment SC-Next-02 --content "..."
flux scenes next-code --area Next # print the next free code, e.g. SC-Next-04
flux scenes usecases SC-Next-02 # use cases linked to the scene
flux scenes resync SC-Next-02 # refresh the linked use case titles
# Use cases
flux usecases list [--scene SC-Next-02] [--completed]
flux usecases get UC-NEXT-01 [--no-thread]
flux usecases create --title "Upload data" --area NEXT [--scene SC-Next-02]
flux usecases update UC-NEXT-01 [--title ...] [--code ...] [--status ...] [--description ...]
flux usecases comment UC-NEXT-01 --content "..."
flux usecases next-code --area NEXT # print the next free code, e.g. UC-NEXT-03
flux usecases link UC-NEXT-01 --target-type scene --target-id SC-Next-02
flux usecases unlink UC-NEXT-01 --target-type scene --target-id SC-Next-02
flux usecases issues UC-NEXT-01 # issues linked to the use case
flux usecases resync UC-NEXT-01 # refresh the linked issue titles
# Issues
flux issues create --title "..." --app web --usecase UC-NEXT-01 [--epic ...] [--milestone ...] [--context Dev]
flux issues update 12345 --context UC-NEXT-02 # sets the title's [UC-NEXT-02] prefix
flux issues list --context dev # issues with that title prefix
flux issues update 12345 --usecase UC-NEXT-02 # moves it; --usecase "" removes the link
flux issues link 12345 --target-type usecase --target-id UC-NEXT-01 [--unlink]issues create and issues update link the issue through --epic,
--milestone and --usecase after writing it, with the same link endpoint as
issues link. With --usecase, the command first reads the use case, so a
server without Scenes, a project without Product or an unknown use case fails
before anything is written. If a link still fails after the issue was created,
the command exits with "issue was created, but could not link …"; link it
with issues link rather than creating it again.
An issue's context is the bracketed prefix of its title: Dev in
[Dev] Fix login, UC-NEXT-01 in [UC-NEXT-01] Show the results. It used to
be called the program. --context on issues create and issues update sets
that prefix, replacing any existing one, issues list --context filters on it,
and issues get prints it as Context:. --program still works as a hidden,
deprecated alias of --context.
On create, the title gets --code, else the code it already starts with, else
the next free code in --area. --status is the name of a group in the list;
on update, --status none moves the item out of its group. Scenes and use cases
are completed by hand in Basecamp. A parent keeps a copy of each child's title:
run resync on it after renaming its children.
A project without a Product to-do set returns a product_not_configured error.
A server older than this CLI returns "not supported by this server".
The CLI calls /api/delivery for issues, milestones and epics, and
/api/product for scenes and use cases. Against an older server without
/api/delivery it falls back to /api/dev automatically.
Flux does not link epics to milestones. The old epics link and
milestones epics commands are removed; link issues with flux issues link
and list a milestone's issues with flux milestones issues.
Use optional --ai-model to declare which model generated text you supply:
flux issues comment 12345 --content "Investigated the failure." --ai-model "openai/gpt-5" --json
flux comments update 67890 --content "Updated findings." --ai-model "anthropic/claude-sonnet-4" --jsonSupported commands are issues, epics, milestones, scenes, and usecases
create, update
(for supplied descriptions), and comment; comments update; and
issues advance (for its optional --comment, not the automatic stage comment).
The flag is not global and is unavailable on reads, deletes, links, assignments,
resyncs, and other operations.
The CLI forwards the exact string as JSON ai_model, including provider/model
IDs, whitespace, and HTML-looking text. When omitted, the JSON field is omitted;
no model is inferred from credentials or environment. This is
caller-declared display metadata, not verified identity: it does not invoke or
select a model, change authentication, or change environment/project selection.
The server renders a single code-block footer, with only Flux and the model name bold and no italics:
- Without a model, or with an empty/whitespace-only value:
<pre>Assisted by <strong>Flux</strong></pre> - With
--ai-model "openai/gpt-5":<pre>Assisted by <strong>Flux</strong> · Generated with <strong>openai/gpt-5</strong></pre>
The server escapes model text as HTML and does not expand its @mentions.
Content edits replace the previous generated footer rather than accumulating
footers; editing content without a model removes its old model suffix.
Independent AI-disclosure text is retained. Metadata-only updates without a
description leave the historical content and model footer unchanged, even if
--ai-model is supplied. Advancing without --comment likewise attributes no
user text.
# Production (default) - every project's real backlog, including Flux's own
flux issues list --project flux
# Test environment - only for verifying the eyra-flux-test deployment
flux issues list --env testAn explicit --env takes precedence over FLUX_ENV, including --env prod when
FLUX_ENV=test. Without either, the environment is prod.
The CLI connects to:
- prod:
https://eyra-flux.fly.dev(default) - test:
https://eyra-flux-test.fly.dev
# Build
go build -o flux .
# Run
./flux issues list --env test
# Run against a local server
FLUX_BASE_URL=http://localhost:4040 ./flux auth login
FLUX_BASE_URL=http://localhost:4040 ./flux scenes list --project next