workspace

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 21, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package workspace provides workspace/project management.

Package workspace provides workspace discovery functionality.

Discovery helpers for pkg/workspace - see workspace.go for the main package doc. the web UI can offer to register them. It is deliberately separate from pkg/workspace to avoid coupling registration concerns with filesystem scanning or network calls.

Two source types are supported:

  • Local filesystem: walk a directory, emit every .git repo
  • GitHub: list the authenticated user's repositories via the REST API

Each helper returns a slice of Candidate with a consistent shape so the caller (handlers/workspaces.go) can serialize to JSON without additional shaping.

Package workspace provides workspace/project management.

Package workspace provides workspace/project management.

Package workspace provides workspace and project management for bc.

A workspace represents a project directory containing bc configuration and agent state in .bc/settings.json.

Basic Usage

Find the current workspace:

ws, err := workspace.Find(".")
if err != nil {
    log.Fatal("not in a bc workspace")
}
fmt.Println("Workspace:", ws.Name())

Initialize a new workspace:

ws, err := workspace.Init("/path/to/project")
if err != nil {
    log.Fatal(err)
}

Load an existing workspace:

ws, err := workspace.Load("/path/to/project")
if err != nil {
    log.Fatal(err)
}

Index

Constants

View Source
const (
	// PreferencesFileName is the canonical workspace preferences filename (M11c+).
	PreferencesFileName = "preferences.json"
	// LegacySettingsFileName is the pre-M11c filename, still read for
	// backward compatibility.
	LegacySettingsFileName = "settings.json"
)

Preferences / settings filename constants.

Before M11c: every workspace stored its config at <StateDir>/settings.json. From M11c onward the canonical filename is preferences.json; the legacy file is read as a fallback and promoted on first write.

View Source
const ConfigVersion = 2

ConfigVersion is the current config schema version.

View Source
const CurrentRegistryVersion = 2

CurrentRegistryVersion is the current registry schema version. v1 = legacy (no IDs). v2 = IDs + github_* + last_used_at.

View Source
const DefaultBaseRole = `` /* 2540-byte string literal not displayed */

DefaultBaseRole is the foundational role all other roles inherit from. It provides the bc MCP server so every agent can communicate with the workspace.

View Source
const DefaultRootRole = `` /* 619-byte string literal not displayed */

DefaultRootRole returns the default content for root.md.

View Source
const NameMaxLength = 30

User name limits.

Variables

View Source
var (
	ErrInvalidVersion          = errors.New("version must be 2")
	ErrMissingDefaultProvider  = errors.New("providers.default is required")
	ErrDefaultProviderNotFound = errors.New("providers.default references undefined provider")
	ErrInvalidTheme            = errors.New("ui.theme must be one of: dark, light, matrix, synthwave, high-contrast")
	ErrInvalidThemeMode        = errors.New("ui.mode must be one of: auto, dark, light")
	ErrNameTooLong             = errors.New("user.name is too long")
)

Validation errors.

View Source
var DefaultRoles = map[string]string{
	"feature-dev": `---
name: feature-dev
description: Feature developer — implements tasks in isolated worktrees
parent_roles:
  - base
mcp_servers:
  - github
secrets:
  - GITHUB_PERSONAL_ACCESS_TOKEN
prompt_start: |
  Check #engineering channel for any new assignments or updates.
---

# Feature Developer

You implement features, fix bugs, and write tests in an isolated git worktree.

## Workflow
1. Read the assigned issue, create a feature branch (feat/<issue>-<slug>)
2. Implement with tests, run make check
3. Open a PR and post to #merge when ready for review
`,
	"go-reviewer": `---
name: go-reviewer
description: Go code quality reviewer
parent_roles:
  - feature-dev
---

# Go Reviewer

Review Go pull requests for correctness, security, and test coverage.
Use the github MCP to fetch PR diffs and leave inline review comments.
Block merges on security issues or broken tests; suggest rather than block on style.
`,
	"web-reviewer": `---
name: web-reviewer
description: Web/TypeScript UI reviewer
parent_roles:
  - feature-dev
---

# Web Reviewer

Review React/TypeScript pull requests for correctness and component patterns.
Use the github MCP to fetch PR diffs and leave inline review comments.
Hooks cannot be tested without a DOM in Ink — test exported helpers instead.
`,
	"designer": `---
name: designer
description: Design system and Web UI specialist
parent_roles:
  - feature-dev
---

# Designer

Maintain the design token system, build React/Ink TUI components, and implement
CSS/Tailwind changes for the web dashboard. Accessibility is non-negotiable.
`,
	"product-manager": `---
name: product-manager
description: Product coordination and epic management
parent_roles:
  - base
mcp_servers:
  - github
secrets:
  - GITHUB_PERSONAL_ACCESS_TOKEN
---

# Product Manager

Break down goals into epics and issues, assign work to agents, and review
completed work against acceptance criteria. Use GitHub issues for all tracking.
`,
	"docs": `---
name: docs
description: Documentation writer
parent_roles:
  - feature-dev
---

# Documentation Writer

Write and maintain README, CONTRIBUTING, API docs, and CLAUDE.md.
Update docs in the same PR as the feature. Use concrete examples.
`,
}

DefaultRoles contains the built-in role definitions for the bc agent team. These are written to .bc/roles/ if the files don't already exist.

View Source
var ErrGithubNotAuthenticated = errors.New("github not authenticated")

ErrGithubNotAuthenticated indicates no token is configured or it was rejected by the API.

View Source
var ValidModes = []string{"auto", "dark", "light"}

Valid theme modes.

View Source
var ValidThemes = []string{"dark", "light", "matrix", "synthwave", "high-contrast"}

Valid theme names.

Functions

func BCHome

func BCHome() (string, error)

BCHome returns the global bc home directory (~/.bc). Respects BC_HOME env var override.

func Clone added in v0.2.0

func Clone(ctx context.Context, url, target, name string) (string, error)

Clone runs `git clone <url> <target>/<name>` to materialize a repository. Returns the absolute path of the new checkout on success.

func CloneURLFromRepo added in v0.2.0

func CloneURLFromRepo(repo Repo, preferSSH bool) string

CloneURLFromRepo picks the best clone URL for a Repo: SSH if a credential helper appears configured, otherwise HTTPS. Returns the CloneURL field if no URL was provided.

func ComputeWorkspaceID added in v0.2.0

func ComputeWorkspaceID(path string) string

ComputeWorkspaceID returns the stable 12-char hex ID for an absolute path. It is the first registryIDLength hex chars of sha256(absPath). Empty path returns an empty string.

func ConfigPath

func ConfigPath(rootDir string) string

ConfigPath returns the standard config file path for a workspace root. Checks the global state dir first (preferences.json then settings.json), then the legacy <rootDir>/.bc/ directory. When no file exists anywhere yet, returns the canonical preferences.json path under the global dir so callers writing a fresh config land in the right place.

func DaemonAddrPath added in v0.2.0

func DaemonAddrPath() (string, error)

