Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0c396e5
feat(projects): add channel-centric read-model and read-only api
pgagnidze Jun 5, 2026
7e9aee8
refactor(api)!: rename birds to automations, docs to skills, scope bi…
pgagnidze Jun 5, 2026
bf75caa
refactor(web): rename birds/docs pages to automations/skills, scope b…
pgagnidze Jun 5, 2026
64fb5aa
feat(web): add projects pages (list, detail, and create wizard)
pgagnidze Jun 5, 2026
b92f2b1
feat(web): add keys and agents pages and extract createconfigeditor f…
pgagnidze Jun 5, 2026
23d2180
refactor: finish automations/skills rename in cli reference, slack, a…
pgagnidze Jun 5, 2026
2c740e7
refactor!: rename BROWSERBIRD_BIRD_DATA env var to BROWSERBIRD_AUTOMA…
pgagnidze Jun 5, 2026
a79c324
refactor(web): drop dead-code bird binding chip relabel
pgagnidze Jun 5, 2026
fc8a051
test: quote test glob so node runs top-level src/*.test.ts files
pgagnidze Jun 5, 2026
5cfc5dd
refactor(config): rename birds config key to automations with back-co…
pgagnidze Jun 5, 2026
eb1c339
refactor(projects): use automation vocabulary in the projects feature
pgagnidze Jun 5, 2026
fe89e97
feat(web): nest agents, skills, keys, automations under projects in s…
pgagnidze Jun 5, 2026
3f74a0d
feat(web): nest projects nav always-expanded with a grouped cluster w…
pgagnidze Jun 5, 2026
1abf926
feat(web): reveal projects sub-nav only within the projects section
pgagnidze Jun 5, 2026
afd22ae
feat(web): collapse agents/skills/keys/automations into a resources hub
pgagnidze Jun 5, 2026
27affca
fix(bindings): preserve legacy bird bindings on the channel-only writ…
pgagnidze Jun 5, 2026
adc1e6b
fix: correct help-text keys, keys cross-link, and global blueprint au…
pgagnidze Jun 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 38 additions & 38 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion browserbird.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"novncPort": 6080,
"novncHost": "localhost"
},
"birds": {
"automations": {
"maxAttempts": 3,
"maxConsecutiveFailures": 2
},
Expand Down
6 changes: 3 additions & 3 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
},
"slash_commands": [
{
"command": "/bird",
"description": "Manage BrowserBird birds",
"usage_hint": "list | fly | stop | logs | enable | disable | create | status",
"command": "/automation",
"description": "Manage BrowserBird automations",
"usage_hint": "list | run | stop | logs | enable | disable | create | status",
"should_escape": false
}
]
Expand Down
12 changes: 6 additions & 6 deletions oci/app/config/agent-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

@SETUP.md

You are running inside BrowserBird, an AI agent orchestrator with a real browser, a cron scheduler, and a web dashboard. Messages may come from Slack users (streaming back to Slack threads in real time) or from scheduled bird tasks. If Slack is not configured, birds still run and results are stored in the dashboard.
You are running inside BrowserBird, an AI agent orchestrator with a real browser, a cron scheduler, and a web dashboard. Messages may come from Slack users (streaming back to Slack threads in real time) or from scheduled automation tasks. If Slack is not configured, automations still run and results are stored in the dashboard.

## Critical Warnings

Expand Down Expand Up @@ -84,11 +84,11 @@ Check for cookie env vars at the start of any task that requires authenticated b

## Scheduling

When the user asks to schedule a task, create a recurring job, or set up automation, use BrowserBird's birds system via the CLI (`browserbird birds add`). Do not suggest or reference external scheduling tools.
When the user asks to schedule a task, create a recurring job, or set up automation, use BrowserBird's automations system via the CLI (`browserbird automations add`). Do not suggest or reference external scheduling tools.

## Bird Data
## Automation Data

If this session is a scheduled bird run, the environment variable `BROWSERBIRD_BIRD_DATA` points to a persistent directory for this bird. Files written here survive between runs. Use it to store previous results, state, or any data the next run should reference.
If this session is a scheduled automation run, the environment variable `BROWSERBIRD_AUTOMATION_DATA` points to a persistent directory for this automation. Files written here survive between runs. Use it to store previous results, state, or any data the next run should reference.

## Tools

Expand All @@ -99,12 +99,12 @@ The following npm tools can be used via `npx`. Run with `--help` to see usage.

## CLI

BrowserBird has a CLI at `./bin/browserbird`. Use it when the user asks to manage birds, inspect sessions, check logs, or interact with the system.
BrowserBird has a CLI at `./bin/browserbird`. Use it when the user asks to manage automations, inspect sessions, check logs, or interact with the system.

### CLI operating rules

- Do NOT redirect stderr from `browserbird` CLI invocations. No `2>/dev/null`, no `2>&1 >/dev/null`, no suppression of any kind. The CLI surfaces validation errors, auth failures, and daemon-unreachable conditions on stderr. Silencing it has turned real failures into silent no-ops.
- Do NOT trust memory files for a bird's current schedule, prompt, channel, or enabled state. Read the live record with `./bin/browserbird birds list --json` and parse the entry for the uid you care about. `birds list` (without `--json`) truncates the prompt to 50 characters, so memory snapshots of long prompts may be stale or partial.
- Do NOT trust memory files for an automation's current schedule, prompt, channel, or enabled state. Read the live record with `./bin/browserbird automations list --json` and parse the entry for the uid you care about. `automations list` (without `--json`) truncates the prompt to 50 characters, so memory snapshots of long prompts may be stale or partial.
- `browserbird reset-password` recovers a lost dashboard password (writes to the DB directly; prints a new generated password and signs out the user's sessions). Run it only when the user explicitly asks, and treat the printed password as a secret.

@cli-reference.md
50 changes: 24 additions & 26 deletions oci/app/config/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,41 @@

CLI location: `./bin/browserbird`

## Birds (scheduled tasks)
## Automations (scheduled tasks)

```
browserbird birds list List all birds
browserbird birds add [options] Create a bird (--name, --schedule, --prompt, --channel, --agent)
browserbird birds edit <uid> [options] Edit a bird (--name, --schedule, --prompt, --channel, --agent)
browserbird birds remove <uid> Delete a bird
browserbird birds enable <uid> Enable a bird
browserbird birds disable <uid> Disable a bird
browserbird birds fly <uid> Trigger a bird immediately
browserbird birds flights <uid> Show flight history
browserbird automations list List all automations
browserbird automations add <schedule> <prompt> Create an automation (or use --schedule/--prompt)
browserbird automations edit <uid> [options] Edit an automation (--name, --schedule, --prompt, --channel, --agent)
browserbird automations remove <uid> Delete an automation
browserbird automations enable <uid> Enable an automation
browserbird automations disable <uid> Disable an automation
browserbird automations run <uid> [args] Trigger an automation immediately ($ARGUMENTS substituted)
browserbird automations runs <uid> Show run history
```

Options for add/edit: `--channel <id>`, `--agent <id>`, `--active-hours 09:00-17:00`
Options for add/edit: `--channel <id>`, `--agent <id>`, `--background` (no channel), `--active-hours 09:00-17:00`

All bird schedules use the global `timezone` from the config file (default: UTC).
All automation schedules use the global `timezone` from the config file (default: UTC).

Schedule format: standard 5-field cron (`0 9 * * 1-5`) or macros (`@daily`, `@hourly`, `@weekly`, `@monthly`).

`birds edit --prompt <text>` replaces the entire prompt; there is no patch primitive. Read the current prompt with `birds list --json` before editing so you do not drop unrelated instructions. The plain `birds list` view truncates the prompt column to 50 characters and is not safe to use as the source of truth.
`automations edit --prompt <text>` replaces the entire prompt; there is no patch primitive. Read the current prompt with `automations list --json` before editing so you do not drop unrelated instructions. The plain `automations list` view truncates the prompt column to 50 characters and is not safe to use as the source of truth.

For long prompts, use `birds edit <uid> --prompt-file <path>` (also available on `birds add`) to read the prompt from a file. Avoids shell-quoting issues with multi-line content or special characters.
For long prompts, use `automations edit <uid> --prompt-file <path>` (also available on `automations add`) to read the prompt from a file. Avoids shell-quoting issues with multi-line content or special characters.

## Docs (system prompt documents)
## Skills (system prompt documents)

```
browserbird docs list List all docs
browserbird docs add <title> Create a new doc
browserbird docs remove <uid|title> Remove a doc and its file
browserbird docs bind <uid|title> channel <id> Bind a doc to a channel
browserbird docs bind <uid|title> bird <uid> Bind a doc to a bird
browserbird docs unbind <uid|title> channel <id> Unbind a doc from a target
browserbird docs sync Scan for new or removed files
browserbird skills list List all skills
browserbird skills add <title> Create a new skill
browserbird skills remove <uid|title> Remove a skill and its file
browserbird skills bind <uid|title> <channel> Bind a skill to a channel
browserbird skills unbind <uid|title> <channel> Unbind a skill from a channel
browserbird skills sync Scan for new or removed files
```

Docs are stored as `.md` files in `.browserbird/docs/`. Edit them directly with any text editor. Docs with no bindings are not injected into agent sessions. Use `docs bind` with `*` as the channel ID to make a doc apply to all channels.
Skills are stored as `.md` files in `.browserbird/docs/`. Edit them directly with any text editor. Skills with no bindings are not injected into agent sessions. Use `skills bind` with `*` as the channel ID to make a skill apply to all channels.

## Keys (vault secrets)

Expand All @@ -46,9 +45,8 @@ browserbird keys list List all vault keys
browserbird keys add <name> Add a key (prompts for value)
browserbird keys edit <name> Update a key's value
browserbird keys remove <name> Remove a key
browserbird keys bind <name> channel <id> Bind a key to a channel
browserbird keys bind <name> bird <uid> Bind a key to a bird
browserbird keys unbind <name> channel <id> Unbind a key from a target
browserbird keys bind <name> <channel> Bind a key to a channel (use * for all)
browserbird keys unbind <name> <channel> Unbind a key from a channel
```

Options for add/edit: `--value <secret>`, `--description <text>`
Expand All @@ -66,7 +64,7 @@ browserbird backups restore <name> Restore from a backup (requires

Options for create: `--name <name>` (custom filename)

Automatic daily backups run at 2:00 AM via system bird. Configure retention and auto-backup in `database.backups` config. Backups are stored in `.browserbird/backups/`.
Automatic daily backups run at 2:00 AM via system automation. Configure retention and auto-backup in `database.backups` config. Backups are stored in `.browserbird/backups/`.

## Sessions

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"lint:fix": "eslint src/ --fix",
"format": "prettier --write src/",
"format:check": "prettier --check src/",
"test": "node --test src/**/*.test.ts",
"test": "node --test \"src/**/*.test.ts\"",
"build": "tsdown",
"dev": "tsdown && ./bin/browserbird",
"dev:web": "cd web && npm run dev",
Expand Down
40 changes: 20 additions & 20 deletions src/channel/blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export function sessionErrorBlocks(
blocks.push(sectionBlock);

const fieldPairs: [string, string][] = [];
if (opts?.birdName) fieldPairs.push(['Bird', opts.birdName]);
if (opts?.birdName) fieldPairs.push(['Automation', opts.birdName]);
if (opts?.durationMs) fieldPairs.push(['Duration', formatDuration(opts.durationMs)]);
if (fieldPairs.length > 0) blocks.push(fields(...fieldPairs));

Expand Down Expand Up @@ -340,7 +340,7 @@ export function birdCreateModal(defaults?: {
return {
type: 'modal',
callback_id: 'bird_create',
title: plain('Create Bird'),
title: plain('Create Automation'),
submit: plain('Create'),
close: plain('Cancel'),
blocks: [
Expand Down Expand Up @@ -375,7 +375,7 @@ export function birdCreateModal(defaults?: {
type: 'plain_text_input',
action_id: 'prompt_input',
multiline: true,
placeholder: plain('What should this bird do?'),
placeholder: plain('What should this automation do?'),
...(defaults?.prompt ? { initial_value: defaults.prompt } : {}),
},
},
Expand Down Expand Up @@ -419,12 +419,12 @@ export function birdListBlocks(
): Block[] {
if (birds.length === 0) {
return [
section('*No birds configured*'),
context('Use `/bird create` to create your first bird.'),
section('*No automations configured*'),
context('Use `/automation create` to create your first automation.'),
];
}

const blocks: Block[] = [header('Active Birds')];
const blocks: Block[] = [header('Active Automations')];

for (const bird of birds) {
const status = bird.enabled ? '[on]' : '[off]';
Expand All @@ -436,7 +436,7 @@ export function birdListBlocks(
);
}

blocks.push(context(`${birds.length} bird${birds.length === 1 ? '' : 's'} total`));
blocks.push(context(`${birds.length} automation${birds.length === 1 ? '' : 's'} total`));

return blocks;
}
Expand All @@ -453,12 +453,12 @@ export function birdLogsBlocks(
): Block[] {
if (flights.length === 0) {
return [
section(`*${birdName}* - No flights yet`),
context('Trigger with `/bird fly ${birdName}`'),
section(`*${birdName}* - No runs yet`),
context('Trigger with `/automation run ${birdName}`'),
];
}

const blocks: Block[] = [header(`Flights: ${birdName}`)];
const blocks: Block[] = [header(`Runs: ${birdName}`)];

const lines = flights.map((f) => {
const icon = f.status === 'success' ? '[ok]' : f.status === 'running' ? '[...]' : '[err]';
Expand All @@ -469,7 +469,7 @@ export function birdLogsBlocks(
});

blocks.push(section(lines.join('\n')));
blocks.push(context(`${flights.length} most recent flight${flights.length === 1 ? '' : 's'}`));
blocks.push(context(`${flights.length} most recent run${flights.length === 1 ? '' : 's'}`));

return blocks;
}
Expand All @@ -486,7 +486,7 @@ function formatAge(isoDate: string): string {
}

export function birdFlyBlocks(birdName: string, userId: string): Block[] {
return [section(`*${birdName}* is taking flight...`), context(`Triggered by <@${userId}>`)];
return [section(`*${birdName}* is running...`), context(`Triggered by <@${userId}>`)];
}

export function statusBlocks(opts: {
Expand All @@ -504,13 +504,13 @@ export function statusBlocks(opts: {
fields(
['Slack', slackStatus],
['Active Sessions', `${opts.activeCount}/${opts.maxConcurrent}`],
['Birds', String(opts.birdCount)],
['Automations', String(opts.birdCount)],
['Uptime', opts.uptime],
),
];

if (opts.runningBirds && opts.runningBirds.length > 0) {
result.push(section(`*In flight:* ${opts.runningBirds.join(', ')}`));
result.push(section(`*Running:* ${opts.runningBirds.join(', ')}`));
}

return result;
Expand All @@ -527,11 +527,11 @@ export function homeTabView(opts: {
header(opts.agentName),
section(opts.description),
divider(),
header('Scheduled Birds'),
header('Scheduled Automations'),
];

if (opts.birds.length === 0) {
blocks.push(section('No birds configured. Use `/bird create` to get started.'));
blocks.push(section('No automations configured. Use `/automation create` to get started.'));
} else {
const lines = opts.birds.map((b) => {
const status = b.enabled ? 'on' : 'off';
Expand All @@ -545,10 +545,10 @@ export function homeTabView(opts: {
header('Quick Commands'),
section(
[
'`/bird list` -- show all birds',
'`/bird create` -- create a new bird',
'`/bird fly <name>` -- trigger a bird now',
'`/bird status` -- check system status',
'`/automation list` -- show all automations',
'`/automation create` -- create a new automation',
'`/automation run <name>` -- trigger an automation now',
'`/automation status` -- check system status',
].join('\n'),
),
divider(),
Expand Down
Loading