Introduction
Banco Management System, or simply Banco, is an opinionated project management tool for the command line that helps you organize notes, tasks, bookmarks and documents for your projects.
Banco objects (notes, tasks, bookmarks, etc.) are stored in the filesystem, implemented as plain text files and folders within the root of the project, so you won’t need to install or run any database or server. This enables you to easily create archives and backups, move projects around the filesystem, use command line tools, or keep track of changes by using version control.
Here is how a project managed by Banco looks on the filesystem:
├── .banco
│ └── config.yml ← provider configuration
├── misc ← not managed by banco; store anything here
├── notes
│ └── local
│ ├── meetings
│ │ ├── 20260101 Kickstart meeting.md
│ │ └── 20260102 Client call.md
│ └── project-requirements.md
├── repos
│ ├── gitlab
│ │ └── my-project ← cloned via SSH
│ └── local
│ ├── poc
│ └── mvp
└── tasks
├── gitlab
│ └── my-project
│ └── 0042 - Fix login bug.md
└── local
├── backlog
│ └── 0003 - Write full specs.md
├── doing
└── done
├── 0001 - Schedule kickstart meeting.md
└── 0002 - Write project requirements.md
The name “Banco” is a tribute to Banco Del Mutuo Soccorso, the greatest Italian progressive rock band of all time.
Installation
Banco requires Rust. To install the banco binary:
cargo install --path .
Agents
Banco supports agentic workflows. Upon initialization, three files are created for agent context:
.banco/BANCO.md— banco-managed file with detailed instructions on how agents should work with this project; regenerated by banco oninitAGENTS.md— reads.banco/BANCO.mdand is meant for user-defined instructions; never overwritten by bancoCLAUDE.md— readsAGENTS.md; never overwritten by banco
.banco/BANCO.md instructs agents to:
- Run
banco contextfirst to get a JSON snapshot of the project state (providers, modules, items, and the labels required to build commands) - Always use
banco newto create items — never write files directly - Derive label names and values from the context rather than guessing
- Use
statusandtagsmetadata on synced provider items to make informed decisions — e.g. prioritize open issues, filter by label, skip closed tasks when working on active work
Skills
Banco can install agent skills into a project with banco skills install <agent>. For the
claude agent, skills are written to .claude/skills/<skill-name>/SKILL.md — the location
Claude Code discovers project skills from — so they become invokable immediately. See the
skills command for details.
Example prompts
- How many tasks do I have in the backlog?
- Move task “Write full specs” to done
- Create a note about today’s meeting in the meetings folder
- Show me all bookmarks tagged under tools/rust
- What tasks are currently in progress?
Modules
In Banco, items are grouped into modules. Each module represents a category of content — notes, tasks, bookmarks, or repos — and defines how items of that type are stored, named, and managed on the filesystem.
Modules are provided by providers. The same module type can be backed by different providers: for example, you can have tasks from the local provider living alongside tasks synced from GitLab, each in their own subdirectory.
The directory layout follows the pattern <module>/<provider>/:
tasks/
├── local/
│ ├── backlog/
│ ├── doing/
│ └── done/
└── gitlab/
└── my-project/
The following modules are available:
Notes
Notes are plain Markdown files. They support an optional label parameter, which acts as a nested tag and maps directly to a subdirectory path.
For example, creating a note with label meetings/2026 places the file under
notes/<provider>/meetings/2026/.
| Parameter | Type | Required | Description |
|---|---|---|---|
label | string | no | Nested path used as a tag (e.g. meetings/2026) |
Notes have no special frontmatter — the file content is freeform Markdown.
Tasks
Tasks are Markdown files with a numeric prefix — e.g. 0042 - Fix login bug.md. The prefix is
assigned automatically by Banco and increments with each new item.
Status
Each task has a status. For the local provider, status maps to a subdirectory:
| Status | Directory |
|---|---|
awaiting | tasks/local/backlog/ |
doing | tasks/local/doing/ |
done | tasks/local/done/ |
For remote providers (GitHub, GitLab), status is stored in a YAML frontmatter block at the top of the file:
---
status: open
tags:
- bug
---
# Fix login bug
Description here...
status is open or closed. tags mirrors the issue’s labels on the remote provider. Both
fields are updated automatically on each banco sync without touching the rest of the file.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | enum: awaiting/doing/done | yes | Task status |
Bookmarks
Bookmarks are organized in group files stored under bookmarks/local/. Each group is a
Markdown file whose name identifies the group (e.g. default.md, tools.md). A file
contains a plain Markdown list, one bookmark per line:
- [Rust documentation](https://doc.rust-lang.org)
- [crates.io](https://crates.io)
banco init creates bookmarks/local/default.md as the starting group. New groups are
created automatically when you pass a group name that does not yet exist.
Bookmarks support the browse command — selecting a bookmark opens its URL in the system
browser.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
group | string | no | Group file to add the bookmark to (default: default) |
url | string | yes | The URL to bookmark |
Example
banco new bookmark -n "Rust documentation" -l url=https://doc.rust-lang.org
banco new bookmark -n "crates.io" -l url=https://crates.io -l group=rust
The first command appends to bookmarks/local/default.md; the second creates (or appends
to) bookmarks/local/rust.md.
Repos
Repos are directories, not files. Each repo is a git repository stored under
repos/<provider>/.
For the local provider, Banco runs git init when a new repo is created. For remote providers
(GitHub, GitLab), repositories are cloned via SSH and kept up to date with git fetch on each
banco sync.
Repos support the browse command — selecting a repo opens its remote URL (repository page,
pull requests, pipelines, etc.) in the system browser.
Git status
Each repo item carries a small git status summary, surfaced in the dashboard
and in banco context JSON:
| Field | Meaning |
|---|---|
branch | Current branch, or null for a detached HEAD / unreadable repo |
dirty | true when the working copy has uncommitted or untracked changes |
unmerged_branches | Count of local branches not merged into the current branch |
{
"name": "my-service",
"branch": "main",
"dirty": true,
"unmerged_branches": 2
}
In the dashboard these render compactly as my-service (main) *↟2 — * for a dirty working
copy and ↟N for unmerged branches.
Providers
A provider is a source of items. Providers implement one or more modules and are responsible for creating, reading, and (for remote providers) synchronizing items with an external service.
Configuration
Provider configuration is stored in .banco/config.yml within the project directory. The local
provider is added automatically on banco init; additional providers are added interactively via
banco provider add or the dashboard config editor (press c), which
can also edit and remove existing providers.
Each provider entry supports a common enabled field (default: true) — set it to false to
disable a provider without removing its configuration.
It also supports an optional disabled_modules field: a list of module names to turn off for
that provider while leaving its other modules active. Omitted (or empty), every module the
provider implements is on. For example, a GitHub provider with disabled_modules: [repos] syncs
issues as tasks but does not clone repositories; disabled modules are also omitted from
banco context and banco browse. This applies to the built-in local provider too — disabling
a local module additionally makes banco new <module> refuse to create items in it. Existing
files on disk for a disabled module are left in place (and banco check will not flag them as
extraneous), so you can re-enable the module later without losing data.
Environment variable expansion
String values in the config support environment variable expansion: use $VAR or ${VAR} to
avoid storing tokens in plain text. For example:
api_key: $GITLAB_TOKEN
Aliases
You can use aliases when configuring the same provider type more than once — for example, two
separate GitLab instances. An alias is required if a provider of the same kind is already
configured; Banco will prompt for one interactively during banco provider add.
The alias is used in directory paths and banco sync <alias> calls in place of the provider
name.
Available providers
Local
The local provider is built in and enabled by default. It is added to .banco/config.yml
automatically on banco init. Items are not synchronized with any external service — they are
plain files and directories on your filesystem, managed entirely by you.
Modules
| Module | Directory | Items | Parameters |
|---|---|---|---|
tasks | tasks/local/ | Markdown files, prefixed 0001 - | status (enum: awaiting / doing / done) |
notes | notes/local/ | Markdown files | label (string, optional — nested tag, e.g. meetings/2026) |
bookmarks | bookmarks/local/ | Markdown files | label (string, optional — nested tag, e.g. tools/rust), url (string) |
repos | repos/local/ | Directories, git init on create | — |
Any of these modules can be turned off with the top-level
disabled_modules field on the local provider entry — e.g.
disabled_modules: [bookmarks, repos]. A disabled local module is omitted from banco context
and banco browse, and banco new <module> will refuse to create items in it. Existing files
are left untouched.
Note: Gerrit provider is planned and will be available soon.
GitHub
The GitHub provider syncs tasks (issues) and repositories from configured GitHub projects into
the local filesystem. Repositories are cloned via SSH and kept up to date with git fetch. Pull
requests are excluded from tasks.
Configuration
Set interactively via banco provider add.
| Parameter | Required | Description |
|---|---|---|
api_key | yes | GitHub personal access token |
host | no | GitHub instance URL (default: https://github.com) — set for GitHub Enterprise Server |
projects | no † | Explicit list of project paths in owner/repo format |
projects_pattern | no † | Regex matched against owner/repo — e.g. myorg/.* |
† Exactly one of projects or projects_pattern must be set; they are mutually exclusive.
The GitHub provider implements two modules, tasks and repos. Turn either off with the
top-level disabled_modules field — e.g. disabled_modules: [repos]
to sync issues only.
Example configuration
providers:
- name: github
config:
api_key: $GITHUB_TOKEN
projects:
- myorg/my-project
- myorg/another-project
With a pattern and GitHub Enterprise:
providers:
- name: github
alias: github-work
config:
api_key: $GITHUB_WORK_TOKEN
host: https://github.mycompany.com
projects_pattern: myorg/.*
Directory structure
Tasks are synced flat under tasks/<provider>/<owner>/<repo>/:
tasks/
└── github/
└── myorg/
└── my-project/
└── 0042 - Fix login bug.md
Repos are cloned under repos/<provider>/.
Task file format
Each task file carries a YAML frontmatter block followed by the issue title and description:
---
status: open
tags:
- bug
---
# Fix login bug
Description here...
status is open or closed. tags mirrors the issue’s labels on GitHub. Both fields are
updated automatically on each banco sync without touching the rest of the file.
Templates
New task files are initialized from the first matching template found under .banco/templates/tasks/:
github/<owner>/<repo>/TEMPLATE.md → github/<owner>/TEMPLATE.md → github/TEMPLATE.md → tasks/TEMPLATE.md.
See Templates for details.
Sync
After a successful sync, banco stores the timestamp in .banco/sync-state/<provider>. On every
sync, all currently-open issues are fetched.
After writing the fetched issues, banco reconciles local tasks: any local task with status: open
whose issue number was not in the fetched set is marked closed — it was closed on GitHub and
disappeared from the open results. Tasks already closed locally are left untouched.
See banco sync for the full sync flow.
GitLab
The GitLab provider syncs tasks (issues) and repositories from configured GitLab projects into
the local filesystem. Repositories are cloned via SSH and kept up to date with git fetch.
Configuration
Set interactively via banco provider add.
| Parameter | Required | Description |
|---|---|---|
api_key | yes | GitLab personal access token |
host | no | GitLab instance URL (default: https://gitlab.com) |
projects | no † | Explicit list of project paths in namespace/project format |
projects_pattern | no † | Regex matched against namespace/project — e.g. mygroup/.* |
† Exactly one of projects or projects_pattern must be set; they are mutually exclusive.
The GitLab provider implements two modules, tasks and repos. Turn either off with the
top-level disabled_modules field — e.g. disabled_modules: [repos]
to sync issues only.
Example configuration
providers:
- name: gitlab
config:
api_key: $GITLAB_TOKEN
projects:
- mygroup/my-project
- mygroup/another-project
With a pattern and a self-hosted instance:
providers:
- name: gitlab
alias: gitlab-work
config:
api_key: $GITLAB_WORK_TOKEN
host: https://gitlab.mycompany.com
projects_pattern: mygroup/.*
Directory structure
Tasks are synced flat under tasks/<provider>/<project>/:
tasks/
└── gitlab/
└── my-project/
└── 0042 - Fix login bug.md
Repos are cloned under repos/<provider>/.
Task file format
Each task file carries a YAML frontmatter block followed by the issue title and description:
---
status: open
tags:
- bug
---
# Fix login bug
Description here...
status is open or closed. tags mirrors the issue’s labels on GitLab. Both fields are
updated automatically on each banco sync without touching the rest of the file.
Templates
New task files are initialized from the first matching template found under .banco/templates/tasks/:
gitlab/<project>/TEMPLATE.md → gitlab/TEMPLATE.md → tasks/TEMPLATE.md.
See Templates for details.
Sync
After a successful sync, banco stores the timestamp in .banco/sync-state/<provider>. On every
sync, all currently-open issues are fetched.
After writing the fetched issues, banco reconciles local tasks: any local task with status: open
whose issue IID was not in the fetched set is marked closed — it was closed on GitLab and
disappeared from the open results. Tasks already closed locally are left untouched.
See banco sync for the full sync flow.
JIRA
The JIRA provider syncs tasks (issues) from a configured JIRA project into the local filesystem.
It does not call the JIRA REST API directly — instead it delegates to the
claude CLI, which uses the Atlassian Rovo MCP server to fetch issues
on your behalf. No API token is required in Banco.
Prerequisites
- The
claudeCLI must be installed and available in yourPATH - The Atlassian Rovo MCP server must be configured in your
claudesetup - If using Claude via AWS Bedrock, run
claudeinteractively at least once to complete authentication before runningbanco sync
Configuration
Set interactively via banco provider add.
| Parameter | Required | Description |
|---|---|---|
host | yes | JIRA instance URL (e.g. https://yourorg.atlassian.net) — used to construct browse URLs |
project | yes | Project key to sync (e.g. ENG) |
labels | no | List of labels to filter issues by — passed to the agent at fetch time; omit to fetch all |
agent_backend | yes | Agent backend to use; only claude is supported |
By default, only issues assigned to the calling user and not in Done status are synced. There are no config fields for these — they are built-in defaults.
Example configuration
providers:
- name: jira
config:
host: https://yourorg.atlassian.net
project: ENG
agent_backend: claude
With labels filter and an alias (useful when syncing multiple projects):
providers:
- name: jira
alias: jira-sre
config:
host: https://yourorg.atlassian.net
project: OPS
labels:
- SRE
- platform
agent_backend: claude
Directory structure
Tasks are synced flat under tasks/<provider>/:
tasks/
└── jira/
├── ENG-1 - Fix login bug.md
└── ENG-42 - Improve onboarding flow.md
If an alias is configured, the alias is used in place of jira.
Task file format
Each task file carries a YAML frontmatter block with the issue metadata, followed by the file body (populated from a template if one exists, otherwise empty):
---
status: In Progress
type: Task
parent_id: ENG-10
---
parent_id is omitted for top-level issues. All three fields are updated automatically on each
banco sync without touching the rest of the file.
Issue types
type reflects the JIRA issue type name exactly as returned by the Rovo MCP server. Common
values include Epic, Story, Task, Sub-task, and Bug, but custom issue types are also
supported.
Browsing
banco browse constructs issue URLs as {host}/browse/{id} using the host config value and
the issue ID parsed from each filename.
Templates
New task files are initialized from the first matching template found under .banco/templates/tasks/:
jira/TEMPLATE.md → tasks/TEMPLATE.md.
See Templates for details.
Sync
After a successful sync, banco stores the timestamp in .banco/sync-state/<provider>. On every
sync, all currently non-done issues are fetched.
After writing the fetched issues, banco reconciles local tasks: any local task whose status is not
Done and whose ID was not in the fetched set is marked Done — it was completed on JIRA and
disappeared from the non-done results. Tasks already Done locally are left untouched.
See banco sync for the full sync flow.
Syncing
banco sync # sync all providers
banco sync jira # sync only the jira provider (or use its alias)
If claude exits with an error, Banco will display the error output. If authentication is
pending (e.g. first run with Bedrock), run claude interactively to complete login, then retry.
Dashboard
Running banco with no subcommand opens a full-screen, read-only dashboard for the current
project.
banco
Press q or Ctrl+C to exit.
Layout
━━━━━━━━━━━━━ Status: 2026-01-15 09:30:00 (3d ago) · ok · 1.2 MB
┃ banco ┃ Providers: local, github
━━━━━━━━━━━━━
┌ local ──────────────┬──────────────────┬──────────────┐
│ notes (2) │ tasks (4) │ bookmarks (1)│
│ My first note │ backlog (2) │ Rust docs │
│ Meeting 2026-01 │ Fix login │ │
│ │ Add tests │ │
│ │ doing (1) │ │
│ │ Review PR │ │
└─────────────────────┴──────────────────┴──────────────┘
Header
The top row shows:
| Field | Source |
|---|---|
| Status | Most recent sync timestamp with relative age, config check result, and total project folder size |
| Providers | Enabled providers from .banco/config.yml, always starting with local |
Provider sections
Each provider with at least one non-empty module gets a box. Modules with zero items are hidden. Each visible module is a column:
- notes / bookmarks — header with item count, then up to 5 most recent names
- repos — like notes/bookmarks, but each repo also shows its current git branch and
status, e.g.
my-repo (main) *↟2(see Repo status indicators) - tasks — header with total count, then items grouped by status with up to 5 items per group; task number prefixes are stripped from displayed names
Repo status indicators
Repos render as name (branch) flags, where the flags annotate the git working copy:
| Marker | Meaning |
|---|---|
(branch) | Current branch. Omitted for a detached HEAD or a directory git can’t read |
* | The working copy has uncommitted or untracked changes |
↟N | N local branches are not merged into the current branch |
A clean repo on its default branch shows just name (main) with no flags. The same branch,
dirtiness, and unmerged-branch information is available in banco context JSON
output and in banco tidy repo findings.
If the terminal is too narrow to show item details usefully (less than 16 characters per column), the columns collapse to headers-only — counts remain visible.
The focused provider’s box is drawn in orange. The focused module’s column header is also orange.
Collapsing providers
Press v to collapse the focused provider. A collapsed provider is replaced by a single
summary bar showing its name and per-module item counts, freeing the vertical space for the
expanded providers. Press v again on it to expand it back.
│ ▸ github tasks (4) · repos (2) │
This is a per-project view preference: it is remembered per project and persists across
restarts. It is stored outside the repository in $XDG_STATE_HOME/banco/state.yml (falling
back to ~/.local/state/banco/state.yml), not in .banco/config.yml, so it never appears in
diffs and never leaks between users.
Keyboard shortcuts
| Key | Action |
|---|---|
? | Toggle shortcuts overlay |
c | Open the config editor |
d | Open check panel |
Esc | Close overlay |
j / k | Next / previous provider |
q | Quit |
v | Collapse / expand the focused provider |
Ctrl+C | Quit |
Ctrl+S | Sync, then reload the dashboard with the freshly synced items |
Tab | Next module (overflows to first module of next provider) |
Shift+Tab | Previous module (underflows to last module of previous provider) |
Space | Browse all items in the focused module |
Press ? at any time to show the shortcuts panel as an overlay over the dashboard.
Item browser
Pressing Space on a focused module opens a full-screen list of all items in that module.
┌ local: tasks (12 items) ────────────────────────────────┐
│ filter: _ │
├──────────────────────────────────────────────────────────┤
│ backlog │
│ Fix login bug │
│ Add tests │
│ doing │
│ Review PR │
└──────────────────────────────────────────────────────────┘
Esc/q close ↑↓/Tab navigate type to filter Enter edit
Filtering
Type any characters to fuzzy-filter items. Label/group headers (e.g. status names) are always shown for groups that have at least one matching item, and hidden when all their items are filtered out.
Navigation
| Key | Action |
|---|---|
↑ / ↓ | Previous / next item (wraps around) |
Tab / Shift+Tab | Next / previous item (wraps around) |
Editing
Pressing Enter opens the selected item in $EDITOR (falls back to vi). The dashboard
suspends while the editor runs and resumes when it exits.
Editing is supported for all modules that map to files on disk:
localprovider:notes,tasks- Remote providers (
jira,github,gitlab):tasks
Check panel
Pressing d opens a compact overlay summarising the output of banco check.
┌ check ──────────────────────────────┐
│ │
│ 2 issues found: │
│ │
│ Extraneous directories │
│ ✗ ./archive │
│ │
│ Extraneous module paths │
│ ✗ ./notes/local/scratch.txt │
│ │
│ Esc close │
└─────────────────────────────────────┘
When there are no issues the panel shows a single green confirmation line:
┌ check ──────────────┐
│ │
│ ✓ No issues found │
│ │
│ Esc close │
└─────────────────────┘
The panel is sized to fit its content and centered on the terminal. It is drawn as an overlay on top of the dashboard — the underlying view is not redrawn until the panel is closed.
Press Esc or q to close.
Config editor
Pressing c opens an editor for .banco/config.yml as a master-detail view. The master list
holds a General row (project-wide settings) followed by one row per configured provider.
Providers that are disabled show ✗ off, and providers with validation problems show a ⚠
issue count in red.
┌ config ───────────────────────────────────┐
│ │
│ General │
│ local │
│ github (gh-work) │
│ gitlab ✗ off │
│ jira ⚠ 1 │
│ │
│ ↑↓ move Enter open a add x delete … │
└───────────────────────────────────────────┘
| Key | Action |
|---|---|
↑ / ↓ | Move between rows |
Enter | Open the selected row’s detail view |
a | Add a provider (runs the same interactive flow as banco provider add) |
x / Del | Remove the selected provider from the config (after confirmation) |
Esc / q | Close the editor |
Removing a provider only deletes its entry from .banco/config.yml — synced files already on
disk are left in place. Use banco tidy afterwards to review what is now orphaned.
The built-in local provider cannot be removed, because an absent local entry means “use the
defaults” (every module enabled) — deleting it would reset its configuration rather than turn it
off. To switch local off instead, open its detail view and toggle enabled, or disable
individual modules; both are saved to the config.
Detail views
Opening General edits the project-wide browse block (the command and arguments used to
open URLs). Opening a provider shows a schema-driven form:
┌ github (gh-work) ─────────────────────────┐
│ │
│ alias gh-work │
│ enabled [x] │
│ module tasks [x] │
│ module repos [x] │
│ api_key $GH_TOKEN │
│ host (unset) │
│ projects [2 items] │
│ browse cmd (none) │
│ │
│ ⚠ 0 issues │
└───────────────────────────────────────────┘
Each field is edited in place with Enter:
- alias, string parameters, browse cmd — open a single-line text editor. Clearing the value unsets it (string parameters are removed from the config entirely).
- enabled and module rows — toggle on/off. Toggling a module off adds it to the
provider’s
disabled_modules. - list parameters (e.g.
projects) and browse args — open a list editor whereaadds an entry anddremoves the selected one.
Required parameters that are unset are shown in red, and a live issue count at the bottom
mirrors banco check. Stored values are shown raw — a $GH_TOKEN reference is
displayed as $GH_TOKEN, not its expanded value.
Every change is saved to .banco/config.yml immediately. When you close the editor, the
dashboard rebuilds so any newly enabled or disabled providers and modules are reflected at
once.
Note: saving rewrites
config.ymlthrough the YAML serializer, so hand-written comments and key ordering are not preserved. Edit the file directly if you need to keep those.
init
Run banco init in an empty directory to set up a new Banco project.
Banco creates:
- The directory skeleton for each module (e.g.
tasks/local/backlog,tasks/local/doing,tasks/local/done) - A
misc/directory for files not managed by banco .banco/BANCO.md,AGENTS.md, andCLAUDE.mdfor agentic workflows
banco init
Flags
--update
Overwrites .banco/BANCO.md in an existing project with the version built into
the installed binary. All other project files are left untouched.
Useful after upgrading banco to pick up improvements to the agent instructions.
banco init --update
new
Creates a new item in a module that supports the new capability.
banco new note -l 'label=some/nested/path' -n 'My note'
Pass -n for the item name and -l key=value for each label. Run without flags to use the
interactive TUI, which prompts for all required fields and offers to open the new item in
$EDITOR when done.
When passing a value for an enum label via -l, the value must be one of the allowed strings
defined by the module. Passing an invalid value will cause the command to fail with an error.
template
Creates or edits a template interactively.
banco template
Banco reads the current module structure and presents a selection of available paths (e.g.
notes/local, notes/local/meetings, tasks/local). After selecting a path, banco creates
.banco/templates/<path>/TEMPLATE.md if it does not already exist, then opens it in $EDITOR.
Save and close the editor to finish.
The template will be used as the initial content when creating new items under that path. See Templates for details on how template lookup works.
context
Outputs a minified JSON summary of the project state to stdout. Intended primarily for agents — run it to give an AI assistant full context about the project contents.
banco context # or: banco ctx
banco context --pretty # pretty-print the JSON output
Output format
{
"project": "name of the dir",
"providers": [
{
"name": "local",
"modules": [
{
"name": "notes",
"parameters": [
{
"name": "label",
"type": "string",
"description": "Optional nested path used as a tag (e.g. meetings/2026)"
}
],
"items": [
{
"name": "My first note",
"label": "meetings"
}
]
}
]
}
]
}
provider
Manages providers configured for the current project. Provider configuration is stored in
.banco/config.yml.
banco provider add # add a new provider (interactive)
banco provider list # list configured providers
provider add
Presents a list of available providers to choose from. After selecting one, you are prompted for
an optional alias — an alias is required if a provider of the same kind is already configured.
Banco then walks through each configuration parameter for the chosen provider and saves the
result to .banco/config.yml.
provider list
Prints the name (or alias) of each configured provider.
Editing in the dashboard
The dashboard also offers an interactive config editor (press c) for adding,
removing, enabling, and reconfiguring providers without editing .banco/config.yml by hand.
sync
Pulls data from configured remote providers and writes it to the local filesystem.
banco sync # sync all configured providers
banco sync <name> # sync a specific provider by name or alias
banco sync <name> --module tasks # sync only the tasks module
banco sync <name> --module repos # sync only the repos module
banco sync <name> --pattern "myorg/frontend" # sync only projects matching regex
banco sync <name> --jobs 10 # clone/fetch up to 10 repos at once
--module and --pattern can be combined: banco sync github --module tasks --pattern "myorg/.*".
Sync is non-destructive: it never deletes or overwrites existing files.
Options
| Option | Description |
|---|---|
--module <tasks|repos> | Limit sync to a single module; skips the other. Useful when you only want to fetch issues without cloning repos, or vice versa. |
--pattern <regex> | Only sync projects whose path (owner/repo for GitHub/GitLab) matches this regex. Applied on top of the project list already defined in the provider config. Not applicable to Jira. |
--jobs <n>, -j <n> | Number of repos to clone/fetch concurrently. Defaults to 6. Repo syncing is network-bound, so this is a small fixed value rather than something derived from CPU cores — raising it mainly risks tripping the remote’s connection or rate limits. |
Sync state
After each successful sync, banco writes a timestamp to .banco/sync-state/<provider>. This
records when the last sync completed and is available for informational purposes. The state file
is only written on success, so a failed sync is retried in full on the next run.
Tasks (issues)
Syncing tasks is a two-phase process: fetch then reconcile.
Phase 1 — fetch. Only open/non-done issues are pulled from the remote. The full set of currently-open issues is always retrieved.
Phase 2 — reconcile. After writing the fetched issues, banco scans every local task file. Any task whose ID was not in the fetched set and whose local status is not already done/closed is marked done/closed — it was completed on the remote and simply disappeared from the open results.
| Situation | Action |
|---|---|
| Issue not yet on disk | Creates a new file with frontmatter and initial content |
| Issue title changed | Renames the file; body content is untouched |
| Status or labels changed | Updates frontmatter block; body content is untouched |
| Issue unchanged | Does nothing |
| Local open task absent from remote set | Marks the local file as done/closed |
Repos
| Situation | Action |
|---|---|
| Repo not yet on disk | Clones via SSH |
| Repo already on disk | Runs git fetch --all --prune |
Within a provider, repos are cloned/fetched in parallel (see --jobs); git’s own
progress output is suppressed in favour of a single summary line. A failed clone
aborts the sync; a failed fetch on an existing repo is reported as a warning and
does not stop the run.
browse
Opens a URL from the project in the system browser.
banco browse
Presents a fuzzy-select menu: provider → module → item → page (if the item has more than one
page). The selected URL is opened with the configured browser, the $BROWSER environment
variable, xdg-open, open, or cmd /c start, tried in that order.
Configuring the browser
By default, banco browse delegates to the $BROWSER environment variable or the OS default
opener. You can override this in .banco/config.yml.
Global (all providers)
browse:
command: firefox
args: ['-P', 'my-profile']
Per-provider
providers:
- name: gitlab
enabled: true
browse:
command: chromium
args: ['--profile-directory=Work']
The per-provider setting takes precedence over the global one. Both take precedence over
$BROWSER and the OS default.
args is optional and defaults to an empty list. The URL is always appended as the last argument.
Browseable items
| Provider | Module | Pages | URL source |
|---|---|---|---|
local | bookmarks | default | First line of the bookmark .md file |
github | tasks | default | Derived from filename: {host}/{owner}/{repo}/issues/{n} ¹ |
github | repos | Repository · Pull Requests · Actions | Derived from the cloned repo’s git remote origin URL |
gitlab | repos | Repository · Merge Requests · Pipelines | Derived from the cloned repo’s git remote origin URL |
gitlab | tasks | default | Derived from the repo’s remote URL: {repo_url}/-/issues/{iid} ¹ |
¹ Virtual items — the URL is not stored anywhere in the task file; it is reconstructed at
browse time from the filename (issue number and title) and the provider’s host or the matching
repo’s git remote URL. A GitLab task item is only surfaced if a matching cloned repository is
found under repos/<provider>/, since that is where the namespace URL is resolved from.
check
Scans the project directory for content that does not belong to any module and reports it.
banco check
Exits with code 0 if no issues are found, or 1 if any are reported — making it suitable for
use in scripts or CI pipelines.
What is checked
Extraneous top-level directories
Any directory at the project root that is not owned by a module (notes/, tasks/,
bookmarks/, repos/) and is not misc/ or a hidden directory (e.g. .banco/, .git/) is
flagged as extraneous.
extraneous directory: archive/
Extraneous paths within modules
Module directories follow the layout {module}/{provider}/{item}. The check enforces this at
two levels.
Provider subdirectory — every direct subdirectory of a module root must match a configured
provider name (or alias). local is always valid; any other provider you have added via
banco provider add is also valid.
extraneous path: repos/banco/ ← "banco" is not a configured provider
Provider contents — inside each {module}/local/ directory the expected structure is:
| Module | Flagged as extraneous |
|---|---|
notes | Non-.md files anywhere under notes/local/ |
tasks | Files directly in tasks/local/; subdirectories other than backlog/, doing/, done/; non-.md files inside status subdirectories |
bookmarks | Any subdirectory under bookmarks/local/; non-.md files under bookmarks/local/ |
repos | Non-directory entries under repos/local/ |
extraneous path: notes/local/scratch.txt
extraneous path: tasks/local/wip/
extraneous path: tasks/local/doing/notes.csv
extraneous path: repos/local/README.md
Provider configuration
Every provider entry in .banco/config.yml is validated against its known schema:
- Unknown parameters — keys in the
config:block that are not recognised by the provider are flagged. - Missing required parameters — keys that the provider requires but are absent from the
config:block are flagged. - Unknown disabled modules — names in the
disabled_modules:list that the provider does not implement are flagged. - Unknown provider — an entry whose
nameis not a known provider is flagged.
config: provider 'github': unknown parameter 'token'
config: provider 'jira' (alias 'work-jira'): missing required parameter 'agent_backend'
config: provider 'github': unknown module 'task' in disabled_modules
config: provider 'local': unknown parameter 'bogus_key'
The local provider takes no configuration parameters, so any key under its config: block is
flagged as an unknown parameter. Its disabled_modules list is validated against the modules it
implements (notes, tasks, bookmarks, repos).
Unmanaged content
If you need to keep files that are intentionally outside any module, place them in misc/ —
banco check will never flag its contents. See misc.
Dashboard integration
The same check runs inside the interactive dashboard. The Status header shows a green ok
or a red issue count at a glance. Press d to open the check panel,
a compact overlay that lists the findings without leaving the dashboard.
tidy
Reports module data that the current configuration no longer backs — repositories dropped from a provider, task trees whose syncing was turned off, and local items you may want to retire. The output is JSON, intended for agents (see the tidy skill).
banco tidy [--module <name>] [--pretty]
tidy is detection only — it never deletes anything. It compares what is on disk against
.banco/config.yml and prints what no longer belongs, leaving every removal decision to you.
Unlike check, which flags content that was never part of a module, tidy flags
content that was synced or created but has since become stale because the configuration changed.
Options
| Flag | Description |
|---|---|
--module <name> | Limit the scan to one module: repos, tasks, notes, bookmarks |
--pretty | Pretty-print the JSON output |
Local modules (notes, bookmarks) are only scanned when requested explicitly with --module,
since they have no configuration to compare against — the scan instead surfaces their content for
your review.
Output
A JSON object with four arrays: repos, tasks, local, and modules.
repos
Each synced repository directory that no longer matches the configuration, with a reason and a
git safety summary so nothing is lost on removal.
{
"provider": "github",
"name": "old-service",
"path": "repos/github/old-service",
"reason": "removed_from_config",
"git": {
"branch": "main",
"uncommitted_changes": false,
"untracked_files": 2,
"unmerged_branches": 1,
"unpushed_commits": 1,
"local_only_branches": ["spike"],
"stashes": 0,
"safe_to_remove": false
}
}
reason is one of:
| Reason | Meaning |
|---|---|
removed_from_config | Dropped from the provider’s explicit projects list |
no_longer_matches_pattern | No longer matched by the provider’s projects_pattern |
provider_disabled | The provider is configured with enabled: false |
provider_removed | The provider is gone from .banco/config.yml entirely |
safe_to_remove is true only when the working copy holds nothing that would be lost. When git
cannot be inspected (e.g. not a git repository), a git.error field is set and safe_to_remove
stays false.
branch (current branch, omitted for a detached HEAD) and unmerged_branches (local branches
not merged into the current branch) are decision context rather than safety gates — they do not
affect safe_to_remove, but a repo on a feature branch or with unmerged work is worth a mention
before removal.
tasks
Each task directory whose issues are no longer synced, with file counts split by status.
{
"provider": "github",
"path": "tasks/github",
"reason": "module_disabled",
"files": 12,
"open": 5,
"closed": 7
}
reason is one of module_disabled (the module is listed in the provider’s
disabled_modules), removed_from_config, provider_disabled, or provider_removed.
Per-project detection (removed_from_config) applies to GitHub projects and to GitLab projects
configured via an explicit projects list. The module_disabled reason applies to both the
tasks and repos modules, and to the local provider as well — turning repos or tasks
off for local (or disabling the whole local provider) flags repos/local and tasks/local
just as it does for a remote provider. Local repo findings carry the same git safety summary.
local
When --module notes or --module bookmarks is passed, each item is listed with hints about
whether it holds content worth keeping.
{
"module": "bookmarks",
"path": "bookmarks/local/tools/ripgrep.md",
"has_url": true,
"body_lines": 3,
"modified": "2026-05-14"
}
modules
Each whole module directory (repos/, tasks/, notes/, bookmarks/) that no enabled
provider backs anymore — the module is off for the local provider and no remote provider
implements it with the module enabled. This is the headline that an entire top-level directory
is now stale; the per-subtree entries in repos/tasks still detail what’s inside it.
{
"module": "repos",
"path": "repos",
"reason": "no_provider_backs_module",
"entries": 3
}
entries is the number of immediate entries under the directory (provider subdirs, label dirs,
or files) — a quick measure of how much is there. As with everything else tidy reports,
removing the directory is your decision; review the repos/tasks findings (and their git
safety summaries) before deleting a whole tree.
Removal is yours
tidy never deletes. Review the report and remove only what you choose — the bundled
tidy skill drives an agent through exactly this: it presents the findings, warns
about anything that would be lost, and removes only what you confirm.
skills
Installs agent skills into the current project. Skills are bundled into the banco binary and written out on install.
banco skills install <agent> # install all bundled skills for an agent
banco skills list # list installed and available skills
skills install
Installs every bundled skill for the given agent. The agent argument is required and determines where the skills are written:
| Agent | Skills directory |
|---|---|
claude | .claude/skills/ |
banco skills install claude
Each skill is written to <skills-dir>/<skill-name>/SKILL.md. For claude, this is the location
Claude Code discovers project skills from, so installed skills become invokable immediately.
The command is idempotent: re-running it overwrites the SKILL.md files so they stay up to date
with the bundled version. Passing an unknown agent fails with the list of supported agents.
skills list
Prints the skills currently installed for claude and the bundled skills still available to
install.
Bundled skills
| Skill | Description |
|---|---|
hello-world | A minimal example skill that greets the user; useful for verifying that installed skills are discovered and invokable. |
tidy | Finds and removes module data the configuration no longer backs, warning about anything that would be lost first. Drives banco tidy. |
completions
Prints a shell completion script to stdout. Supported shells: bash, fish, zsh, elvish,
powershell.
banco completions bash # generate bash completions
banco completions zsh # generate zsh completions
banco completions fish # generate fish completions
To enable completions for your current shell session, source the output directly:
source <(banco completions bash)
To persist completions, write the output to the appropriate location for your shell. For example, on most Linux systems for bash:
banco completions bash > ~/.local/share/bash-completion/completions/banco
Templates
When creating an item, Banco looks for a template file inside .banco/templates/. The lookup is
hierarchical — the most specific template wins, falling back to progressively less specific ones.
.banco/
└── templates/
├── tasks/
│ ├── TEMPLATE.md ← applies to all tasks from any provider
│ ├── local/
│ │ └── TEMPLATE.md ← applies to local tasks only
│ ├── github/
│ │ ├── TEMPLATE.md ← applies to all GitHub tasks
│ │ └── myorg/
│ │ └── TEMPLATE.md ← applies to tasks from myorg (takes precedence)
│ ├── gitlab/
│ │ └── TEMPLATE.md ← applies to all GitLab tasks
│ └── jira/
│ └── TEMPLATE.md ← applies to all JIRA tasks
└── notes/
└── local/
├── TEMPLATE.md ← applies to all local notes
└── meetings/
└── TEMPLATE.md ← applies to notes in meetings/ (takes precedence)
Lookup order
The most specific template found is used. For example, when syncing a GitHub issue from
myorg/my-repo, Banco checks:
.banco/templates/tasks/github/myorg/my-repo/TEMPLATE.md.banco/templates/tasks/github/myorg/TEMPLATE.md.banco/templates/tasks/github/TEMPLATE.md.banco/templates/tasks/TEMPLATE.md
For a JIRA issue:
.banco/templates/tasks/jira/TEMPLATE.md.banco/templates/tasks/TEMPLATE.md
The first match found is used as the initial content of the new file. If no template is found, the file is created empty. Templates are only applied when a file is first created — subsequent syncs update frontmatter only and never touch the body.
Use banco template to create or edit templates interactively.
misc
The misc/ directory is created by banco init at the root of every Banco project.
It is not managed by Banco — no command reads from or writes to it.
Its purpose is to give you a free-form space for files and directories that don’t belong to
any module (notes, tasks, bookmarks, repos).
Typical uses include scratch files, one-off scripts, reference documents, or any other
content you want to keep co-located with your Banco project without it being picked up by
context, browse, or sync.
my-project/
├── .banco/
├── misc/ ← unmanaged; store anything here
├── notes/
├── tasks/
└── ...