DaemonAddrPath returns the path to the user-global bcd address file (~/.bc/daemon.addr). `bc up` writes the currently-listening address (scheme + host:port, e.g. "http://127.0.0.1:8080") so the CLI and agents can locate the daemon without requiring BC_DAEMON_ADDR to be set when the daemon runs on a non-default port.

func DaemonLogPath added in v0.2.0

func DaemonLogPath() (string, error)

DaemonLogPath returns the path to the user-global bcd log file (~/.bc/daemon.log). Same rationale as DaemonPidPath: one bcd, one log.

func DaemonPidPath added in v0.2.0

func DaemonPidPath() (string, error)

DaemonPidPath returns the path to the user-global bcd pid file (~/.bc/daemon.pid). The bcd daemon is user-scoped — a single process serves every workspace — so its pid lives outside any per-workspace directory.

func DataDir added in v0.2.0

func DataDir(id string) (string, error)

DataDir returns the per-workspace runtime directory for a given workspace ID — the M11 replacement for the legacy <project>/.bc/ sidecar.

Returns ~/.bc/workspaces/<id>/ (respecting BC_HOME). Pass the ID from ComputeWorkspaceID(absRootDir) or from a RegistryEntry.

This path holds every piece of runtime state for the workspace: preferences.json, state.db, cron.db, agents/, logs/ — nothing lives under the project directory anymore.

func DeleteGithubToken added in v0.2.0

func DeleteGithubToken() error

DeleteGithubToken removes the token file, ignoring "not found".

func DiscoverAndRegister

func DiscoverAndRegister(opts DiscoverOptions) (int, error)

DiscoverAndRegister discovers workspaces and adds new ones to the registry. Returns the number of newly registered workspaces.

func EnsureBCHome

func EnsureBCHome() error

EnsureBCHome creates the global ~/.bc directory structure if it doesn't exist.

func EnsureGlobalDir added in v0.2.0

func EnsureGlobalDir() (string, error)

EnsureGlobalDir makes sure ~/.bc/ exists with 0750 permissions. It is idempotent and safe to call from any process path that needs to write a global asset. Returns the resolved BCHome path for convenience.

func FormatRoleFile

func FormatRoleFile(role *Role) (string, error)

FormatRoleFile formats a role as a markdown file with YAML frontmatter.

func GithubConnected added in v0.2.0

func GithubConnected() bool

GithubConnected returns true if a non-empty token is on disk.

func GithubTokenPath added in v0.2.0

func GithubTokenPath() (string, error)

GithubTokenPath returns the filesystem location of the stored token. The directory is created as 0700 on first write.

func GlobalCostsDB added in v0.2.0

func GlobalCostsDB() (string, error)

GlobalCostsDB returns the path to the user-global cost ledger (~/.bc/costs.db). Every cost record is tagged with a workspace_id so cross-workspace analytics work without data duplication.

func GlobalDir

func GlobalDir() string

GlobalDir returns the path to ~/.bc/. Honors BC_HOME so test isolation (or power-user overrides) route every registry read/write through the same sandbox — previously this ignored BC_HOME and always read the host's real registry, which let tests corrupt production state.

func GlobalMCPConfig added in v0.2.0

func GlobalMCPConfig() (string, error)

GlobalMCPConfig returns the path to the user-global MCP trust config (~/.bc/mcps.json). Servers listed here are available to every workspace unless the workspace overrides them locally.

func GlobalSecretsVault added in v0.2.0

func GlobalSecretsVault() (string, error)

GlobalSecretsVault returns the path to the user-global secrets vault (~/.bc/secrets.vault). This is a SQLite database holding the user's encrypted key/value secrets shared across workspaces.

func GlobalStateDir

func GlobalStateDir(rootDir string) (string, error)

GlobalStateDir returns the state directory for a workspace at ~/.bc/workspaces/<workspace-id>/, where the ID is the 12-char sha256 prefix produced by ComputeWorkspaceID. Matches RegistryEntry.DataDir so the migration and the registry agree on a single path. Respects BC_STATE_DIR env var override.

func GlobalTemplatesDir added in v0.2.0

func GlobalTemplatesDir() (string, error)

GlobalTemplatesDir returns the user-global templates directory (~/.bc/templates/). Templates here apply across all workspaces; each workspace may override a template by placing a file with the same name under <ws>/.bc/templates/.

func GlobalToolsConfig added in v0.2.0

func GlobalToolsConfig() (string, error)

GlobalToolsConfig returns the path to the user-global CLI tools registry (~/.bc/tools.json). Tools here describe machine-level dependencies (claude, bun, docker helpers, etc.) — there is no per-workspace override for this file.

func IsWorkspace

func IsWorkspace(dir string) bool

IsWorkspace checks if a directory is a workspace. Checks legacy .bc/ directory and global state dir (~/.bc/workspaces/<id>/).

func NormalizeNickname

func NormalizeNickname(nickname string) (string, error)

NormalizeNickname ensures a nickname has the @ prefix and is valid.

func NormalizeRoleName

func NormalizeRoleName(name string) string

NormalizeRoleName canonicalises a role name by replacing underscores with hyphens and lower-casing, preventing duplicates like "product_manager" vs "product-manager".

func ParseHTMLURL added in v0.2.0

func ParseHTMLURL(raw string) (owner, name string)

ParseHTMLURL extracts owner/name from a github.com HTTPS URL for display purposes. Returns ("", "") on non-github hostnames.

func ReadGithubToken added in v0.2.0

func ReadGithubToken() (string, error)

ReadGithubToken returns the stored PAT, or "" if none. Any read error other than ENOENT is returned so the caller can distinguish "not set" from "read failed".

func RegistryPath

func RegistryPath() string

RegistryPath returns the path to ~/.bc/workspaces.json (BC_HOME-aware via GlobalDir).

func SetGithubAPIBase added in v0.2.0

func SetGithubAPIBase(base string) func()

SetGithubAPIBase is a test hook for retargeting the API base (e.g. at an httptest.Server). Not intended for production use.

func UserRCConfigPath

func UserRCConfigPath() string

UserRCConfigPath returns the path to the user's .bcrc file. Default: ~/.bcrc

func UserRCExists

func UserRCExists() bool

UserRCExists returns true if ~/.bcrc exists.

func ValidateGithubToken added in v0.2.0

func ValidateGithubToken(ctx context.Context, token string) (string, error)

ValidateGithubToken performs a lightweight /user call to verify the token works. Returns the GitHub login on success.

func ValidateNickname

func ValidateNickname(nickname string) error

ValidateNickname validates a nickname and returns an error if invalid.

func WriteGithubToken added in v0.2.0

func WriteGithubToken(token string) error

WriteGithubToken persists the PAT to ~/.bc/github-token with 0600 perms. Empty token clears the file.

Types

type AliasConflictError

type AliasConflictError struct {
	Alias        string
	ExistingPath string
}

AliasConflictError indicates the alias is already in use.

func (*AliasConflictError) Error

func (e *AliasConflictError) Error() string

type BitbucketGatewayConfig added in v0.2.1

type BitbucketGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

BitbucketGatewayConfig configures the Bitbucket webhook gateway adapter.

type Candidate added in v0.2.0

