Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 18 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@

**Dailybot CLI** is a Python command-line tool that bridges **humans** and **agents** with the [Dailybot](https://www.dailybot.com) platform. It provides:

- **For humans** — email-OTP login, viewing pending check-ins, submitting structured/free-text updates, interactive TUI mode.
- **For agents (AI assistants, CI jobs, deploy scripts, bots)** — progress reports, milestone tracking, agent health, webhook registration, agent-to-agent messaging, transactional email, and standalone agent registration (creates an org without a human Dailybot account).
- **For humans** — email-OTP login, viewing pending check-ins, submitting structured/free-text updates, **filling out forms** (one-shot or driven through a workflow state machine: `pre_release → qa → code_review → ready_to_release → released`), **browsing teams** (role-scoped server-side), **giving kudos to users or whole teams**, interactive TUI mode.
- **For agents (AI assistants, CI jobs, deploy scripts, bots)** — progress reports, milestone tracking, agent health, webhook registration, agent-to-agent messaging, transactional email, standalone agent registration (creates an org without a human Dailybot account), **and the full forms-response lifecycle** (`get / responses / response get / update / transition / delete`) so an agent can drive any form — including workflow-enabled ones — end-to-end after `dailybot login`.

It talks exclusively to the Dailybot HTTP API under `/v1/cli/*` and `/v1/agent*/*` endpoints. There is no local database; all state is either in `~/.config/dailybot/` (credentials, agent profiles, config) or fetched from the API.
It talks exclusively to the Dailybot HTTP API under `/v1/cli/*`, `/v1/agent*/*`, `/v1/forms/*`, `/v1/teams/*`, `/v1/kudos/`, `/v1/users/`, and `/v1/checkins/*` endpoints. There is no local database; all state is either in `~/.config/dailybot/` (credentials, agent profiles, config) or fetched from the API.

**Stack:** Python 3.10+, [Click](https://click.palletsprojects.com/) 8.3+, [httpx](https://www.python-httpx.org/) 0.28+, [questionary](https://questionary.readthedocs.io/) 2.1+, [rich](https://rich.readthedocs.io/) 15+. Tested with `pytest`. Built and packaged with `setuptools`; distributed via PyPI, Homebrew tap (`dailybothq/tap`), a PyInstaller-built Linux x86_64 binary, and a PowerShell installer (`install.ps1`) that wraps `pipx`/`uv`/`pip` for native Windows users.

Expand All @@ -55,6 +55,15 @@ dailybot_cli/ # Source package
├── status.py # pending check-ins + --auth status
├── update.py # submit human check-in update
├── config.py # get/set/remove stored settings (api_key)
├── checkin.py # `checkin` group: list / complete (user-scoped)
├── form.py # `form` group: list / get / submit / responses /
│ # response get / update / transition / delete
├── team.py # `team` group: list / get (server-scoped by role)
├── kudos.py # `kudos give` (to a user, a team, or both)
├── user.py # `user list` (org directory)
├── public_api_helpers.py # require_bearer_auth, exit_for_api_error,
│ # ERROR_CODE_MESSAGES, resolve_user_/team_by_name_or_uuid
├── user_scoped_actions.py # shared handlers for checkin + form (used by CLI + TUI)
├── interactive.py # questionary-based TUI when run with no args
├── version.py # `dailybot version` — install info + PyPI update check
├── upgrade.py # `dailybot upgrade` — auto-detect install method + self-update
Expand All @@ -63,8 +72,12 @@ dailybot_cli/ # Source package
# update, health, webhook, message, email

tests/ # pytest suite (file naming: *_test.py)
├── api_client_test.py # HTTP client mocking
├── commands_test.py # Click CliRunner invocations
├── api_client_test.py # HTTP client mocking (all DailyBotClient methods)
├── commands_test.py # Click CliRunner — agent + interactive + auth flows
├── public_api_commands_test.py # Click CliRunner — checkin, form (lifecycle),
│ # team, kudos, user (all Bearer-token paths)
├── form_question_types_test.py # guided-prompt type classifier
├── repo_profile_test.py # `.dailybot/profile.json` resolution
└── config_test.py # Config/credential file management

.github/workflows/release.yml # Tag-triggered: PyPI + Linux binary + Homebrew
Expand Down
74 changes: 65 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ dailybot checkin complete <followup_uuid> -a 0="Done" --yes --json
# List all forms visible to you (includes question count)
dailybot form list

# Get a form's full payload (questions + workflow states + permissions)
dailybot form get <form_uuid>

# Submit a form — guided mode (prompts each question by label and type)
dailybot form submit <form_uuid>

Expand All @@ -143,11 +146,36 @@ dailybot form submit <form_uuid> \
--content '{"<question-uuid>":"Great week!", "<question-uuid-2>":"No blockers"}' \
--yes

# List your own responses on a form
dailybot form responses <form_uuid>
dailybot form responses <form_uuid> --state qa --json
dailybot form responses <form_uuid> --latest --json # continue where you left off

# Operate on a single response
dailybot form response get <form_uuid> <response_uuid>
dailybot form update <form_uuid> <response_uuid> --content '{"<q-uuid>":"PR #4242"}'
dailybot form transition <form_uuid> <response_uuid> qa --note "QA assigned"
dailybot form delete <form_uuid> <response_uuid>

# Machine-readable JSON output
dailybot form list --json
dailybot form submit <form_uuid> --content '{"<q-uuid>":"Yes"}' --yes --json
```

### Workflow-enabled forms

When a form has `workflow_enabled: true`, every response carries a workflow-state surface that the CLI prints after every mutating call:

| Field | Meaning |
|---|---|
| `current_state` | The effective current state. |
| `allowed_transitions` | List of `{to_state, label}` for every reachable next state. |
| `can_change_state` | Whether the caller is in the form's `state_change_permission` audience. |
| `allow_reopen_from_final_state` | Form-level — `false` (default) means the terminal state is sticky. |
| `state_history` | Append-only audit trail of every transition. |

The form's `state_change_permission` audience is the sole gate for `dailybot form transition` — there is no response-author short-circuit. If you're not in the audience, the API returns 403 with `code: form_response_change_state_forbidden`.

Guided mode (`form submit` without `--content`) fetches the form's question list from the API and prompts each question one by one, with type-aware inputs:

| Question type | Prompt |
Expand All @@ -170,9 +198,15 @@ Guided mode (`form submit` without `--content`) fetches the form's question list
## Kudos

```bash
# Give kudos — receiver resolved by full name against your org directory
# Give kudos to a user — receiver resolved by full name against your org directory
dailybot kudos give --to "Jane Doe" --message "Shipped the auth refactor cleanly, great work!"

# Give kudos to an entire team (resolved against GET /v1/teams/)
dailybot kudos give --team "Engineering" --message "Shipped flawlessly"

# Combine both — single message goes to one user and a whole team
dailybot kudos give --to "Alice" --team "QA" --message "Both nailed it"

# Resolve by UUID instead
dailybot kudos give --to <user-uuid> --message "Thanks for the PR review." --yes

Expand All @@ -183,13 +217,16 @@ dailybot kudos give --to "Jane Doe" --message "Great!" --value <company-value-uu
dailybot kudos give --to "Jane Doe" --message "Great!" --yes --json
```

If `--to` matches more than one name partially, the CLI lists the ambiguous matches and exits — it never guesses. Pass the full name or a UUID to be precise.
If `--to` or `--team` matches more than one name partially, the CLI lists the ambiguous matches and exits — it never guesses. Pass the full name or a UUID to be precise. At least one of `--to` or `--team` is required.

Team kudos pass through the backend's team manager, which expands the team into its active members and excludes the caller — so giving kudos to a team you belong to is valid (you credit your teammates, not yourself).

### `dailybot kudos give` options

| Flag | Short | Description |
|------|-------|-------------|
| `--to` | `-t` | Receiver full name or UUID. Required. |
| `--to` | `-t` | User full name or UUID. Optional when `--team` is provided. |
| `--team` | | Team name or UUID. Optional when `--to` is provided. |
| `--message` | `-m` | Kudos message (team-visible). Required. |
| `--value` | | Optional company value UUID. |
| `--yes` | `-y` | Skip the confirmation prompt. |
Expand All @@ -205,26 +242,37 @@ dailybot user list

# Machine-readable
dailybot user list --json

# List teams visible to you (scoped server-side by your role)
dailybot team list

# Get a single team by UUID or name; optionally include members
dailybot team get "Engineering"
dailybot team get <team_uuid> --with-members --json
```

The table shows **Name** and **User UUID**. You can copy a UUID directly into `dailybot kudos give --to <uuid>` for precise targeting.
The `user list` table shows **Name** and **User UUID**. You can copy a UUID directly into `dailybot kudos give --to <uuid>` for precise targeting.

`team list` is **role-scoped server-side**: org admins see all teams in the organization; members see only the teams they belong to. The CLI never client-filters — it shows the server response verbatim. If `dailybot kudos give --team "X"` errors with a "not visible to you" message, the team either doesn't exist or you're not a member.

---

## User-scoped exit codes

All user-scoped commands (`checkin`, `form`, `kudos`, `user`) use structured exit codes for scripting:
All user-scoped commands (`checkin`, `form`, `kudos`, `user`, `team`) use structured exit codes for scripting:

| Code | Meaning |
|------|---------|
| `0` | Success |
| `2` | Invalid input (bad format, ambiguous receiver) |
| `2` | Invalid input (bad format, ambiguous receiver, 400 from server) |
| `3` | Not logged in — run `dailybot login` |
| `4` | Permission denied (403), self-kudos, or daily kudos limit reached |
| `5` | Form response quota exhausted |
| `4` | Permission denied (403), self-kudos, daily kudos limit, or `final_state_locked` |
| `5` | Resource not found (404) or form response quota exhausted (402) |
| `6` | Rate limited — wait and retry |
| `7` | User declined the confirmation prompt |

`--json` output for any 4xx surfaces both `detail` (server-provided text) and the structured `code` field — chat-agent consumers can pattern-match on the code (`form_response_change_state_forbidden`, `final_state_locked`, `form_response_not_found`, `no_valid_team`, etc.) without parsing prose.

## For agents

Any software agent — AI coding assistants, CI jobs, deploy scripts, bots — can report activity through the CLI. This lets teams get visibility into what automated processes are doing, alongside human updates. Dailybot interconnects agents and humans with work analysis, progress reports, observability, and automations.
Expand Down Expand Up @@ -491,19 +539,27 @@ Replies to agent emails land as messages retrievable via `dailybot agent message
| Command | Description |
|---------|-------------|
| `dailybot form list` | List forms visible to you (includes question count) |
| `dailybot form get <uuid>` | Show the form's full payload (questions + workflow states) |
| `dailybot form submit <uuid>` | Submit a form (guided prompts or `--content` JSON) |
| `dailybot form responses <uuid>` | List your own responses on a form (`--state`, `--latest`) |
| `dailybot form response get <uuid> <resp_uuid>` | Show a single response (state + history + answers) |
| `dailybot form update <uuid> <resp_uuid>` | Patch new answers into an in-progress response |
| `dailybot form transition <uuid> <resp_uuid> <state>` | Advance a response through the workflow |
| `dailybot form delete <uuid> <resp_uuid>` | Delete a response (author / owner / admin) |

### Kudos

| Command | Description |
|---------|-------------|
| `dailybot kudos give` | Give kudos to a teammate by name or UUID |
| `dailybot kudos give` | Give kudos to a user (`--to`), a team (`--team`), or both |

### Team

| Command | Description |
|---------|-------------|
| `dailybot user list` | List all members in your organization |
| `dailybot team list` | List teams visible to you (scoped server-side by role) |
| `dailybot team get <uuid_or_name>` | Show a team; add `--with-members` for the member list |

### Agent commands

Expand Down
Loading