Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

banco

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 on init
  • AGENTS.md — reads .banco/BANCO.md and is meant for user-defined instructions; never overwritten by banco
  • CLAUDE.md — reads AGENTS.md; never overwritten by banco

.banco/BANCO.md instructs agents to:

  • Run banco context first to get a JSON snapshot of the project state (providers, modules, items, and the labels required to build commands)
  • Always use banco new to create items — never write files directly
  • Derive label names and values from the context rather than guessing
  • Use status and tags metadata 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/.

ParameterTypeRequiredDescription
labelstringnoNested 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:

StatusDirectory
awaitingtasks/local/backlog/
doingtasks/local/doing/
donetasks/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

ParameterTypeRequiredDescription
statusenum: awaiting/doing/doneyesTask 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

ParameterTypeRequiredDescription
groupstringnoGroup file to add the bookmark to (default: default)
urlstringyesThe 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:

FieldMeaning
branchCurrent branch, or null for a detached HEAD / unreadable repo
dirtytrue when the working copy has uncommitted or untracked changes
unmerged_branchesCount 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

ModuleDirectoryItemsParameters
taskstasks/local/Markdown files, prefixed 0001 -status (enum: awaiting / doing / done)
notesnotes/local/Markdown fileslabel (string, optional — nested tag, e.g. meetings/2026)
bookmarksbookmarks/local/Markdown fileslabel (string, optional — nested tag, e.g. tools/rust), url (string)
reposrepos/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.

ParameterRequiredDescription
api_keyyesGitHub personal access token
hostnoGitHub instance URL (default: https://github.com) — set for GitHub Enterprise Server
projectsno †Explicit list of project paths in owner/repo format
projects_patternno †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.mdgithub/<owner>/TEMPLATE.mdgithub/TEMPLATE.mdtasks/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.

ParameterRequiredDescription
api_keyyesGitLab personal access token
hostnoGitLab instance URL (default: https://gitlab.com)
projectsno †Explicit list of project paths in namespace/project format
projects_patternno †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.mdgitlab/TEMPLATE.mdtasks/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 claude CLI must be installed and available in your PATH
  • The Atlassian Rovo MCP server must be configured in your claude setup
  • If using Claude via AWS Bedrock, run claude interactively at least once to complete authentication before running banco sync

Configuration

Set interactively via banco provider add.

ParameterRequiredDescription
hostyesJIRA instance URL (e.g. https://yourorg.atlassian.net) — used to construct browse URLs
projectyesProject key to sync (e.g. ENG)
labelsnoList of labels to filter issues by — passed to the agent at fetch time; omit to fetch all
agent_backendyesAgent 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.mdtasks/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    │              │
└─────────────────────┴──────────────────┴──────────────┘

The top row shows:

FieldSource
StatusMost recent sync timestamp with relative age, config check result, and total project folder size
ProvidersEnabled 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:

MarkerMeaning
(branch)Current branch. Omitted for a detached HEAD or a directory git can’t read
*The working copy has uncommitted or untracked changes
↟NN 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

KeyAction
?Toggle shortcuts overlay
cOpen the config editor
dOpen check panel
EscClose overlay
j / kNext / previous provider
qQuit
vCollapse / expand the focused provider
Ctrl+CQuit
Ctrl+SSync, then reload the dashboard with the freshly synced items
TabNext module (overflows to first module of next provider)
Shift+TabPrevious module (underflows to last module of previous provider)
SpaceBrowse 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.

KeyAction
/ Previous / next item (wraps around)
Tab / Shift+TabNext / 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:

  • local provider: 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  …  │
         └───────────────────────────────────────────┘
KeyAction
/ Move between rows
EnterOpen the selected row’s detail view
aAdd a provider (runs the same interactive flow as banco provider add)
x / DelRemove the selected provider from the config (after confirmation)
Esc / qClose 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 where a adds an entry and d removes 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.yml through 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, and CLAUDE.md for 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

OptionDescription
--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.

SituationAction
Issue not yet on diskCreates a new file with frontmatter and initial content
Issue title changedRenames the file; body content is untouched
Status or labels changedUpdates frontmatter block; body content is untouched
Issue unchangedDoes nothing
Local open task absent from remote setMarks the local file as done/closed

Repos

SituationAction
Repo not yet on diskClones via SSH
Repo already on diskRuns 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

ProviderModulePagesURL source
localbookmarksdefaultFirst line of the bookmark .md file
githubtasksdefaultDerived from filename: {host}/{owner}/{repo}/issues/{n} ¹
githubreposRepository · Pull Requests · ActionsDerived from the cloned repo’s git remote origin URL
gitlabreposRepository · Merge Requests · PipelinesDerived from the cloned repo’s git remote origin URL
gitlabtasksdefaultDerived 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:

ModuleFlagged as extraneous
notesNon-.md files anywhere under notes/local/
tasksFiles directly in tasks/local/; subdirectories other than backlog/, doing/, done/; non-.md files inside status subdirectories
bookmarksAny subdirectory under bookmarks/local/; non-.md files under bookmarks/local/
reposNon-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 name is 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

FlagDescription
--module <name>Limit the scan to one module: repos, tasks, notes, bookmarks
--prettyPretty-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:

ReasonMeaning
removed_from_configDropped from the provider’s explicit projects list
no_longer_matches_patternNo longer matched by the provider’s projects_pattern
provider_disabledThe provider is configured with enabled: false
provider_removedThe 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:

AgentSkills 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

SkillDescription
hello-worldA minimal example skill that greets the user; useful for verifying that installed skills are discovered and invokable.
tidyFinds 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:

  1. .banco/templates/tasks/github/myorg/my-repo/TEMPLATE.md
  2. .banco/templates/tasks/github/myorg/TEMPLATE.md
  3. .banco/templates/tasks/github/TEMPLATE.md
  4. .banco/templates/tasks/TEMPLATE.md

For a JIRA issue:

  1. .banco/templates/tasks/jira/TEMPLATE.md
  2. .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/
└── ...