type Candidate struct {
	Path              string `json:"path"`
	Name              string `json:"name"`
	GitRemote         string `json:"git_remote,omitempty"`
	GithubURL         string `json:"github_url,omitempty"`
	HasBC             bool   `json:"has_bc"`
	AlreadyRegistered bool   `json:"already_registered"`
}

Candidate describes one discovered repository/workspace.

func ScanLocal added in v0.2.0

func ScanLocal(ctx context.Context, opts ScanOptions) ([]Candidate, error)

ScanLocal walks opts.Root looking for Git repositories (directories containing a .git entry, file or dir) and returns one Candidate per hit. It is safe to call with an unresolvable or inaccessible Root — the error is returned without partial results.

type Config

type Config struct {
	User      UserConfig      `json:"user"`
	Providers ProvidersConfig `json:"providers"`
	Gateways  GatewaysConfig  `json:"gateways"`
	Runtime   RuntimeConfig   `json:"runtime"`
	Storage   StorageConfig   `json:"storage"`
	Server    ServerConfig    `json:"server"`
	Cron      CronConfig      `json:"cron"`
	Logs      LogsConfig      `json:"logs"`
	UI        UIConfig        `json:"ui"`
	Version   int             `json:"version"`
}

Config represents the JSON-based workspace configuration for bc.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns sensible defaults for a new workspace.

func LoadConfig

func LoadConfig(path string) (*Config, error)

LoadConfig reads and parses a JSON config file.

If path is a directory, LoadConfig treats it as a state dir and looks for preferences.json first (M11c+), falling back to the legacy settings.json. When only the legacy file is present it is read in place; the caller is responsible for writing the promoted file via Save() or LoadConfig's higher-level wrappers.

If path points at a file, it is read directly.

func ParseConfig

func ParseConfig(data []byte) (*Config, error)

ParseConfig parses JSON data into a Config.

func (*Config) FillDefaults

func (c *Config) FillDefaults()

FillDefaults fills zero-valued fields with defaults. Called after ParseConfig to handle configs from older versions.

func (*Config) GetDefaultProvider

func (c *Config) GetDefaultProvider() string

GetDefaultProvider returns the default AI provider name.

func (*Config) GetPreferredTool

func (c *Config) GetPreferredTool(rc *UserRCConfig) string

GetPreferredTool returns the first available preferred tool from .bcrc.

func (*Config) GetProvider

func (c *Config) GetProvider(name string) *ProviderConfig

GetProvider returns an AI provider's configuration by name.

func (*Config) HasProviderDefined

func (c *Config) HasProviderDefined(name string) bool

HasProviderDefined checks if an AI provider is configured.

func (*Config) ListProviders

func (c *Config) ListProviders() []string

ListProviders returns the names of all configured AI providers.

func (*Config) MergeWithUserRC

func (c *Config) MergeWithUserRC(rc *UserRCConfig)

MergeWithUserRC merges user-level defaults from .bcrc into a workspace config.

func (*Config) Save

func (c *Config) Save(path string) error

Save writes the config to a JSON file atomically (temp+rename).

func (*Config) Validate

func (c *Config) Validate() error

Validate checks the config for required fields and consistency.

type CronConfig

type CronConfig struct {
	PollIntervalSeconds int `json:"poll_interval_seconds"`
	JobTimeoutSeconds   int `json:"job_timeout_seconds"`
}

CronConfig configures the cron/job scheduler.

type DatadogGatewayConfig added in v0.2.1

type DatadogGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

DatadogGatewayConfig configures the Datadog webhook gateway adapter.

type DiscordGatewayConfig

type DiscordGatewayConfig struct {
	BotToken string `json:"bot_token"`
	Enabled  bool   `json:"enabled"`
}

DiscordGatewayConfig configures the Discord gateway adapter.

type DiscoverOptions

type DiscoverOptions struct {
	// ScanPaths additional paths to scan for workspaces
	ScanPaths []string
	// MaxDepth maximum directory depth to scan (default 3)
	MaxDepth int
	// IncludeCached includes workspaces from the global registry (~/.bc/workspaces.json)
	IncludeCached bool
	// ScanHome scans ~/Projects and ~/Developer directories
	ScanHome bool
}

DiscoverOptions configures workspace discovery.

func DefaultDiscoverOptions

func DefaultDiscoverOptions() DiscoverOptions

DefaultDiscoverOptions returns sensible defaults for discovery.

type DiscoveredWorkspace

type DiscoveredWorkspace struct {
	Path      string // Absolute path to workspace root
	Name      string // Workspace name (from config or directory name)
	IsV2      bool   // True if v2 (TOML) workspace
	FromCache bool   // True if found in registry (not disk scan)
}

DiscoveredWorkspace represents a workspace found during discovery.

func Discover

func Discover(opts DiscoverOptions) ([]DiscoveredWorkspace, error)

Discover finds all bc workspaces on the machine. It checks the global registry and optionally scans common directories.

type DockerRuntimeConfig

type DockerRuntimeConfig struct {
	ExtraMounts      []string `json:"extra_mounts"`
	Image            string   `json:"image"`
	Network          string   `json:"network"`
	DockerSocketPath string   `json:"docker_socket_path"`
	MemoryMB         int64    `json:"memory_mb"`
	CPUs             float64  `json:"cpus"`
}

DockerRuntimeConfig configures Docker container settings for agents.

type FeishuGatewayConfig added in v0.2.1

type FeishuGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

FeishuGatewayConfig configures the Feishu/Lark event subscription webhook adapter.

type GatewaysConfig

