Symphony for Trello lets Codex work from Trello cards. Use it when prompts and terminal history are not enough, and you want a clear board that shows what Codex should do, what is running, and what is ready for review.
demo.mp4
Use it when you want to:
- Plan Codex work in Trello.
- Reuse an existing engineering board.
- Create a simple board just for Codex tasks.
- Let Codex pick up ready cards without starting each one by hand.
- Keep each card in its own local workspace.
- Have Codex comment on the card and move it to review when it is done.
- Check running and retrying work with
symphony-trello statusor the local status page.
Trello is still where you plan and review work. Codex still writes the code. Symphony connects them so the same workflow can run again and again.
You can use it with one board, or run it for several boards at the same time.
Symphony for Trello is a variant of OpenAI's Symphony adapted
for Trello. The original Symphony spec uses Linear; this project keeps the same orchestration idea
and maps it to Trello boards, lists, and cards. In Trello, a list is the board column that contains
cards, for example Ready for Codex or In Progress.
Symphony for Trello is an independent project. It is not affiliated with, endorsed by, or sponsored by OpenAI, Atlassian, or Trello.
Symphony for Trello is preview automation for trusted environments. Start with a disposable board or a small low-risk project, then expand once the workflow matches how you review and merge work.
Use the installer for the shortest path to a working local board. It installs Symphony for Trello, checks the required tools, runs guided setup, and starts the local worker.
macOS, Linux, and Windows through WSL2:
curl -fsSL https://symphony-trello.fmartin.ch/install.sh | bashFor Windows, WSL2 is recommended. Run the Linux installer inside WSL2. Native Windows PowerShell is best effort; see Installer Reference.
Follow the prompts. When setup finishes, create a Trello card and move it to Ready for Codex.
Symphony should move the card to In Progress, add or update one ## Codex Workpad Trello comment
with what Codex is doing, then move the card to the next review, blocked, merge, or done list when
the workflow says to.
If the card does not move or the workpad comment does not appear, run symphony-trello status and
symphony-trello logs. For issue reports, see Operations.
- You put a Trello card in a configured active list such as
Ready for Codex. - Symphony polls the board, claims the next eligible card, and creates a local workspace for it.
- Symphony starts the Codex CLI in app-server mode inside that workspace.
- Codex receives the
WORKFLOW.mdprompt with the card title, description, comments, and routing rules. - Codex works in the workspace, keeps one
## Codex Workpadcomment current, and moves the card toIn Progress,Human Review,Blocked,Merging, orDonewhen the workflow says to. - Symphony keeps the same Codex session going while the card remains active, then stops when the card reaches a review, blocked, terminal, or otherwise inactive list.
- You check running and retrying cards with
symphony-trello status, the local status page, or JSON API.
- Quick Start
- How It Works
- What You Get
- Trello Setup
- Using Symphony Day To Day
- Installer Reference
- Advanced Setup
- Workflow Contract
- Advanced Configuration
- Operations
- Safety Posture
- Building 1.0.0 by the Numbers
- Contributing and Security
All Symphony for Trello features work with Trello's Free plan.
- Guided local setup that can create a Trello board for you or connect an existing board.
- A repeatable Trello flow from
Ready for Codexto active work, human review, blocked, merge, and done lists. - One local workspace per Trello card so Codex work is separated by task.
- Optional GitHub pull request flow for repository-changing work.
- Trello comments that show progress, blockers, validation, and handoff notes on the card.
- Scoped Trello tools let Codex comment on, update, and move its current Trello card without access to the Trello API credentials. Symphony performs permitted Trello operations on Codex's behalf and enforces the configured write controls.
- A local worker status page and JSON API for running, retrying, blocked, and finished work.
- Configurable workflow files for board lists, workspace paths, Codex settings, concurrency, and safe local file access.
Trello has three concepts that matter for Symphony:
- A Workspace groups boards and is also where Trello lets you create a custom Power-Up for API access.
- A Board is the project or queue Symphony polls.
- Lists are the board columns that contain cards.
WORKFLOW.mdand tool fields use names likeactive_list_ids,allowed_move_list_names,list_id, andlist_name.
Symphony reads cards, creates local Codex workspaces, and runs Codex. When GitHub integration is
configured, the generated workflow tells Codex to commit the change, create or update a pull request,
leave a Trello handoff comment, and move the card to Human Review when the PR is ready for a
person. Without GitHub integration, the workflow stays local/non-GitHub and does not create the
GitHub-specific Merging list.
When several active Trello lists have cards, Symphony handles later workflow lists first, such as
Merging before In Progress before Ready for Codex, then uses priority labels and Trello card
position within the same list.
Start with the browser setup below. Those steps create the Trello credentials used by both board setup paths.
Complete these browser steps once before creating the recommended board or importing an existing
board. Symphony can create boards and write WORKFLOW.md, but Trello requires you to create the
Workspace and authorize the API token in the browser.
-
Sign in to Trello in your browser.
-
Create a Workspace if you do not already have one that you want to use with Symphony.
The Workspace owns the Trello app/admin entry that provides the API key. If you create a new board with Symphony, the board is created in this Workspace. If you import an existing board, the token you generate here must be able to access that board. It is fine to use a Workspace that also contains non-Symphony boards; Symphony only polls the board configured in
WORKFLOW.md. Create a separate Workspace when you want cleaner separation of automation credentials, collaborators, or boards. -
Open the Trello apps administration page.
-
If Trello asks you to accept or complete a developer agreement before creating an app, complete that browser flow.
-
Click
Newto create a new app/admin entry for the Workspace. -
Fill the required fields with clear, recognizable values:
Name:Symphony for Trello AutomationWorkspace: the Workspace you created or chose aboveEmail/Support Contact: an email you controlAuthor: your name or your team nameiframe Connector URL: leave this blank. Symphony only needs REST API credentials and does not need a board-enabled Power-Up UI.
-
Create the app/admin entry.
-
Open its
API Keytab and chooseGenerate a new API Key. -
If Trello warns that generating a key replaces the API key used for Personal Data Storage and GDPR compliance, continue when this is the new
Symphony for Trello Automationapp/admin entry. For an existing app already used elsewhere, rotating the key means those uses must be updated. -
Copy the API key somewhere temporary. The API key identifies the app, but the token is the sensitive credential.
-
On the same API key page, click the
Tokenlink below the key. -
Review the authorization screen. Confirm it shows
Symphony for Trello Automation, your Trello account, and permissions to make comments and create or update cards, lists, boards, and Workspaces. -
Click
Allow. -
Copy the generated token. Treat it like a password: it grants access as your Trello account to boards and Workspaces your account can access.
-
Save both values in the
.envfile read by the command you will run:- Fresh installed
symphony-trellocommand on normal Linux, macOS, or WSL2:$HOME/.config/symphony-trello/.env. - Existing default installs upgraded from the older single-home layout keep using the path from
their install context, usually
$HOME/.local/share/symphony-trello/config/.env. - Custom installs use the selected
SYMPHONY_HOMEorSYMPHONY_TRELLO_CONFIG_DIRconfig path. - Installed
symphony-trellocommand on MicroOS-like systems where the installer chose the/varlayout:/var/lib/symphony-trello/users/<user>/config/.env. - Source checkout with Maven: the project-root
.env.
- Fresh installed
TRELLO_API_KEY=replace-with-generated-key
TRELLO_API_TOKEN=replace-with-generated-tokenUse this path when you are new to Trello or want Symphony to create a clean Inbox -> Ready for Codex -> In Progress -> Blocked -> Human Review -> Merging -> Done board for you. One
command creates the board, creates the recommended lists, and writes a workflow file for that
board. This direct command keeps the GitHub PR flow enabled by default. Use setup-local or pass
--no-github when you want a local/non-GitHub workflow without Merging.
Now create the board and workflow:
symphony-trello new-board --name "Symphony Work Queue"When this board is for one repository, save its clone URL during setup:
symphony-trello new-board --name "Symphony Work Queue" \
--repository-url https://github.com/OWNER/REPO.gitFor a non-GitHub board:
symphony-trello new-board --name "Symphony Work Queue" --no-githubIf your token can access exactly one Workspace, Symphony uses it automatically. If your token can
access multiple Workspaces, the command stops and asks for --workspace-id. Show the available ids:
symphony-trello list-workspaces
symphony-trello new-board --name "Symphony Work Queue" --workspace-id workspace-id-from-list-workspacesThe command creates this Trello board layout:
InboxReady for CodexIn ProgressBlockedHuman ReviewMergingDone
It also writes a workflow that:
- Dispatches from
Ready for Codex,In Progress, andMerging. - Treats
Doneas the terminal list. - Lets Codex move cards to
In Progress,Human Review,Blocked, andDone. - Uses
./workspacesas the local workspace directory. - Chooses a stable HTTP status port.
- Sets
max_concurrent_agents: 1, so Symphony starts one card at a time from this board.
With --no-github, Merging is not created. The active lists are Ready for Codex and
In Progress, and the workflow does not require PR publication or merging.
During guided setup-local, --no-in-progress can create a local board without In Progress; in
that case picked-up cards stay in the active list until they move to review or blocked.
The first run writes WORKFLOW.md. If that file already exists and you did not pass --workflow,
Symphony keeps the existing file and writes a board-specific file instead. For a board named
My Project, the next file is WORKFLOW.my-project.md. If that file also exists, Symphony adds a
number, such as WORKFLOW.my-project-2.md. Very long board-name slugs are shortened with a stable
hash so the generated workflow file name stays filesystem-safe. Symphony also chooses the first
unused status port from 18080, 18081, 18082, and so on by checking other workflow files in the
same folder. Use --server-port when you want to choose the port yourself.
Pass --force only when you intentionally want to replace the selected workflow file:
symphony-trello new-board --name "Symphony Work Queue" --forceStart Symphony with the command printed under Next after the file is generated. It looks like
this:
symphony-trello start --env .env --workflow WORKFLOW.mdUse the generated board like this:
- Put raw ideas or incomplete tasks in
Inbox. - Move only cards that are ready for agent work into
Ready for Codex. - Symphony starts Codex for cards in
Ready for Codex. - Symphony moves the card to
In Progressbefore Codex starts, so the board shows active work. - Codex works in a local workspace, creates or updates a pull request for repository-changing work,
adds a Trello comment with its summary and verification notes, and moves the card to
Human Reviewwhen the PR is ready for human review. - If PR checks fail because of the card's changes or current branch, Codex keeps the card in
In Progress, reruns the failing check or closest local equivalent, fixes reproducible failures, pushes again, and repeats the review sweep. If the related CI failure passes locally and looks flaky, Codex can move the card toHuman Reviewwith that caveat. If CI cannot run, Codex runs equivalent local CI checks. If CI fails for a clearly unrelated reason, Codex does not try to reproduce that unrelated failure locally; it explains why the failure is unrelated in the Trello comment. - If Codex cannot safely finish the work, it adds a blocker comment and moves the card to
Blockedso the problem is visible from the board. - If changes are needed, a human moves the card from
Human Reviewback toReady for Codex. Codex treats that as rework: it rereads the updated card, new Trello comments, the existing workpad, and linked PR feedback before changing code again. It normally updates the existing PR instead of starting over. - If the work is accepted and should be merged by Codex, a human moves the card to
Merging. Codex treatsMergingas the approval signal, runs the merge helper skill, checks PR feedback and CI, resolves addressed GitHub review threads when GitHub allows it, follows the repository's merge policy, and moves successfully merged work toDone. - If you merge outside Codex instead, move the card to
Doneyourself after the work is accepted and merged.
Use this path when you already have a Trello board and want Symphony to write a starter
WORKFLOW.md for that board.
- Copy the board short link from the board URL.
In
https://trello.com/b/SYNTH001/my-board, useSYNTH001. - Run the import command:
symphony-trello import-board --board SYNTH001 --active "Ready for Codex" --in-progress "In Progress" --terminal Done --blocked BlockedAdd --repository-url URL when every card handled by the imported workflow normally belongs to the
same repository. Omit it to keep the workflow repository-general.
Add --no-github when the imported board should not use GitHub PR publication or merging:
symphony-trello import-board --board SYNTH001 --active "Ready for Codex" --in-progress "In Progress" --terminal Done --blocked Blocked --no-githubYou may omit list options when the board already uses the default list names:
- Omit
--activewhen the board hasReady for Codex. - Omit
--in-progresswhen the board hasIn Progress. - Omit
--terminalwhen the board hasDone. - Omit
--blockedwhen the board hasBlocked.
If your board has no in-progress list, Codex leaves picked-up cards in the active list until it moves
them to review or blocked. If your board has no blocked list, import falls back to the review handoff
list, so blocked cards still leave the active list. Create a blocked list or pass --blocked when
you want blocked work separated from reviewable work.
For an existing team board, be deliberate about --active: every open card in that list is eligible
for Codex work. A conservative import starts with a new list named Ready for Codex and only moves
cards there after they have a clear title, useful description, and acceptance criteria.
When the imported board has a list named Human Review, the starter workflow allows Codex to move
reviewable work there after it has created or updated a PR for repository-changing work. Boards that
still use a Review list remain supported when Human Review is absent. If there is no obvious
review list, the generated workflow keeps Trello writes disabled until you choose one. Do not run a
write-disabled workflow with blocked cards left in Ready for Codex unless you plan to move them
manually; they can be picked up again.
When the imported board has a list named Merging and a terminal list such as Done, the
starter workflow treats Merging as the human approval list for merging and allows Codex to move
merged work to the terminal list. Boards without Merging, or without a terminal list, still
work for implementation and human review; merging stays a manual step unless you add both lists to
the workflow.
Common setup command options:
--workflow PATH: write the generated workflow file somewhere other thanWORKFLOW.md. Use this when you want to choose the exact file name yourself. If that file exists, Symphony stops unless you also pass--force.--workspace-root PATH: choose where Symphony creates the local work directory for each Trello card. The generated workflow uses./workspaces; choose another path when you want those checkouts on a different disk or clearly separated from the repository.--repository-url URL: save the workflow's usual clone source inrepository.default_url.setup-local,new-board, andimport-boardaccept credential-free HTTP(S), username-onlyssh://, SCP-style SSH, andfile://URLs without query strings or fragments. Setup validates the URL format locally; it does not contact the repository.--server-port PORT: choose the HTTP status port written into the generated workflow. Use a port from1024through65535. If you omit it, Symphony uses the first unused workflow port starting at18080.--max-agents N: choose how many cards from this board are processed concurrently. Guided setup asks about this when you do not pass the option. Keep1until your machine can run several Codex sessions, builds, tests, package installs, and network calls at once. If cards depend on other cards, add prerequisite checklist items before moving them intoReady for Codex.--codex-model MODEL: write a Codex model into generated workflows without prompting. Omit it during guided setup to accept or edit the recommended model interactively.--codex-reasoning-effort EFFORT: write a Codex reasoning effort into generated workflows without prompting. When the selected model advertises supported efforts, the value must exactly match one of them; setup reports the accepted values when it rejects a choice. If the model does not advertise an effort list, the value remains a pass-through Codex setting.--force: replace an existing workflow file. Use this only when you are fine losing the current generated workflow content.--keyand--token: pass Trello credentials directly for this one command instead of reading them from.envor environment variables.--workspace-id ID: choose the Trello Workspace for a new board when your token can access more than one Workspace.--active NAME: duringimport-board, choose an exact Trello list name that Symphony may poll for ready work. Repeat--activefor multiple active lists.--terminal NAME: duringimport-board, choose an exact Trello list name that means work is done. Repeat--terminalfor multiple terminal lists.--in-progress NAME: duringimport-board, choose the Trello list where Codex should move a card immediately after it is picked up. If you omit it, import usesIn Progresswhen the board has that list. If no in-progress list is configured, the card stays in the active list while Codex works.--no-in-progress: during guidedsetup-localorimport-board, do not configure pickup moves even when the board has anIn Progresslist. For a new guided local board, theIn Progresslist is not created.--blocked NAME: duringimport-board, choose the Trello list where Codex should move cards it cannot safely finish. If you omit it, import uses a list namedBlockedwhen the board has one.
This section explains the board features you use after setup. It does not cover every configuration possibility; use Advanced Configuration when you need to change how the workflow is wired.
The recommended board gives you a simple flow:
Inbox: collect ideas, rough tasks, and notes that are not ready for Codex yet.Ready for Codex: put cards here when they have enough context for Codex to start.In Progress: Symphony moves a card here when Codex is actively working on it.Blocked: Codex moves a card here when it cannot safely continue without a human or environment fix.Human Review: Codex moves work here when it is ready for a person to review. If you find something that needs more work, comment on the Trello card or on the linked PR, then move the card back toReady for Codex.Merging: move a reviewed card here when you want Codex to do final checks and merge the pull request.Done: finished work. For PR-based work, Codex moves the card here after you move it toMergingand the PR merges successfully. For work that does not need a PR, move it here after human review is complete.
For a normal coding task, write the Trello card like you would write a clear issue or a prompt you
would normally send to a coding agent. Include the goal, important constraints, what should not
change, and how you expect the result to be verified. Then move the card to Ready for Codex.
Symphony picks it up, moves it to In Progress, gives Codex the card title, description, comments,
and workflow instructions, and keeps the card visible on the board while work is running.
Codex keeps one Trello comment named ## Codex Workpad up to date. The workpad is the best place to
look while a card is running: it should say what Codex is doing, what it has learned, what remains,
and whether it is blocked. Symphony updates that same comment instead of creating a long stream of
progress comments.
Use normal Trello checklists when one card must wait for another. Add a checklist such as
Must finish first; the checklist name is only for people. Put one bare Trello card reference in
each prerequisite item, for example https://trello.com/c/abc123. Symphony waits until each linked
card is in a list that this workflow treats as finished, such as Done. It keeps the checklist
checkmarks in sync and keeps one waiting comment on the blocked Trello card.
Keep related Trello card links out of prerequisite checklists, or write them as Markdown links such
as related to [the API card](https://trello.com/c/abc123). A bare Trello card link with extra text,
such as Wait for https://trello.com/c/abc123, is unclear and blocks until someone fixes the
checklist. Links in descriptions, Trello comments, attachments, and Markdown checklist links are
given to Codex as context. Codex can use them to notice likely missing prerequisites before it edits,
but those links do not block scheduling by themselves.
Use priority labels when one ready card should run before another. The default labels are p1,
p2, p3, p4, priority: critical, priority: high, priority: medium, and priority: low.
Within the same active Trello list, higher-priority cards run first. When priority is the same,
Trello card order decides. Configure this with
tracker.priority_labels.
With the default concurrency, Symphony works on one card per board at a time. That keeps review and
dependency ordering easy to understand. You can run several boards at once; each connected board has
its own workflow and worker. If you later raise per-board concurrency, make sure your machine can run
several Codex sessions and project test suites at the same time, and make sure the cards do not rely
on each other being completed in a specific order. Configure this with
agent.max_concurrent_agents and
agent.max_concurrent_agents_by_state.
If setup found an authenticated GitHub CLI, your workflow can include GitHub support automatically.
For repository-changing work, Codex can then create or update a pull request. Human Review means a
person should review the Trello result and the PR. If review feedback needs more work, write the
finding on the Trello card or, when there is a linked PR, on the PR. Then move the card back to
Ready for Codex. Codex treats that as rework, rereads the card, comments, workpad, PR feedback,
and checks, and normally updates the existing PR instead of starting over.
When every card in a workflow belongs to the same GitHub repository, set the workflow repository default once. Then cards do not need to repeat the repository URL.
Guided setup-local asks:
If this board is for one Git repository, enter its clone URL; press Enter for a general-purpose board:
Enter the clone URL to save it as repository.default_url, or press Enter to keep the workflow
repository-general. Non-interactive setup and the direct new-board and import-board commands use
--repository-url URL. Setup output names the generated workflow file where you can add or change
repository.default_url later; manual editing remains available for advanced cases.
In the workflow file front matter, set repository.default_url:
repository:
default_url: https://github.com/OWNER/REPO.git
default_path: nullUse the normal clone URL for the project. Generic Git remotes supported by the workflow contract are valid too; the repository does not have to be hosted on GitHub. Do not include credentials, query strings, or fragments.
With this setting, Symphony gives Codex fallback repository context for cards handled by the workflow. A card can override the workflow default when it clearly identifies a different repository. A labelled source line is the most explicit form:
Repository URL: https://github.com/OTHER-OWNER/OTHER-REPO.git
The effective order is: explicit card repository source, then one unambiguous repository identity
in ordinary card task context, then repository.default_url, then repository.default_path, then
no repository. For local repositories, use repository.default_path instead of
repository.default_url.
A selected source provides repository context. It does not make every card a repository-changing
task, and Codex should not create a checkout unless the card needs repository files. A fully
qualified GitHub issue or pull request URL remains its own direct API target, even when it names a
different repository. A full repository, issue, pull-request, or file URL, owner/repository, or
equivalent unambiguous card context supplies repository identity without requiring a special label.
Codex derives the normal credential-free clone URL from that identity only when the requested work
needs repository files. A selected remote URL also includes repository identity. For a selected local path
or file:// source, Codex uses a repository-relative issue or pull request reference only when
read-only inspection finds exactly one explicit, unambiguous compatible remote. Otherwise, Codex
blocks and requests a fully qualified repository URL together with the issue or pull request number.
It does not derive identity from the local path, directory name, or branch.
Codex validates an explicit selected source with a read-only probe before it works on the card. A workflow default is validated only when the card does not identify another repository. Validation does not create a checkout or write to the selected source. A malformed, unavailable, unreadable, or uncheckoutable selected source blocks the card even when the requested work would otherwise be repository-independent. When no source is selected, repository-independent work and direct fully qualified API targets can proceed. Codex must not infer repository identity from unrelated checkouts, earlier cards, or files left in the workspace.
If repository.default_url remains malformed after compatibility normalization, exactly one
unambiguous card repository identity overrides that unused fallback. Full issue and pull-request URLs
remain checkout-free for API-only work; repository-changing work may use a full repository, issue,
pull-request, or file URL, owner/repository, or equivalent single identity. With no card identity,
the malformed workflow URL blocks unconditionally, including for repository-independent work. With
conflicting card identities, Codex blocks rather than choosing one. A lower-priority
repository.default_path never supplies identity or replaces the malformed selected URL; after one
card identity overrides the URL, the path is only a checkout candidate whose Git remotes must match
that identity.
When a task needs repository files, Codex prepares the checkout only after selecting one repository
identity. A configured repository.default_path remains a candidate when the selected identity is a
remote, including an explicit card remote, but it is used first only after read-only inspection proves
its Git remotes match that identity. The configured path never establishes identity, and Codex does
not assume it matches merely because it was configured with a workflow URL. An explicitly selected
local path is already the selected checkout and does not receive a second configured path candidate.
Otherwise, Codex searches accessible local checkouts and compares their Git remotes with the selected
identity; one matching checkout is reused without cloning, while an ambiguous match blocks. Codex
clones only when no matching local repository exists. For either a reused or new repository, it
fetches the remote default branch before creating a separate task worktree from that freshly fetched
branch. A card that
explicitly requests another branch, ref, base, or checkout arrangement overrides this default. Local
directory names, current branches, earlier cards, and workspace residue never establish repository
identity.
Existing workflow files keep compatibility for repository.default_url values wrapped like prose
tokens or followed by prose punctuation. Symphony removes that outer punctuation before validation.
A default URL that is valid after this normalization is a selected source, not a malformed one.
Existing persisted WORKFLOW.md files also do not need regeneration for repository-need
classification. Symphony appends a final authoritative runtime repository-source context after the
workflow prompt. When that context reports no selected source, it explicitly supersedes legacy
instructions that blocked unconditionally on a missing source and requires the current task to be
classified first. "No selected source" does not mean "no repository": Codex still uses a single
unambiguous repository identity in ordinary card context.
Move a card to Merging when you have reviewed it and want Codex to merge the PR. Merging tells
Codex to do final checks, review PR comments and checks, follow the repository's merge policy, and
move the card to Done when the PR merges successfully. If there is exact feedback that was already
on the PR before the card entered Merging, Codex can make that fix first and then merge after
clean checks. If the feedback needs a broader change or is unclear, Codex should move the card back
to Human Review with the reason. If merging is blocked by an unresolved review, required approval,
failing check, auth problem, or repository rule, Codex should move the card to Blocked with the
next human action.
Blocked is for work that needs attention before Codex can continue. Common examples are missing
credentials, missing allowed file access, unclear requirements, failing external services, or a PR
state that cannot be resolved automatically. After fixing the problem, move the card back to
Ready for Codex so Codex can continue with the new context. When the newest ordinary Trello
comment is an explicit Blocked: or Blocked by ... handoff, the generated workflow keeps one
managed blocker-recheck status. Because the rendered prompt contains only recent comments, Codex
first calls the status tool to classify the deep comment window. A no-blocker result creates no
comment. When a blocker qualifies, the Blocked: comment is the comment being rechecked and stays
unchanged. The tool creates or updates a separate managed comment to show that the blocker is being
checked. It says that work resumed only after Codex confirms the old blocker no longer applies. The
managed comment ends with a readable Symphony label and a link to the comment being rechecked;
Symphony uses that exact footer to recognize the comment it may safely update.
If the initial status call fails, the run stops without another Trello write and retries the initial
check on the next dispatch rather than publishing an unsafe later handoff.
Each card gets its own local workspace. That separation makes it easier to inspect the files for one
task, avoids mixing unrelated changes, and lets Symphony clean up terminal work later. By default,
Codex can write in the card workspace. If a card needs another local repository or shared folder,
allow that path during setup or in the workflow before asking Codex to edit it. Keep broad filesystem
access for trusted boards and machines only. Configure extra write access with
codex.additional_writable_roots, and prepare workspaces with
hooks.after_create or hooks.before_run when needed.
You can connect more than one Trello board. This is useful when different projects or teams should
have separate queues, workspace roots, GitHub behavior, or status ports. The installer and lifecycle
commands understand connected boards, so you can check, start, stop, inspect logs, and run diagnostics
for all boards or for one selected board. To add another board after the first setup, run
symphony-trello setup-local again and choose to connect another board, or use new-board or
import-board directly.
If your workflow has required labels, Symphony only starts cards that have those labels. For
example, a card in Ready for Codex will wait until it has every required label. This is useful on
team boards where many cards are visible but only some are meant for automation. If a required label
is removed from a running or retrying card, Symphony stops treating that card as ready until the
label comes back. Configure this with tracker.required_labels.
Symphony tries again automatically after short waits when a problem is likely temporary. A card may
pause briefly if Codex exits, Trello is temporarily unavailable, a rate limit is hit, or a worker
appears stalled. symphony-trello status and the worker's local status page show running and
retrying cards so you can distinguish "still working" from "needs human attention". Configure the
maximum wait with
agent.max_retry_backoff_ms.
When Codex reports its structured usage-limit error, Symphony pauses new card pickup for the whole
workflow until Codex's reported reset time, when one card rechecks availability. A repeated limit
extends the pause. If no usable reset is available, Symphony waits for
agent.max_retry_backoff_ms. Already-running cards continue. The affected card's ## Codex Workpad shows the clean Codex message and next attempt when Trello comment writes are enabled, and
the status page shows the active CODEX_USAGE_LIMIT pause. Concurrent cards launched by the same
configured codex.command share the latest sparse rate-limit snapshot, so a reset reported to one
worker remains available when another worker reports the limit. Available account metadata is also
retained without letting absent or null fields erase an earlier value, but only events accepted from
a current worker enter that shared snapshot. Typed usage-limit event summaries expose only the clean
message, not raw provider or account details. A valid change to codex.command stops the old
command's pause from gating the new command; late results and events remain attributed to the command
that launched them. Late typed usage results and stale callbacks cannot change the new command's
pause, while normal card lifecycle may create an ordinary retry under the new command when the
Trello target is unchanged. Invalid workflow reloads keep the existing command scope unchanged.
You do not have to babysit the CLI to make good use of a Codex usage window. Add clear, ready cards
to an active list such as Ready for Codex whenever you have them, even if there are more queued
cards than the current concurrency setting can run at once. Symphony works through that queue
according to workflow state, priority labels, prerequisite checklists, and
agent.max_concurrent_agents, so Symphony starts ready cards as capacity becomes available without
you starting each one by hand.
If capacity is temporarily unavailable, such as during a Codex usage-limit pause, queued cards wait in their active list instead of failing. Symphony resumes dispatching them automatically when capacity returns. A queue prepared ahead of time therefore continues across a reset period without requiring you to retrigger each card by hand. This queueing behavior does not bypass Codex usage limits or grant extra capacity.
Diagnostics are safe to paste into public issues by default. They summarize local setup, connected
boards, workflow files, health probes, and recent logs while hiding secrets and private context. Use
symphony-trello diagnostics when asking for help. Use --deep when a maintainer needs deeper
public-safe checks. Use --show-private-context only locally when you need to map diagnostics hashes
back to your own board, workflow, log file, or PID/state file. Add --lookup <token> when you only
need one mapping. Do not paste private-context output into public issues.
The installer downloads the latest GitHub Release archive, verifies its SHA3-256 checksum, and
unpacks it into the local app directory. It installs or updates Symphony for Trello, then runs guided
setup and starts the managed local worker unless you pass --no-onboard.
For Windows, WSL2 is the recommended setup path. Run the Linux installer inside WSL2, keep Codex CLI
and Git on the WSL2 PATH, and use Linux paths for allowed local files and folders. Native Windows
PowerShell is implemented as best effort.
Supported local platforms:
| Platform | Status |
|---|---|
| macOS arm64/amd64 | Supported |
| Linux arm64/amd64 | Supported |
| WSL2 on Windows | Supported through the Linux installer |
| Windows amd64 PowerShell | Best effort |
| Windows arm64 PowerShell | Best effort |
Native Windows PowerShell:
powershell -c "irm https://symphony-trello.fmartin.ch/install.ps1 | iex"The installer checks a Java 25+ JDK, Codex CLI auth, Trello credentials, and optional GitHub CLI auth. It checks Git only when you install from a source checkout. When a required local tool is missing, the installer offers a concrete install command before it continues.
On immutable Linux systems that use transactional-update, such as openSUSE MicroOS, Leap Micro,
Aeon, or Kalpa, package installs only become active after a reboot. If Git, Java, or Node.js/npm is
missing, the installer combines the missing OS packages into one transactional-update command,
stops, and tells you to reboot and rerun the installer.
GitHub is not required unless you want Symphony to create and merge GitHub pull requests. If GitHub is
not configured, setup creates a Trello board without the GitHub-specific Merging list and writes a
non-GitHub starter workflow. If you enable GitHub while importing an existing board, setup creates
the missing Merging list when needed.
With WSL2, browser login may open in Windows; if that is awkward, choose device login when setup asks
whether the machine can open a browser. The managed start, stop, status, and logs commands
are the public lifecycle controls for connected boards. status reports whether each selected
workflow is currently responding as the expected local Symphony worker; use logs when a worker is
not responding. It does not inspect autostart configuration or say whether a worker will start after
login or reboot. Installer-managed autostart remains supported and can be investigated through setup
checks, installer output, logs, or native platform tools when needed. On Linux hosts with user systemd, the
installer registers a user service that runs symphony-trello start --all for connected boards on
login or reboot when user lingering can be enabled. On macOS it registers a per-user LaunchAgent. On
Windows it creates a per-user Scheduled Task, falling back to a Startup-folder command if task
creation is denied. If the host does not support managed autostart, run
symphony-trello start --all after a system restart or login.
The installer prints its final good-to-go handoff only after worker startup, autostart setup,
lingering notes, and any direct-start fallback have finished successfully. The handoff names each
connected Trello board with its normalized workflow path and ends with useful checks:
symphony-trello status plus one shell-quoted symphony-trello logs --workflow PATH command for
each connected workflow. If setup or managed worker startup fails, the installer exits without
printing that completion block.
Setup saves Trello credentials that you type or pass directly. If credentials already come from real
environment variables or an existing .env file, setup uses them without copying them into another
file for setup. For managed autostart, the installer writes a private autostart environment snapshot
with only Symphony/Trello/Codex/GitHub/OpenAI/Anthropic/Quarkus-prefixed variables from the installer
session, then removes that snapshot during uninstall.
On normal Linux, macOS, and WSL2 installs, Symphony uses XDG-style user-local paths by default:
config in $HOME/.config/symphony-trello, app and workspaces in
$HOME/.local/share/symphony-trello, state and logs in $HOME/.local/state/symphony-trello, and
cache/dependency data in $HOME/.cache/symphony-trello.
On openSUSE MicroOS-like hosts, and on other Linux hosts with the same storage topology, the POSIX
installer checks whether $HOME is on a small root-backed filesystem while /var is the larger
mutable filesystem. If so, it stores Symphony's app, config, workspaces, state, and cache under
/var/lib/symphony-trello/users/<user>/ and keeps the command shim in $HOME/.local/bin. If
$HOME already resolves into /var, for example through a symlinked or bind-mounted home, the
installer keeps the normal logical XDG paths under $HOME. Explicit path overrides such as
SYMPHONY_HOME, SYMPHONY_TRELLO_CONFIG_DIR, SYMPHONY_TRELLO_WORKSPACE_ROOT,
SYMPHONY_TRELLO_STATE_HOME, --prefix, and --bin-dir still win.
The installer writes an install context in the selected config and state directories, plus stable
default context locations under $HOME, so future updates and uninstall can find the selected paths
without the original flags. Durable data is config and state/logs. Large generated data is app
files, workspaces, and cache/dependency stores.
The installer writes the command to $HOME/.local/bin/symphony-trello on macOS, Linux, and WSL2, or
$HOME\.local\bin\symphony-trello.ps1 on native Windows PowerShell. If that directory is not on
PATH, the installer updates the shell profile or current user PATH when it can. Pass
--no-update-path if you want to manage PATH yourself. Open a new terminal after PATH setup. If
symphony-trello is still not found, add the printed directory to PATH manually.
Pass --version 0.x.y to install a specific release. Pass --from-source --repo URL --ref REF only
when you are developing or testing from a Git checkout instead of the published release archive.
During setup, you can keep the default Codex workspace access or allow extra local files/folders.
Extra paths are opt-in because Trello cards should not make Codex read or edit unrelated files by
accident. You can also opt into danger-full-access, but setup asks for confirmation because that
disables Codex's command/filesystem sandbox for that workflow.
To inspect the installer first:
curl -fsSL https://symphony-trello.fmartin.ch/install.sh -o install.sh
less install.sh
bash install.shirm https://symphony-trello.fmartin.ch/install.ps1 -OutFile install.ps1
notepad install.ps1
powershell -ExecutionPolicy Bypass -File .\install.ps1Pass installer flags like this:
curl -fsSL https://symphony-trello.fmartin.ch/install.sh | bash -s -- --dry-runpowershell -c "& ([scriptblock]::Create((irm https://symphony-trello.fmartin.ch/install.ps1))) --dry-run --no-onboard"Useful commands after install:
symphony-trello setup-local check
symphony-trello setup-local repair-port --board "My Board Name"
symphony-trello status --board "My Board Name"
symphony-trello logs --board "My Board Name"
symphony-trello diagnostics --board "My Board Name" --output diagnostics.txt
symphony-trello diagnostics --workflow WORKFLOW.md --output diagnostics.txt
symphony-trello diagnostics --show-private-context
symphony-trello stop --board "My Board Name"Use setup-local repair-port --board "My Board Name" when setup-local check reports that a board's
local HTTP port is already used by another process, or after intentionally changing server.port as
described in Find And Edit Workflow Files.
Uninstall removes only the installer-managed command and app checkout by default. It preserves local
.env files, workflows, connected-board metadata, workspaces, logs/state, Codex auth, GitHub auth,
Trello boards, and any PATH entry you accepted during install.
curl -fsSL https://symphony-trello.fmartin.ch/uninstall.sh | bashpowershell -c "irm https://symphony-trello.fmartin.ch/uninstall.ps1 | iex"To inspect uninstall first or pass cleanup scopes:
curl -fsSL https://symphony-trello.fmartin.ch/uninstall.sh -o uninstall.sh
less uninstall.sh
bash uninstall.sh --dry-run
bash uninstall.sh --remove-config --remove-workspaces --remove-state
bash uninstall.sh --yes --yes-local-data --remove-all-local-data--yes only skips the prompt for installer-managed app files. Add --yes-local-data only when you
also want unattended deletion of local .env files, workflows, workspaces, state, and logs.
Use this section only when the guided setup, new-board, or import-board commands do not fit how
you want to connect a board. Most first-time local installs can skip it.
Use this manual path when your team already has a Trello board for engineering work and you prefer to
write WORKFLOW.md yourself.
- Pick the board Symphony should poll.
- Choose one or two list names that mean "Codex may work on this now".
A low-risk default is a single list named
Ready for Codex. - Choose an optional in-progress list, such as
In Progress, if you want Trello to show when Codex has picked up a card. - Choose terminal list names that mean "never run Codex for this card again".
A common default is
Done. - Choose a non-active list for blocked work, such as
Blocked. If your board does not have one, use your review list so blocked cards still leave the active list. - Copy the board short link from the board URL.
In
https://trello.com/b/SYNTH001/my-board, theboard_idvalue can beSYNTH001. - Create
WORKFLOW.mdand settracker.board_id,tracker.active_states,tracker.in_progress_state,tracker.terminal_states, and the handoff list names to match your board.
For a hand-written workflow, start from WORKFLOW.example.md and adjust the
front matter to match your board. The setup commands generate the current full prompt body, so the
README shows only the key fields:
tracker:
board_id: SYNTH001
active_states:
- Ready for Codex
- In Progress
in_progress_state: In Progress
terminal_states:
- Done
workspace:
root: ./workspaces
repository:
default_url: https://github.com/OWNER/REPO.git
default_path: nullUse repository.default_url when every card in this workflow belongs to the same GitHub repository.
Use repository.default_path when every card should use the same local repository checkout. You may
set both for the same repository: the URL remains the fallback identity and clone source, while the
path is the first checkout candidate and is used only when its Git remote matches that identity.
Operationally, use the board like this:
- Put new ideas wherever your team normally triages work.
- Move a card to
Ready for Codexonly when the title and description are clear enough for an engineer to start. - Check that the card moves to
In Progressafter Codex picks it up. - Open Symphony at
http://127.0.0.1:18080/; see Operations for the available status endpoints. - Review the card after Codex moves it to
Human RevieworBlocked. - Move the card out of active lists if you want to pause or prevent further retries.
- Move the card to
Donewhen the generated work has been reviewed and accepted.
Use this manual path when you want a clean board designed for Symphony from the start but do not want the setup command to create it for you.
Create a board named Symphony Work Queue and add these lists in this order:
InboxReady for CodexIn ProgressBlockedHuman ReviewMergingDone
Recommended meaning:
Inbox: rough tasks, ideas, or incomplete cards. Symphony ignores this list.Ready for Codex: cards that are ready to run. Symphony polls this list.In Progress: active Codex work. If an attempt fails and waits for a retry, Symphony moves the card back to the queue list when it can.Blocked: cards Codex could not safely finish. Symphony ignores this list.Human Review: work produced by Codex that needs human review. Symphony ignores this list.Merging: human-approved work that is ready for the merge flow.Done: finished cards. Symphony treats this as terminal.
For each task card, use a title that reads like a pull request title, then put the useful details in the description:
Goal:
- What should change?
Acceptance criteria:
- What must be true when this is done?
Verification:
- Which command or manual check should pass?
Notes:
- Links, constraints, or gotchas.Codex treats card-written Validation, Test Plan, and Testing sections as required. For bugs or
behavior changes, include the current behavior you expect Codex to reproduce or capture before it
edits code. If a required check needs credentials, files, or tools that are not available to the
deployed service, Codex should move the card to Blocked instead of Human Review.
If a card already has a pull request or branch, put the PR URL or branch name in the description or a
Trello comment. Codex will use that link to sweep PR comments, inline review feedback, Codex review
comments, and checks before it moves the card to Human Review.
The setup commands normally write the current full WORKFLOW.md prompt for you. If you create the
board manually, copy WORKFLOW.example.md, set tracker.board_id, and adjust
the list names to match the board.
If all cards on this board belong to one GitHub repository, also set repository.default_url in that
workflow file. See One Workflow For One Repository.
Start with max_concurrent_agents: 1. If two cards are in an active list such as Ready for Codex,
that default makes Symphony run one card and leave the other waiting until a slot is free. Raising
the value to 2 lets two cards from the same configured board run at the same time; raising it to
N allows up to N simultaneous Codex sessions for that process. Raise it only after
one-card-at-a-time runs are routine and predictable.
Within the available slots, Symphony starts cards in a predictable order. Priority labels run first when you use them. Otherwise, it follows the configured active-list order, then the order of cards in the Trello list from top to bottom. If there is still a tie, older cards run first.
List routing for the recommended board:
Inbox: rough ideas or incomplete tasks. Symphony ignores this list.Ready for Codex: queued work. Symphony dispatches from here and moves the card toIn Progress.In Progress: work currently running in Codex. If an attempt is waiting for retry or no concurrency slot is available, Symphony moves the card back to the queue list when it can.Blocked: work that needs a human or environment fix. Symphony ignores it until a human moves it back to an active list.Human Review: work ready for a person. Symphony does not code from this list.Merging: human approval for merging. Codex can merge only from this list when it is configured as active.Done: terminal work. Symphony treats it as complete and removes matching workspaces during terminal cleanup.
Each running card keeps one Codex app-server session while it remains active. After a successful
turn, Symphony refreshes the Trello card. If the card is still in an active list and the worker has
not reached agent.max_turns, Symphony sends a short continuation prompt to the same Codex thread.
If the card moved to Human Review, Blocked, Done, or another non-active list, that worker
stops.
Symphony reads WORKFLOW.md from the working directory unless SYMPHONY_WORKFLOW_PATH points to a
different file. Each running process uses one workflow file. For Trello, that workflow contains one
tracker.board_id, so one process polls one Trello board.
For multiple boards or projects, create one workflow per board and start one process per workflow.
Give each process its own workflow path and HTTP port. The setup commands write a stable
server.port for generated workflows and choose the next port automatically when other workflow
files in the same folder already use earlier ports. If another local Symphony process is already
using the same resolved workflow file, startup takes a workflow-local operating-system lock and fails
before polling Trello. If that lock cannot be created, startup fails instead of using a weaker
process-local fallback.
By default, installer-managed setup-local writes each generated workflow in the active Symphony
config directory. Without --workflow, the file is named from the Trello board, for example
WORKFLOW.my-board.md. Unless --force is set, setup adds a number such as
WORKFLOW.my-board-2.md when that name already exists. --workflow PATH overrides generated naming;
a relative path resolves from the active config directory. --force permits overwriting the
selected path.
The default workflow directory is:
$XDG_CONFIG_HOME/symphony-trellowhenXDG_CONFIG_HOMEis set on Linux, macOS, or WSL2; otherwise$HOME/.config/symphony-trello./var/lib/symphony-trello/users/<user>/configwhen the installer selects the MicroOS-style/varlayout.$env:LOCALAPPDATA\SymphonyTrello\configfor a native Windows PowerShell install.- A custom active directory selected by setup's
--config-dir,SYMPHONY_TRELLO_CONFIG_DIR, an installerSYMPHONY_HOMEor PowerShell-SymphonyHome, or a saved install context.
Do not guess the final file name from the Trello board name. Guided setup prints the full path on its
Workflow written: line, and the direct new-board and import-board commands print it on their
Wrote workflow: line. Run this command later to inspect the recorded workflow paths; it lists each
valid entry and warns about invalid ones:
symphony-trello setup-local checksetup-local check reads the selected connected-board manifest rather than scanning the config
directory for WORKFLOW*.md. Its output has a Workflow: row for each valid connected workflow and
warns about recorded paths that are missing or invalid. Add --board "My Board Name" to select one
board, or omit --board to check every manifest entry. Extra workflow files on disk are not
automatically treated as connected boards. If several connected boards have the same name, select
one with its Trello id or short link instead.
To also enumerate conventionally named workflow files that are disconnected, hand-created, or orphaned, search the active config directory on disk. Replace the example path with the active directory described above:
find "/path/to/active/config" \( -type f -o -type l \) -name 'WORKFLOW*.md' -printIn PowerShell:
Get-ChildItem -LiteralPath 'C:\path\to\active\config' -Filter 'WORKFLOW*.md' -File -Recurse |
Select-Object -ExpandProperty FullNameThis filesystem list does not say which files have connected managed workers. Compare it with the
unfiltered setup-local check output. A custom --workflow path outside the active config directory,
or a nonconventional file name, is not found by this search; use the exact path printed by setup. The
selected manifest records that path while the board is connected.
Each connected Trello board records one workflow path and one local HTTP status port. The workflow
selects one tracker.board_id; when the board is started, one managed Symphony worker process loads
that file and listens on its port. Connecting another Trello board creates another workflow and
worker configuration with its own port. Raising
agent.max_concurrent_agents can start several Codex sessions inside that worker; it does not change
the one-workflow-per-board mapping.
Open the exact path printed by setup or setup-local check in a text editor and save changes to the
same file. No reload command is needed. When available, a filesystem watcher requests a refresh when
the file changes, and every scheduler tick also checks the file in case a watch event was missed or
watching is unavailable. The fallback delay is the current workflow's polling.interval_ms;
generated workflows set it to 5000 ms.
A valid reload affects later scheduler decisions and newly started Codex work. It does not rewrite or
restart an in-flight Codex session. Each running session continues to use the effective workflow
configuration captured when it started for tracker reconciliation and stall handling. Normal
reconciliation can still cancel it if the Trello card becomes ineligible under that launch-time
configuration or if its launch-time stall timeout expires. If the edited file is invalid, Symphony
logs outcome=reload_failed and continues with the last valid workflow. Fix and save the same file
to try the reload again.
server.port is restart-bound: editing it does not move the HTTP listener of a running worker and
can leave the connected-board manifest with the old port. To choose a specific available port, stop
the managed worker, edit server.port, start the board, then run repair-port to copy the healthy
workflow port into the manifest:
symphony-trello stop --board "My Board Name"
# Edit server.port in the workflow file.
symphony-trello start --board "My Board Name"
symphony-trello setup-local repair-port --board "My Board Name"
symphony-trello setup-local check --board "My Board Name"When setup-local check reports a port conflict, run repair-port without editing the workflow. It
selects an available port, updates both the workflow and connected-board metadata, and restarts a
running managed worker.
If SYMPHONY_HTTP_PORT or QUARKUS_HTTP_PORT is set in the board environment or service
environment, that value takes precedence over server.port, and repair-port refuses to run while
the override is defined. Remove it before using repair-port. To keep managing the port through the
override instead, change the override and restart the worker without running repair-port.
WORKFLOW.example.md contains a complete starter. YAML front matter
configures runtime behavior. The Markdown body becomes the prompt template for the card.
Minimum example:
---
tracker:
kind: trello
api_key: $TRELLO_API_KEY
api_token: $TRELLO_API_TOKEN
board_id: your-board-id-or-shortlink
active_states: [Todo, In Progress]
in_progress_state: In Progress
terminal_states: [Done, Archived, ArchivedList, ArchivedBoard, Deleted]
workspace:
root: ./workspaces
server:
port: 18080
polling:
interval_ms: 5000
codex:
command: codex app-server
model: gpt-5.5
reasoning_effort: medium
---
\# Task
Work on Trello card {{ card.identifier }}: {{ card.title }}.Unknown template variables fail the affected attempt, then the orchestrator applies normal retry behavior. This is intentional; typo-tolerant prompts hide broken automation.
Use dispatch controls when a board has more than one kind of card, when your machine cannot run many Codex sessions at once, or when some cards need an explicit readiness signal.
tracker.active_states names the Trello lists Symphony may dispatch from. Generated GitHub workflows
use Ready for Codex, In Progress, and Merging. Generated non-GitHub workflows use
Ready for Codex and In Progress. Keep draft ideas, human review, blocked work, and completed
work out of active lists.
tracker.active_list_ids is the ID-based version of tracker.active_states. Use it when list names
are duplicated or likely to be renamed. When it is set, open Trello cards are matched by list ID
instead of list name.
tracker.in_progress_state is the visible pickup list. When it is configured, Symphony moves a card
there after it decides to run the card and before Codex starts. If the card is waiting for retry or a
concurrency slot, Symphony moves it back to the queue list when it can so In Progress represents
work that is actually running.
tracker.blocker_enforced_states names active Trello lists where dependency blockers prevent
dispatch. The default covers Todo and Ready for Codex. Leave review, blocked, and terminal lists
out of this setting because Symphony does not dispatch from those lists.
tracker.blocked_state is the Trello list the generated prompt tells Codex to use when it cannot
safely finish. Symphony does not dispatch from this list. Use a separate blocked list so unresolved
work is visible and does not keep getting picked up.
tracker.terminal_states names Trello lists or special states that mean the card is done for this
workflow. Generated workflows use Done, Archived, ArchivedList, ArchivedBoard, and
Deleted.
tracker.terminal_list_ids is the ID-based version of tracker.terminal_states for open cards in
Trello lists. Use it when terminal list names are duplicated or likely to be renamed. Special states
such as Archived, ArchivedList, ArchivedBoard, and Deleted still come from
tracker.terminal_states.
tracker.required_labels is an optional dispatch gate. A card must have every configured Trello
label before Symphony dispatches it. The default is an empty list, so labels are not required.
Configured labels and Trello card labels are matched after trimming surrounding whitespace and
ignoring case. Multiple configured labels are all required. A blank configured label matches no card,
so it blocks every card until the workflow is fixed.
Example:
tracker:
required_labels:
- Ready for automation
- backendIf a running or retrying card no longer has every required label, Symphony releases or requeues it instead of continuing to dispatch it.
tracker.priority_labels lets selected labels run before other cards in the same active list. Lower
numbers run first. The default recognizes p1 through p4 and
priority: critical, priority: high, priority: medium, and priority: low.
Example:
tracker:
priority_labels:
p1: 1
p2: 2
customer escalation: 1agent.max_concurrent_agents controls how many cards from one workflow are processed concurrently.
Generated workflows use 1. Guided setup asks for this value and keeps the current value when you
press Enter. Raise it only when the machine can run that many Codex sessions and their build/test
commands in parallel. If cards depend on other cards, use prerequisite checklist items before moving
the dependent cards into an active Trello list.
agent.max_turns limits how many Codex turns one worker session may take before Symphony stops that
session and schedules normal continuation handling. Increase it only when long cards need more
Codex turns and the extra runtime is acceptable.
agent.max_concurrent_agents_by_state can put a narrower per-list cap on an active state. Use it
when one active list, such as Merging, should run with lower concurrency than normal coding work.
agent.max_retry_backoff_ms caps the exponential retry delay after worker failures, timeouts, or
stalls. Generated workflows keep the default five-minute cap. Lower it only when quick retries are
more important than reducing load; raise it when repeated failures are noisy or expensive. It is
also the fallback duration for a structured Codex usage limit that has no valid future reset time;
non-positive values use a one-second safety floor for that pause.
Each Trello card runs in its own workspace. By default, Codex can write there and cannot freely edit unrelated host files. Keep that default until a card needs another local file or folder.
During guided setup, you can add allowed host paths. In WORKFLOW.md, those become
codex.additional_writable_roots. Relative paths resolve relative to the workflow file. The runtime
adds those paths to a Codex workspaceWrite sandbox policy unless the workflow already uses
dangerFullAccess. Generated workflows use workspaceWrite so Codex can write inside each card's
workspace, and they set networkAccess: true so selected repository URLs can be cloned while
keeping the filesystem sandbox enabled.
--add-path <checkout> gives Codex filesystem access to that checkout as an additional writable
root. It may be enough for source-file edits, but it does not by itself guarantee that direct work in
a Git checkout can create commits. Direct commits also need writable Git metadata for that checkout.
If you need direct checkout commits, use a deployment policy that grants both the checkout files and
Git metadata, or let Codex clone into the per-card workspace and commit there.
Example:
codex:
additional_writable_roots:
- ../shared-library
- /opt/symphony-fixturesUse danger-full-access only for a trusted board and machine. It disables Codex's command and
filesystem sandbox for that workflow, so Trello cards can ask Codex to read or edit much more than
the card workspace.
Workspace hooks let operators prepare or clean up the per-card workspace with shell snippets in
WORKFLOW.md.
hooks.after_create: runs once after Symphony creates a new card workspace. Use it to clone a repository, install project-local files, or prepare a checkout.hooks.before_run: runs before each Codex attempt. Use it for lightweight sync or validation that must happen before Codex starts.hooks.after_run: runs after each Codex attempt. Use it for best-effort cleanup or log capture.hooks.before_remove: runs before Symphony removes a workspace for terminal cleanup.hooks.timeout_ms: limits each hook run.
after_create and before_run failures abort the current attempt. after_run and before_remove
failures are logged and cleanup continues where possible.
Example:
hooks:
after_create: |
git clone https://github.com/example/project.git .
before_run: |
git status --short
timeout_ms: 60000Generated workflows poll Trello every 5 seconds:
polling:
interval_ms: 5000Increase polling.interval_ms in WORKFLOW.md if Trello rate-limit warnings
repeat in the logs. Deployments above roughly 5-10 boards sharing the same Trello token should
consider a higher value, such as 10000 or 30000.
To check for rate limits, search the service logs for Trello rate limit reached. Occasional
warnings can happen during bursts; repeated warnings mean the interval is too aggressive for the
current board count and token.
A generated Codex section can look like this when Terra is available:
codex:
command: codex app-server
model: gpt-5.6-terraWhen the selected catalog entry has a non-blank reasoning recommendation, setup also writes
reasoning_effort with that exact value. It omits the field when the selected entry has no
recommendation.
Symphony runs codex.command with bash -lc from the card workspace. Any command is acceptable if
it starts a Codex app-server on stdio for the same OS user that runs Symphony. Examples include an
absolute path such as /opt/codex/bin/codex app-server or a small wrapper script that sets up the
environment before starting codex app-server.
Generated workflows also make model selection explicit. During setup, Symphony calls the installed
Codex CLI's model/list method for the available models, each model's recommended reasoning effort,
and its advertised supportedReasoningEfforts. For a new workflow without a model override, setup
first prefers an exact visible gpt-5.6-terra entry. If Terra is absent or hidden, it uses the first
visible model marked isDefault; if no visible model is marked as the default, it uses the first
visible usable model in catalog order. gpt-5.6-sol has no special fallback rule. It can be selected
explicitly, preserved from an existing workflow, or selected through the same generic catalog rules
as any other model. Explicit setup choices and existing workflow values still take precedence over
this new-workflow recommendation.
Guided setup prints the exact ordered efforts and descriptions advertised for the selected model;
for example, xhigh, max, and ultra appear when that catalog entry supports them. It marks the
model's advertised default and the effective current setup or workflow value. These markers are
derived from the model default and current selection; they are not a fixed property of an effort
name. Press Enter to keep the current value, or type another advertised value. An explicit
--codex-reasoning-effort takes precedence, followed by an existing workflow value and then the
exact selected model's recommendation. If supported discovery returns a usable catalog but the
selected model is absent or has no defaultReasoningEffort, and neither an explicit effort nor an
existing workflow effort has higher precedence, guided setup shows Reasoning effort: without a
bracketed recommendation. Press Enter in that case to leave reasoning_effort unset.
Non-interactive setup also omits the field instead of reusing another model's recommendation. A
workflow that already omits reasoning_effort keeps that omission during forced regeneration unless
you explicitly change the model or effort. A newly selected effort outside a non-empty advertised
list is rejected with the accepted values.
Symphony does not maintain a separate fixed effort list or display-name table. If the selected model
does not advertise an effort list, guided setup says so and setup permits a non-blank pass-through
value for compatibility with custom or older catalogs. Discovery retains hidden catalog entries so
an explicitly selected or preserved model still gets its own choices, but setup never chooses a
hidden model as the guided default.
To preserve its no-write guarantee, setup-local --dry-run does not launch Codex solely to discover
the model catalog. It still validates input that is available without discovery; a real setup run
performs model-specific effort validation before changing Trello or writing workflow files.
For a new workflow without an explicit or preserved model, supported discovery that returns an empty
catalog or no visible usable model id writes the deterministic compatibility fallback gpt-5.5. It
also writes medium when no explicit or preserved effort takes precedence; an explicit effort
replaces medium without replacing the fallback model. This supported-empty or unusable catalog
fallback is separate from a miss for an explicit or preserved model: that model still needs its own
recommendation, or setup omits reasoning_effort when no explicit or preserved effort takes
precedence.
If the installed Codex app-server cannot answer the model-list request at all, setup omits the
first-class model fields when the operator requested neither a model nor a reasoning effort. For
compatibility with that older discovery path, an explicit model without an explicit or preserved
effort uses the fallback medium effort.
codex.model maps to the app-server model request field. codex.reasoning_effort maps to the
app-server turn effort field. Edit those workflow values to choose a different model or reasoning
level. Catalog validation applies when setup selects a new reasoning effort; runtime workflow values
remain pass-through Codex settings. Existing workflow values remain the source of truth for that
Trello board; setup preserves them when regenerating a workflow unless you pass --codex-model,
pass --codex-reasoning-effort, or edit the workflow value. If either field is omitted, the
installed Codex CLI/app-server default or codex.command configuration decides the value.
codex.turn_timeout_ms limits a full Codex turn. codex.read_timeout_ms limits app-server startup
and request/response reads. codex.stall_timeout_ms controls how long Symphony waits without Codex
events before killing the worker and scheduling a retry. Set stall_timeout_ms to 0 only when you
intentionally want to disable stall detection for that workflow.
The generated workflow points Codex to small procedure files in .codex/skills/symphony-trello-*.
When a workflow references those paths, Symphony installs the files into each per-card workspace
after workspace sync hooks and before Codex starts, so they are available even when the target
repository does not provide its own skills. They keep the workflow prompt readable while still
spelling out repeated work such as committing, pushing a PR, sweeping review comments, updating the
Trello workpad, and handling Trello handoff.
The most common skills are:
.codex/skills/symphony-trello-trello-workpad/SKILL.md: keep the single## Codex Workpadcomment current..codex/skills/symphony-trello-trello-handoff/SKILL.md: move the current card through pickup, review, blocked, merge, and done handoff..codex/skills/symphony-trello-review-sweep/SKILL.md: check PR comments, inline review feedback, GitHub review threads, and checks before handoff..codex/skills/symphony-trello-commit/SKILL.md: commit focused changes, follow the target repository's commit message convention, and, for PR-bound work, reuse a workflow-verified checkout-local commit author or configure one from the authenticated GitHub account before committing..codex/skills/symphony-trello-push-pr/SKILL.md: push the branch, check PR-bound commit authors, and create or update the pull request. Repository-changing work creates a ready-for-review PR by default, and PR bodies preserve the target repository's pull request template when one exists. Cards that need a draft PR must ask for one explicitly..codex/skills/symphony-trello-land/SKILL.md: merge approved work only fromMerging, resolve addressed review threads when possible, then move successful work to the configured completion list or blocked merge attempts toBlocked..codex/skills/symphony-trello-debug/SKILL.md: diagnose stuck, retrying, blocked, or failed runs.
These files are instructions for Codex. Symphony copies them into the workspace but does not execute them directly. When the workspace is a Git checkout root, Symphony adds the namespaced skill directories to that checkout's local Git exclude file so they do not appear as task changes.
For GitHub pull requests, Codex first checks the task checkout's local git config user.name,
git config user.email, and git config symphony-trello.github-author-verified. If the author is
complete and marked verified, it reuses that author and avoids another GitHub API lookup. Otherwise,
Codex uses the GitHub CLI account that publishes the PR as the commit author and stores the verified
author in the checkout-local Git config. If that account has no public email, Codex fetches the
account's actual GitHub noreply email through gh api user/emails, which needs the user:email
GitHub CLI scope. If that email is not accessible, PR-bound work must stop before committing. If
commits show the wrong author, check gh auth status, gh api user, gh api user/emails, and the
repository's local git config user.name, git config user.email, and
git config symphony-trello.github-author-verified inside the task checkout.
The recommended workflow gives Codex four scoped Trello handoff tools:
trello_add_comment: add a comment to the current card.trello_upsert_workpad: create or update the single## Codex Workpadcomment on the current card.trello_update_blocker_recheck_status: reuse one managed status while Codex checks a stale blocker handoff, then mark work as resumed only after the recheck succeeds.trello_move_current_card: move the current card to a configured board-local list such asIn Progress,Human Review, orBlocked.
Hand-authored workflows can enable two more current-card tools:
trello_upsert_checklist_item: create or update one checklist item whentrello_tools.allow_checklists=true.trello_add_url_attachment: attach one HTTP or HTTPS URL without credentials, query string, or fragment whentrello_tools.allow_url_attachments=true.
The move tool uses argument names such as list_name and list_id because Trello calls these board
columns lists.
Symphony advertises those tools when trello_tools.enabled=true and
trello_tools.allow_writes=true; each write type is controlled by its own allow flag. The generated
workflow keeps checklist and URL attachment tools disabled unless you edit those flags. For a
read-only scheduler deployment, set trello_tools.allow_writes: false and move cards manually.
If the API token is read-only or Trello rejects writes, Codex still runs, but handoff tool calls fail and the failures are visible in the Codex session events.
To move cards to workflow lists with different names, set trello_tools.allowed_move_list_names to
those allowed list names and update the pickup and final handoff instructions in
WORKFLOW.md to match them. Do not tell Codex to leave blocked cards in an
active list such as Ready for Codex or In Progress; Symphony may treat the card as still
eligible and run it again.
If a destination list name matches more than one open Trello list, Symphony refuses the name-based
move instead of guessing. Rename the duplicate lists or configure trello_tools.allowed_move_list_ids
and tell Codex to move with list_id.
The standardized generic trello_rest dynamic tool extension is documented in SPEC.md.
This Java implementation advertises the narrower handoff tools above.
Useful endpoints:
GET /returns a small human-readable status page.GET /api/v1/statereturns running sessions, retry queue, token totals, any active dispatch pause, and rate-limit data when reported by Codex.GET /api/v1/{card_identifier}returns card-specific runtime details.POST /api/v1/refreshqueues an immediate poll/reconciliation cycle.
For field meanings, token totals, logging conventions, and troubleshooting expectations, see docs/operations.md.
For issue reports, run symphony-trello diagnostics,
symphony-trello diagnostics --board "My Board Name", or
symphony-trello diagnostics --workflow WORKFLOW.md. Use --board or --workflow to keep the
report smaller. Without a selector, the report covers every connected Trello board and also lists
workflow files in the config directory that are not connected to any board in a separate
Unconnected Workflow Files section, without probing their ports. --board and --workflow are
mutually exclusive; if multiple connected Trello boards have the same name, use the Trello board id
or short link. The command prints sanitized local
setup, workflow, health, and recent log context without Trello, GitHub, or Codex network calls by
default. Add --deep when the default report does not include enough context; it runs deeper
public-safe checks such as local Codex and GitHub auth-status commands. Review the output before
sharing it.
Diagnostics replaces private values with stable local tokens such as the value in a board_hash or
key_hash row, and <path:...> path tokens, so maintainers can compare related rows without seeing
your Trello identifiers or local paths. These tokens are created with a random key stored on your
machine, so they are stable for your installation but are not meant to be guessed by other people.
If a maintainer asks which local board, workflow, or log one of those tokens refers to, run
symphony-trello diagnostics --show-private-context on your machine. Add --lookup <token> to
resolve only one token instead of printing the full private-context report. Private context maps
tokens back to your local Trello board ids, board URLs, workflow paths, env file path, workspace
root, state directory, worker log files, managed PID/state files, and file-backed secret paths. It
does not print the secret values stored in those files. The lifecycle commands may also print one of
these tokens when hiding a local path in an error. Use it to inspect your own machine or answer a
maintainer's question in your own words. Do not paste the --show-private-context output
into public issues because it intentionally contains private Trello identifiers, URLs, and local
paths. It does not include credential values or worker log contents.
WORKFLOW.md is watched for changes and also checked defensively on each
scheduler tick. Invalid reloads are logged and the last known good configuration remains active.
Important environment variables:
SYMPHONY_WORKFLOW_PATH: workflow file path, defaultWORKFLOW.md.SYMPHONY_HTTP_PORT: Quarkus HTTP port, default18080.SYMPHONY_AUTOSTART: setfalsein tests or when only using injected services.SYMPHONY_TRELLO_DOTENV: ignored dotenv file used by local managed runs when credentials are not in real environment variables. The installer wrapper sets this when you start withsymphony-trello start --env PATH --workflow WORKFLOW.md.TRELLO_API_KEYandTRELLO_API_TOKEN: default Trello credential variable names.SYMPHONY_CODEX_ADDITIONAL_WRITABLE_ROOTS: path-separated files or folders that are added to Codex'sworkspaceWritesandbox policy for deployments that intentionally expose extra host paths.SYMPHONY_CODEX_DANGER_FULL_ACCESS: settrueonly with an intentionally broad deployment sandbox.
For local runs, the same names can be placed in ignored .env; real environment variables take
precedence.
Workflow values can also read secret files with file:/path. Use this when an operator manages
secrets outside the workflow file and does not want Trello secrets in the service environment.
This implementation targets trusted automation environments by default. Workspace boundaries are enforced, hooks run inside the per-card workspace, and Codex manages Trello cards through scoped tools without access to the Trello API credentials. Symphony injects those credentials into Trello HTTP requests rather than prompts. Hooks and Codex still execute trusted local code, so production deployments should use a dedicated OS user, a dedicated workspace volume, narrowly scoped Trello credentials, and Codex approval/sandbox settings appropriate to the board's trust level.
Approval and sandbox values are passed through from WORKFLOW.md to the
installed Codex app-server schema. When additional writable roots are configured, this implementation
adds them to a workspaceWrite turn sandbox policy unless the workflow already uses
dangerFullAccess. Generated workflows use workspaceWrite so Codex can write inside each card's
workspace, and they enable network access so Codex can clone selected repository URLs or publish
pull requests without disabling the filesystem sandbox. User-input and unsupported dynamic tool requests
are answered without waiting indefinitely.
A lot went into getting Symphony for Trello 1.0.0 ready.
Across the audited AI-assisted development sessions, the build footprint was approximately:
- 15.13 billion total tokens
- $13,240.24 in API/API-equivalent token cost
- 2,041 human prompts and follow-ups, totaling 72,542 words, roughly the length of Mary Shelley's Frankenstein, or about 8 hours as an audiobook
- 96,825+ agent/model turns
- 107,796+ tool/function calls
- 82,242+ shell executions
These are historical development metrics, not runtime requirements. Running Symphony for Trello does not require this token volume or cost. They are included to make the scale of iteration, validation, and review behind the 1.0.0 release visible.
See CONTRIBUTING.md for contributor setup and development checks, AI_CONTRIBUTION_POLICY.md for AI-assisted contribution expectations, and SECURITY.md for private vulnerability reporting guidance.
Release notes are tracked in CHANGELOG.md.