type GatewaysConfig struct {
	// Telegram is the single default Telegram bot (key "telegram").
	// Deprecated: prefer Telegrams map for multi-bot setups.
	Telegram *TelegramGatewayConfig `json:"-"`
	Discord  *DiscordGatewayConfig  `json:"discord,omitempty"`
	Slack    *SlackGatewayConfig    `json:"slack,omitempty"`
	// Telegrams holds zero or more Telegram bots keyed by label.
	// A plain "telegram" key is stored under label "".
	Telegrams map[string]*TelegramGatewayConfig `json:"-"`
	// GitHubs holds zero or more GitHub webhook configs keyed by label.
	// A plain "github" key is stored under label "".
	GitHubs map[string]*GitHubGatewayConfig `json:"-"`
	// Webhooks holds zero or more generic webhook configs keyed by label.
	// A plain "webhook" key is stored under label "".
	Webhooks map[string]*WebhookGatewayConfig `json:"-"`
	// RSSFeeds holds zero or more RSS/Atom feed configs keyed by label.
	// A plain "rss" key is stored under label "".
	RSSFeeds map[string]*RSSGatewayConfig `json:"-"`
	// GitLabs holds zero or more GitLab webhook configs keyed by label.
	GitLabs map[string]*GitLabGatewayConfig `json:"-"`
	// Jiras holds zero or more Jira webhook configs keyed by label.
	Jiras map[string]*JiraGatewayConfig `json:"-"`
	// Linears holds zero or more Linear webhook configs keyed by label.
	Linears map[string]*LinearGatewayConfig `json:"-"`
	// Sentries holds zero or more Sentry webhook configs keyed by label.
	Sentries map[string]*SentryGatewayConfig `json:"-"`
	// Stripes holds zero or more Stripe webhook configs keyed by label.
	Stripes map[string]*StripeGatewayConfig `json:"-"`
	// Bitbuckets holds zero or more Bitbucket webhook configs keyed by label.
	Bitbuckets map[string]*BitbucketGatewayConfig `json:"-"`
	// PagerDuties holds zero or more PagerDuty webhook configs keyed by label.
	PagerDuties map[string]*PagerDutyGatewayConfig `json:"-"`
	// Datadogs holds zero or more Datadog webhook configs keyed by label.
	Datadogs map[string]*DatadogGatewayConfig `json:"-"`
	// Grafanas holds zero or more Grafana webhook configs keyed by label.
	Grafanas map[string]*GrafanaGatewayConfig `json:"-"`
	// Vercels holds zero or more Vercel webhook configs keyed by label.
	Vercels map[string]*VercelGatewayConfig `json:"-"`
	// Netlifys holds zero or more Netlify webhook configs keyed by label.
	Netlifys map[string]*NetlifyGatewayConfig `json:"-"`
	// Notions holds zero or more Notion poll configs keyed by label.
	Notions map[string]*NotionGatewayConfig `json:"-"`
	// WhatsApps holds zero or more WhatsApp webhook configs keyed by label.
	WhatsApps map[string]*WhatsAppGatewayConfig `json:"-"`
	// Signals holds zero or more Signal poll configs keyed by label.
	Signals map[string]*SignalGatewayConfig `json:"-"`
	// Matrices holds zero or more Matrix poll configs keyed by label.
	Matrices map[string]*MatrixGatewayConfig `json:"-"`
	// MSTeams holds zero or more MS Teams webhook configs keyed by label.
	MSTeams map[string]*MSTeamsGatewayConfig `json:"-"`
	// GoogleChats holds zero or more Google Chat webhook configs keyed by label.
	GoogleChats map[string]*GoogleChatGatewayConfig `json:"-"`
	// Lines holds zero or more LINE webhook configs keyed by label.
	Lines map[string]*LineGatewayConfig `json:"-"`
	// Feishus holds zero or more Feishu webhook configs keyed by label.
	Feishus map[string]*FeishuGatewayConfig `json:"-"`
	// Mattermosts holds zero or more Mattermost webhook configs keyed by label.
	Mattermosts map[string]*MattermostGatewayConfig `json:"-"`
	// IRCs holds zero or more IRC socket configs keyed by label.
	IRCs map[string]*IRCGatewayConfig `json:"-"`
	// Nostrs holds zero or more Nostr socket configs keyed by label.
	Nostrs map[string]*NostrGatewayConfig `json:"-"`
	// Twitches holds zero or more Twitch webhook configs keyed by label.
	Twitches map[string]*TwitchGatewayConfig `json:"-"`
	// IMessages holds zero or more iMessage poll configs keyed by label.
	IMessages map[string]*IMessageGatewayConfig `json:"-"`
	// MQTTs holds zero or more MQTT socket configs keyed by label.
	MQTTs map[string]*MQTTGatewayConfig `json:"-"`
	// Twitters holds zero or more Twitter poll configs keyed by label.
	Twitters map[string]*TwitterGatewayConfig `json:"-"`
	// Reddits holds zero or more Reddit poll configs keyed by label.
	Reddits map[string]*RedditGatewayConfig `json:"-"`
	// HomeAssistants holds zero or more Home Assistant socket configs keyed by label.
	HomeAssistants map[string]*HomeAssistantGatewayConfig `json:"-"`
}

GatewaysConfig configures external messaging platform integrations.

JSON keys follow a "platform" or "platform:label" convention. Plain "telegram" is a single Telegram bot (backward compat). Keys like "telegram:trade_research" register additional bots — parsed into the Telegrams map keyed by label.

func (GatewaysConfig) MarshalJSON added in v0.2.0

func (g GatewaysConfig) MarshalJSON() ([]byte, error)

MarshalJSON serializes the gateway config, emitting "telegram:label" keys for each entry in Telegrams.

func (*GatewaysConfig) UnmarshalJSON added in v0.2.0

func (g *GatewaysConfig) UnmarshalJSON(data []byte) error

UnmarshalJSON parses gateway config, routing "telegram:*" keys into the Telegrams map and keeping Discord/Slack on their typed fields.

type GitHubGatewayConfig added in v0.2.1

type GitHubGatewayConfig struct {
	Secret  string `json:"secret"`
	Enabled bool   `json:"enabled"`
}

GitHubGatewayConfig configures the GitHub webhook gateway adapter.

type GitLabGatewayConfig added in v0.2.1

type GitLabGatewayConfig struct {
	Token   string `json:"token"`
	Enabled bool   `json:"enabled"`
}

GitLabGatewayConfig configures the GitLab webhook gateway adapter.

type GoogleChatGatewayConfig added in v0.2.1

type GoogleChatGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

GoogleChatGatewayConfig configures the Google Chat webhook adapter.

type GrafanaGatewayConfig added in v0.2.1

type GrafanaGatewayConfig struct {
	Token   string `json:"token,omitempty"`
	Enabled bool   `json:"enabled"`
}

GrafanaGatewayConfig configures the Grafana webhook gateway adapter.

type HomeAssistantGatewayConfig added in v0.2.1

type HomeAssistantGatewayConfig struct {
	URL     string `json:"url"`
	Token   string `json:"token"`
	Enabled bool   `json:"enabled"`
}

HomeAssistantGatewayConfig configures the Home Assistant WebSocket adapter (placeholder).

type IMessageGatewayConfig added in v0.2.1

type IMessageGatewayConfig struct {
	APIURL   string `json:"api_url"`
	Password string `json:"password"`
	Interval int    `json:"interval"` // seconds, default 10
	Enabled  bool   `json:"enabled"`
}

IMessageGatewayConfig configures the iMessage (BlueBubbles) poll adapter.

type IRCGatewayConfig added in v0.2.1

type IRCGatewayConfig struct {
	Server  string `json:"server"`
	Enabled bool   `json:"enabled"`
}

IRCGatewayConfig configures the IRC socket adapter (placeholder).

type JiraGatewayConfig added in v0.2.1

type JiraGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

JiraGatewayConfig configures the Jira webhook gateway adapter.

type LineGatewayConfig added in v0.2.1

type LineGatewayConfig struct {
	Secret  string `json:"secret"`
	Enabled bool   `json:"enabled"`
}

LineGatewayConfig configures the LINE Messaging API webhook adapter.

type LinearGatewayConfig added in v0.2.1

type LinearGatewayConfig struct {
	Secret  string `json:"secret"`
	Enabled bool   `json:"enabled"`
}

LinearGatewayConfig configures the Linear webhook gateway adapter.

type LogsConfig

type LogsConfig struct {
	Path     string `json:"path"`
	MaxBytes int64  `json:"max_bytes"`
}

LogsConfig configures persistent session log streaming.

type MQTTGatewayConfig added in v0.2.1

type MQTTGatewayConfig struct {
	BrokerURL string `json:"broker_url"`
	Topic     string `json:"topic,omitempty"`
	Enabled   bool   `json:"enabled"`
}

MQTTGatewayConfig configures the MQTT socket adapter (placeholder).

type MSTeamsGatewayConfig added in v0.2.1

type MSTeamsGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

MSTeamsGatewayConfig configures the Microsoft Teams Bot Framework webhook adapter.

type MatrixGatewayConfig added in v0.2.1

type MatrixGatewayConfig struct {
	Homeserver string `json:"homeserver"`
	Token      string `json:"token"`
	Interval   int    `json:"interval"` // seconds, default 10
	Enabled    bool   `json:"enabled"`
}

MatrixGatewayConfig configures the Matrix client-server poll adapter.

type MattermostGatewayConfig added in v0.2.1

type MattermostGatewayConfig struct {
	Token   string `json:"token,omitempty"`
	Enabled bool   `json:"enabled"`
}

MattermostGatewayConfig configures the Mattermost outgoing webhook adapter.

type NetlifyGatewayConfig added in v0.2.1

type NetlifyGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

NetlifyGatewayConfig configures the Netlify webhook gateway adapter.

type NostrGatewayConfig added in v0.2.1

type NostrGatewayConfig struct {
	RelayURL string `json:"relay_url"`
	Enabled  bool   `json:"enabled"`
}

NostrGatewayConfig configures the Nostr relay WebSocket adapter (placeholder).

type NotionGatewayConfig added in v0.2.1

type NotionGatewayConfig struct {
	Token    string `json:"token"`
	Interval int    `json:"interval"` // seconds, default 300
	Enabled  bool   `json:"enabled"`
}

NotionGatewayConfig configures the Notion poll gateway adapter.

type PagerDutyGatewayConfig added in v0.2.1

type PagerDutyGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

PagerDutyGatewayConfig configures the PagerDuty webhook gateway adapter.

type ProviderConfig

type ProviderConfig struct {
	Command string `json:"command"`
}

ProviderConfig defines an AI provider's configuration.

type ProvidersConfig

type ProvidersConfig struct {
	Default   string                    `json:"default"`
	Providers map[string]ProviderConfig `json:"providers,omitempty"`
}

ProvidersConfig configures AI agent providers.

type RSSGatewayConfig added in v0.2.1

type RSSGatewayConfig struct {
	URL      string `json:"url"`
	Interval int    `json:"interval"` // seconds, default 300
	Enabled  bool   `json:"enabled"`
}

RSSGatewayConfig configures an RSS/Atom feed poll adapter.

type RedditGatewayConfig added in v0.2.1

type RedditGatewayConfig struct {
	Subreddit   string `json:"subreddit"`
	BearerToken string `json:"bearer_token"`
	Interval    int    `json:"interval"` // seconds, default 60
	Enabled     bool   `json:"enabled"`
}

RedditGatewayConfig configures the Reddit API poll adapter.

type Registry

type Registry struct {
	Active     string          `json:"active,omitempty"` // Path or alias of active workspace
	Workspaces []RegistryEntry `json:"workspaces"`

	Version int `json:"version,omitempty"`
	// contains filtered or unexported fields
}

Registry manages the global list of workspaces at ~/.bc/workspaces.json. Issue #1218: Multi-workspace orchestration support.

func LoadRegistry

func LoadRegistry() (*Registry, error)

LoadRegistry loads the global workspace registry. Returns an empty registry if the file doesn't exist. Always runs Migrate() so callers see a v2 in-memory shape.

func (*Registry) Find

func (r *Registry) Find(path string) *RegistryEntry

Find returns the entry for a given path, or nil if not found.

func (*Registry) FindByAlias

func (r *Registry) FindByAlias(alias string) *RegistryEntry

FindByAlias returns the entry for a given alias, or nil if not found. Issue #1218: Multi-workspace orchestration.

func (*Registry) FindByID added in v0.2.0

func (r *Registry) FindByID(id string) *RegistryEntry

FindByID returns the entry for a given workspace ID (v2+), or nil if not found. The ID is the 12-char hex hash of the absolute path, independent of user-editable fields like name or alias.

func (*Registry) FindByNameOrAlias

func (r *Registry) FindByNameOrAlias(identifier string) *RegistryEntry

FindByNameOrAlias returns the entry matching name, alias, or path. Tries alias first, then name, then path.

func (*Registry) GetActive

func (r *Registry) GetActive() *RegistryEntry

GetActive returns the active workspace entry, or nil if none set.

func (*Registry) List

func (r *Registry) List() []RegistryEntry

List returns all registered workspaces.

func (*Registry) Migrate added in v0.2.0

func (r *Registry) Migrate() bool

Migrate bumps the registry to the current schema version.

  • v1 → v2: populate ID on every entry (sha256(path)[:12]) and ensure LastUsedAt is set (falls back to LastAccessed or CreatedAt).

Returns true if any change was made. Safe to call multiple times.

func (*Registry) Prune

func (r *Registry) Prune() int

Prune removes entries where the workspace no longer exists on disk. Checks for .bc/ dir in project root OR state dir in ~/.bc/workspaces/<id>/.

func (*Registry) PruneStalePaths added in v0.2.0

func (r *Registry) PruneStalePaths() int

PruneStalePaths removes entries whose project directory no longer exists on disk — e.g. test tmpdirs that the caller created via t.TempDir() and that have since been cleaned up. Unlike Prune(), this does not look at .bc/ or the global state dir; it only checks that the root Path itself is still a directory. Returns the count removed.

Callers should invoke this before performing batch operations against the registry (like the M11 runtime migration) to avoid acting on phantom entries.

func (*Registry) Register

func (r *Registry) Register(path, name string)

Register adds or updates a workspace in the registry.

func (*Registry) RegisterWithAlias

func (r *Registry) RegisterWithAlias(path, name, alias string) error

RegisterWithAlias adds or updates a workspace with an optional alias. Issue #1218: Multi-workspace orchestration.

func (*Registry) Resolve added in v0.2.0

func (r *Registry) Resolve(identifier string) *RegistryEntry

Resolve returns the entry matching an id, alias, name, or path. Returns nil if none match.

func (*Registry) Save

func (r *Registry) Save() error

Save persists the registry to disk atomically: write to a temp file then rename over the destination. This prevents corruption if the process is killed mid-write.

func (*Registry) SetActive

func (r *Registry) SetActive(identifier string) error

SetActive sets the active workspace by path, alias, or name.

func (*Registry) SetAlias

func (r *Registry) SetAlias(path, alias string) error

SetAlias sets or clears the alias for a workspace.

func (*Registry) Touch

func (r *Registry) Touch(identifier string)

Touch updates the last-accessed time for a workspace. Accepts a path, id, alias, or name — for backwards compatibility, the single argument was historically a path.

func (*Registry) Unregister

func (r *Registry) Unregister(path string)

Unregister removes a workspace from the registry.

type RegistryEntry

type RegistryEntry struct {
	CreatedAt      time.Time `json:"created_at"`
	LastAccessed   time.Time `json:"last_accessed,omitempty"` // legacy — mirrors LastUsedAt for backwards compat
	LastUsedAt     time.Time `json:"last_used_at,omitempty"`  // canonical timestamp (v2+)
	ID             string    `json:"id,omitempty"`            // stable 12-char hash of abs path (v2+)
	Path           string    `json:"path"`                    // project root (pristine git repo)
	DataDir        string    `json:"data_dir,omitempty"`      // runtime state dir (~/.bc/workspaces/<id>/); M11+
	Name           string    `json:"name"`
	Alias          string    `json:"alias,omitempty"`            // Short alias for quick access (#1218)
	GithubURL      string    `json:"github_url,omitempty"`       // Optional GitHub remote URL (v2+)
	GithubFullName string    `json:"github_full_name,omitempty"` // Optional GitHub owner/repo (v2+)
}

RegistryEntry represents a registered workspace.

func (*RegistryEntry) GetDataDir added in v0.2.0

func (e *RegistryEntry) GetDataDir() string

GetDataDir returns the per-workspace runtime directory. When the registry field is empty (older entries), falls back to computing it from the workspace ID via DataDir(id). Returns "" if neither is available.

type Repo added in v0.2.0

type Repo struct {
	FullName      string `json:"full_name"`
	Name          string `json:"name"`
	CloneURL      string `json:"clone_url"`
	SSHURL        string `json:"ssh_url"`
	HTMLURL       string `json:"html_url"`
	DefaultBranch string `json:"default_branch"`
	Description   string `json:"description,omitempty"`
	Private       bool   `json:"private"`
}

Repo mirrors the subset of a GitHub repository record we expose to the frontend.

func ListGithubRepos added in v0.2.0

func ListGithubRepos(ctx context.Context, query string) ([]Repo, error)

ListGithubRepos returns up to 100 repos accessible to the authenticated user, filtered by optional substring query. Uses /user/repos which requires the `repo` scope.

type ResolvedRole

type ResolvedRole struct {
	Settings     map[string]any    // Merged settings (child overrides parent)
	Rules        map[string]string // Merged rule files (child overrides parent)
	Agents       map[string]string // Merged agent templates
	Skills       map[string]string // Merged skill files
	Commands     map[string]string // Merged command files
	PromptStart  string            // Lifecycle: sent on agent start/restart
	Name         string            // Role name
	PromptStop   string            // Lifecycle: sent on agent stop
	PromptDelete string            // Lifecycle: sent on agent delete
	PromptCreate string            // Lifecycle: sent on agent create
	Prompt       string            // Merged prompt body (child + parent)
	Review       string            // REVIEW.md content
	Plugins      []string          // Unioned plugins from all ancestors
	Secrets      []string          // Unioned secret names from all ancestors
	MCPServers   []string          // Unioned MCP servers from all ancestors
	CLITools     []string          // Unioned CLI tools from all ancestors
	Description  string            // Human-readable role description
}

ResolvedRole contains the fully resolved role after BFS inheritance merge.

type Role

type Role struct {
	FilePath string       // Path to the role file
	Prompt   string       // Markdown body after frontmatter
	Metadata RoleMetadata // Parsed YAML frontmatter
}

Role represents a parsed role file with metadata and prompt content.

func ParseRoleFile

func ParseRoleFile(data []byte) (*Role, error)

ParseRoleFile parses a role file with YAML frontmatter and markdown body. The frontmatter is delimited by --- on its own lines.

func (*Role) Description

func (r *Role) Description() string

Description returns a brief description for the role. Uses Metadata.Description if set, otherwise extracts from the first heading in Prompt.

type RoleManager

type RoleManager struct {
	// contains filtered or unexported fields
}

RoleManager handles role operations for a workspace. All role data is stored in SQL (SQLite or Postgres) via the RoleStore. The rolesDir field is retained only for migration from legacy file-based storage.

func NewRoleManager

func NewRoleManager(stateDir string) *RoleManager

NewRoleManager creates a new role manager for the given workspace state directory. It opens a SQLite-backed RoleStore at stateDir/bc.db automatically and performs a best-effort migration of any .md files in the roles directory. If the store cannot be opened, operations that require the store will return errors.

func NewRoleManagerWithStore

func NewRoleManagerWithStore(stateDir string, store *RoleStore) *RoleManager

NewRoleManagerWithStore creates a role manager backed by a SQLite store. The filesystem rolesDir is still used for migration and backward compatibility.

func (*RoleManager) AddMCPServer

func (rm *RoleManager) AddMCPServer(roleName, server string) error

AddMCPServer adds an MCP server association to a role if not already present.

func (*RoleManager) DeleteRole

func (rm *RoleManager) DeleteRole(name string) error

DeleteRole removes a role by name from the SQL store.

func (*RoleManager) EnsureDefaultRoles

func (rm *RoleManager) EnsureDefaultRoles() ([]string, error)

EnsureDefaultRoles writes built-in default roles to the store if they don't already exist. Returns the names of any roles that were created.

func (*RoleManager) EnsureDefaultRoot

func (rm *RoleManager) EnsureDefaultRoot() (bool, error)

EnsureDefaultRoot ensures the base and root roles exist in the store. Returns true if the root role was created, false if it already existed.

func (*RoleManager) EnsureRolesDir

func (rm *RoleManager) EnsureRolesDir() error

EnsureRolesDir creates the roles directory if it doesn't exist.

func (*RoleManager) GetMCPServers

func (rm *RoleManager) GetMCPServers(roleName string) ([]string, error)

GetMCPServers returns the MCP server associations for a role.

func (*RoleManager) GetRole

func (rm *RoleManager) GetRole(name string) (*Role, bool)

GetRole returns a cached role by name.

func (*RoleManager) HasRole

func (rm *RoleManager) HasRole(name string) bool

HasRole checks if a role exists (cached or in store).

func (*RoleManager) LoadAllRoles

func (rm *RoleManager) LoadAllRoles() (map[string]*Role, error)

LoadAllRoles loads all roles from the SQL store.

func (*RoleManager) LoadRole

func (rm *RoleManager) LoadRole(name string) (*Role, error)

LoadRole loads and parses a single role from the SQL store.

func (*RoleManager) RemoveMCPServer

func (rm *RoleManager) RemoveMCPServer(roleName, server string) error

RemoveMCPServer removes an MCP server association from a role.

func (*RoleManager) ResolveRole

func (rm *RoleManager) ResolveRole(name string) (*ResolvedRole, error)

ResolveRole loads a role directly from the store. No inheritance — each role is self-contained with all its own MCP servers, secrets, plugins, etc.

func (*RoleManager) RolesDir

func (rm *RoleManager) RolesDir() string

RolesDir returns the roles directory path.

func (*RoleManager) SetMCPServers

func (rm *RoleManager) SetMCPServers(roleName string, servers []string) error

SetMCPServers replaces the MCP server list for a role.

func (*RoleManager) Store

func (rm *RoleManager) Store() *RoleStore

Store returns the underlying RoleStore, or nil if filesystem-only.

func (*RoleManager) WriteRole

func (rm *RoleManager) WriteRole(role *Role) error

WriteRole writes a role to the SQL store.

type RoleMetadata

type RoleMetadata struct {
	Settings     map[string]any    `yaml:"settings,omitempty"`      // Claude settings overrides (e.g., model, permissions)
	Rules        map[string]string `yaml:"rules,omitempty"`         // Rule files written to .claude/rules/*.md
	Agents       map[string]string `yaml:"agents,omitempty"`        // Agent templates written to .claude/agents/*.md
	Skills       map[string]string `yaml:"skills,omitempty"`        // Skill files written to .claude/skills/*.md
	Commands     map[string]string `yaml:"commands,omitempty"`      // Command files written to .claude/commands/*.md
	PromptStop   string            `yaml:"prompt_stop,omitempty"`   // Sent when agent is stopped
	PromptCreate string            `yaml:"prompt_create,omitempty"` // Sent when agent is created
	PromptStart  string            `yaml:"prompt_start,omitempty"`  // Sent when agent is started/restarted
	Name         string            `yaml:"name"`                    // Role name (e.g., "engineer", "manager")
	PromptDelete string            `yaml:"prompt_delete,omitempty"` // Sent when agent is deleted
	Description  string            `yaml:"description,omitempty"`   // Human-readable role description
	Review       string            `yaml:"review,omitempty"`        // REVIEW.md content for the role
	Plugins      []string          `yaml:"plugins,omitempty"`       // Claude Code plugins to install on agent start
	Secrets      []string          `yaml:"secrets,omitempty"`       // Secret names needed by MCP env vars
	MCPServers   []string          `yaml:"mcp_servers,omitempty"`   // MCP servers available to this role
	ParentRoles  []string          `yaml:"parent_roles,omitempty"`  // Roles to inherit from (capabilities, prompts)
	CLITools     []string          `yaml:"cli_tools,omitempty"`     // CLI tools expected in agent PATH (e.g., gh, aws, wrangler)
}

RoleMetadata contains the parsed frontmatter from a role file.

type RoleStore

type RoleStore struct {
	// contains filtered or unexported fields
}

RoleStore provides SQL-backed persistence for roles. It supports both SQLite and Postgres via the driver field.

func NewRoleStore

func NewRoleStore(dbPath string) (*RoleStore, error)

NewRoleStore opens (or creates) a SQLite database at dbPath and ensures the roles table exists. The caller must call Close when done.

func NewRoleStoreFromDB

func NewRoleStoreFromDB(sqlDB *sql.DB, driver string) (*RoleStore, error)

NewRoleStoreFromDB creates a RoleStore from an existing *sql.DB connection. The caller retains ownership of the connection — Close on this store is a no-op.

func (*RoleStore) Close

func (s *RoleStore) Close() error

Close closes the database if this store owns the connection.

func (*RoleStore) Delete

func (s *RoleStore) Delete(name string) error

Delete removes a single role by name.

func (*RoleStore) Has

func (s *RoleStore) Has(name string) bool

Has checks if a role exists in the database.

func (*RoleStore) InitSchema

func (s *RoleStore) InitSchema() error

InitSchema creates the roles table if it does not exist. Uses driver-appropriate column types.

func (*RoleStore) Load

func (s *RoleStore) Load(name string) (*Role, error)

Load reads a single role by name. Returns an error if not found.

func (*RoleStore) LoadAll

func (s *RoleStore) LoadAll() (map[string]*Role, error)

LoadAll reads every role into a map keyed by name.

func (*RoleStore) MigrateDefaults

func (s *RoleStore) MigrateDefaults() error

MigrateDefaults inserts the built-in default roles (base, root, and DefaultRoles map) into the database if they don't already exist.

func (*RoleStore) MigrateFromFiles

func (s *RoleStore) MigrateFromFiles(rolesDir string) (int, error)

MigrateFromFiles scans a roles directory for .md files and inserts them into the database. Existing roles in the DB are not overwritten. The source files are NOT deleted (kept as backup).

func (*RoleStore) Save

func (s *RoleStore) Save(role *Role) error

Save persists a single role (upsert).

type RuntimeConfig

type RuntimeConfig struct {
	K8s     json.RawMessage     `json:"k8s,omitempty"` // future
	Default string              `json:"default"`       // "tmux" or "docker"
	Docker  DockerRuntimeConfig `json:"docker"`
	Tmux    TmuxRuntimeConfig   `json:"tmux"`
}

RuntimeConfig configures the agent session backend.

type SQLiteStorageConfig

type SQLiteStorageConfig struct {
	Path string `json:"path"`
}

SQLiteStorageConfig configures SQLite storage.

type ScanOptions added in v0.2.0

type ScanOptions struct {
	// SkipDirs additional directory basenames to exclude, merged with the
	// default SkipDirs list.
	SkipDirs map[string]struct{}
	// Root is the absolute directory to scan. Required.
	Root string
	// Depth bounds recursion relative to Root. Values <=0 use defaultDepth.
	// Values > maxDepth are clamped.
	Depth int
}

ScanOptions controls local discovery behavior.

type SentryGatewayConfig added in v0.2.1

type SentryGatewayConfig struct {
	Secret  string `json:"secret"`
	Enabled bool   `json:"enabled"`
}

SentryGatewayConfig configures the Sentry webhook gateway adapter.

type ServerConfig

type ServerConfig struct {
	Host       string `json:"host"`
	CORSOrigin string `json:"cors_origin"`
	Port       int    `json:"port"`
}

ServerConfig configures the bcd HTTP server.

func (ServerConfig) Addr

func (s ServerConfig) Addr() string

Addr returns the host:port string for the server.

type SignalGatewayConfig added in v0.2.1

type SignalGatewayConfig struct {
	APIURL   string `json:"api_url"`
	Interval int    `json:"interval"` // seconds, default 10
	Enabled  bool   `json:"enabled"`
}

SignalGatewayConfig configures the Signal (signal-cli REST) poll adapter.

type SlackGatewayConfig

type SlackGatewayConfig struct {
	BotToken string `json:"bot_token"`
	AppToken string `json:"app_token"`
	Mode     string `json:"mode"`
	Enabled  bool   `json:"enabled"`
}

SlackGatewayConfig configures the Slack gateway adapter.

type StorageConfig

type StorageConfig struct {
	Default   string                 `json:"default"` // "sqlite" or "timescale"
	SQLite    SQLiteStorageConfig    `json:"sqlite"`
	Timescale TimescaleStorageConfig `json:"timescale"`
}

StorageConfig configures persistent storage.

type StripeGatewayConfig added in v0.2.1

type StripeGatewayConfig struct {
	Secret  string `json:"secret"`
	Enabled bool   `json:"enabled"`
}

StripeGatewayConfig configures the Stripe webhook gateway adapter.

type TelegramGatewayConfig

type TelegramGatewayConfig struct {
	BotToken string `json:"bot_token"`
	Mode     string `json:"mode"`
	Enabled  bool   `json:"enabled"`
}

TelegramGatewayConfig configures the Telegram gateway adapter.

type TimescaleStorageConfig

type TimescaleStorageConfig struct {
	Host     string `json:"host"`
	User     string `json:"user"`
	Password string `json:"password"`
	Database string `json:"database"`
	Port     int    `json:"port"`
}

TimescaleStorageConfig configures TimescaleDB (Postgres) storage.

type TmuxRuntimeConfig

type TmuxRuntimeConfig struct {
	SessionPrefix string `json:"session_prefix"`
	DefaultShell  string `json:"default_shell"`
	HistoryLimit  int    `json:"history_limit"`
}

TmuxRuntimeConfig configures tmux session settings.

type TwitchGatewayConfig added in v0.2.1

type TwitchGatewayConfig struct {
	Secret  string `json:"secret"`
	Enabled bool   `json:"enabled"`
}

TwitchGatewayConfig configures the Twitch EventSub webhook adapter.

type TwitterGatewayConfig added in v0.2.1

type TwitterGatewayConfig struct {
	BearerToken string `json:"bearer_token"`
	UserID      string `json:"user_id"`
	Interval    int    `json:"interval"` // seconds, default 60
	Enabled     bool   `json:"enabled"`
}

TwitterGatewayConfig configures the Twitter API v2 poll adapter.

type UIConfig

type UIConfig struct {
	Theme       string `json:"theme"`
	Mode        string `json:"mode"`
	DefaultView string `json:"default_view"`
}

UIConfig configures UI appearance.

type UserConfig

type UserConfig struct {
	Name string `json:"name"`
}

UserConfig holds user identity settings.

type UserRCConfig

type UserRCConfig struct {
	User     UserRCUserConfig     `json:"user"`
	Defaults UserRCDefaultsConfig `json:"defaults"`
	Tools    UserRCToolsConfig    `json:"tools"`
}

UserRCConfig represents user-level defaults stored in ~/.bcrc. These values are merged with workspace config when loading.

func DefaultUserRCConfig

func DefaultUserRCConfig() UserRCConfig

DefaultUserRCConfig returns sensible defaults for a new .bcrc file.

func LoadUserRCConfig

func LoadUserRCConfig() (*UserRCConfig, error)

LoadUserRCConfig loads the user's .bcrc file.

func ParseUserRCConfig

func ParseUserRCConfig(data []byte) (*UserRCConfig, error)

ParseUserRCConfig parses JSON data into a UserRCConfig.

func (*UserRCConfig) Save

func (c *UserRCConfig) Save() error

Save writes the user config to the .bcrc file.

type UserRCDefaultsConfig

type UserRCDefaultsConfig struct {
	DefaultRole   string `json:"default_role,omitempty"`
	AutoStartRoot bool   `json:"auto_start_root,omitempty"`
}

UserRCDefaultsConfig holds default behavior settings.

type UserRCToolsConfig

type UserRCToolsConfig struct {
	Preferred []string `json:"preferred,omitempty"`
}

UserRCToolsConfig holds tool preferences.

type UserRCUserConfig

type UserRCUserConfig struct {
	Nickname string `json:"nickname,omitempty"`
}

UserRCUserConfig holds user identity settings.

type VercelGatewayConfig added in v0.2.1

type VercelGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

VercelGatewayConfig configures the Vercel webhook gateway adapter.

type WebhookGatewayConfig added in v0.2.1

type WebhookGatewayConfig struct {
	Secret  string `json:"secret,omitempty"`
	Enabled bool   `json:"enabled"`
}

WebhookGatewayConfig configures a generic webhook gateway adapter.

type WhatsAppGatewayConfig added in v0.2.1

type WhatsAppGatewayConfig struct {
	VerifyToken string `json:"verify_token"`
	Enabled     bool   `json:"enabled"`
}

WhatsAppGatewayConfig configures the WhatsApp (Meta Cloud API) webhook adapter.

type Workspace

type Workspace struct {
	Config      *Config      // JSON config
	RoleManager *RoleManager // Role file manager
	RootDir     string       // Project root directory (pristine git repo)
	DataDir     string       // Runtime state dir (~/.bc/workspaces/<id>/); set for M11+ layouts
	// contains filtered or unexported fields
}

Workspace represents an active workspace.

After M11 the Workspace maintains two independent directories:

  • RootDir: the project (a pristine git repo bc points at but never writes runtime state into).
  • DataDir: the per-workspace runtime directory (~/.bc/workspaces/<id>/) containing preferences.json, state.db, cron.db, agents/, logs/, etc.

StateDir() returns DataDir for new workspaces; for legacy workspaces that still keep state inside <RootDir>/.bc/ (pre-M11 migration), it returns that path instead so in-flight code keeps working until the migration runs.

func Find

func Find(dir string) (*Workspace, error)

Find searches for a workspace starting from dir and going up. It checks the registry first (for .bc/-free workspaces), then falls back to the legacy .bc/ directory walk.

func Init

func Init(rootDir string) (*Workspace, error)

Init initializes a new workspace. State is stored under ~/.bc/workspaces/<id>/.

func Load

func Load(rootDir string) (*Workspace, error)

Load loads a workspace from a directory.

func (*Workspace) AgentsDir

func (w *Workspace) AgentsDir() string

AgentsDir returns the agents state directory.

func (*Workspace) ChannelsDir

func (w *Workspace) ChannelsDir() string

ChannelsDir returns the channels directory path.

func (*Workspace) DefaultProvider

func (w *Workspace) DefaultProvider() string

DefaultProvider returns the default provider name for this workspace.

func (*Workspace) DefaultProviderCommand

func (w *Workspace) DefaultProviderCommand() string

DefaultProviderCommand returns the command for the default provider.

func (*Workspace) EnsureDirs

func (w *Workspace) EnsureDirs() error

EnsureDirs creates all required directories.

func (*Workspace) GetRole

func (w *Workspace) GetRole(name string) (*Role, error)

GetRole returns a role by name, loading it if necessary.

func (*Workspace) GetRolePrompt

func (w *Workspace) GetRolePrompt(name string) string

GetRolePrompt returns the prompt content for a role.

func (*Workspace) LogsDir

func (w *Workspace) LogsDir() string

LogsDir returns the logs directory.

func (*Workspace) Name

func (w *Workspace) Name() string

Name returns the workspace name (derived from directory).

func (*Workspace) RolesDir

func (w *Workspace) RolesDir() string

RolesDir returns the roles directory path.

func (*Workspace) Save

func (w *Workspace) Save() error

Save saves the workspace configuration to preferences.json. A legacy settings.json on disk is left alone for the user to audit.

func (*Workspace) SettingsFile added in v0.2.0

func (w *Workspace) SettingsFile() string

SettingsFile returns the absolute path of the workspace preferences file. M11c renames the on-disk filename from settings.json to preferences.json; this accessor is the canonical way to find whichever file actually lives on disk.

Lookup order: <StateDir>/preferences.json (M11c+), then <StateDir>/settings.json (legacy). Returns the preferences.json path when neither exists so callers may safely write to it.

func (*Workspace) StateDir

func (w *Workspace) StateDir() string

StateDir returns the resolved state directory path. Returns DataDir for M11+ layouts or the legacy <RootDir>/.bc/ path when a workspace has not yet been migrated.

type WorkspaceNotFoundError

type WorkspaceNotFoundError struct {
	Identifier string
}

WorkspaceNotFoundError indicates the workspace was not found.

func (*WorkspaceNotFoundError) Error

func (e *WorkspaceNotFoundError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL