> ## Documentation Index
> Fetch the complete documentation index at: https://docs.duvo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Profiles and Teams

> Manage stored CLI profiles, switch between teams, and inspect team membership with the Duvo CLI.

The CLI stores credentials as **named profiles** — each holds either an OAuth session or an API key, so you can switch between teams or workspaces without re-entering credentials. This page is the reference for managing those profiles and the teams they act on. For first-time sign-in, see [Sign in](/cli/index#sign-in).

## Profiles

```bash theme={"dark"}
duvo whoami                          # show the active profile, its key prefix, and team
duvo profiles list                   # list all stored profiles (the default is marked)
duvo profiles use [name]             # switch the default profile (interactive picker if name omitted)
duvo profiles rename <old> <new>     # rename a profile, preserving its credentials
duvo profiles remove <name>          # remove a profile locally
```

### Use a different profile for a single command

```bash theme={"dark"}
duvo agents list --profile staging
```

`--profile <name>` works on every command and doesn't change your default.

### Sign out

```bash theme={"dark"}
duvo logout                          # sign out of the active profile
duvo logout --name <profile>         # sign out of a specific profile
duvo logout --all                    # sign out of every stored profile
```

`duvo logout` revokes the OAuth tokens server-side and removes the profile locally.

### Environment variables

For non-interactive use (CI, scripts), the CLI also reads:

| Variable | Description |
| - | - |
| `DUVO_API_KEY` | API key — bypasses the stored profile entirely |
| `DUVO_PROFILE` | Profile name to use instead of the default |

## Teams

A profile's credentials are scoped to a team. Use these commands to confirm which team you're acting on and inspect its members before running commands that change data.

```bash theme={"dark"}
duvo team current                                                  # the team scoped to your active credentials
duvo team get                                                      # full details for that team
duvo team use <team-id>                                            # set the team for the active profile
duvo team members [--team <team-id>] [--limit <n>] [--offset <n>]  # list team members
duvo teams list                                                    # list every team your credentials can act on
duvo teams orgs                                                    # list the organizations you belong to and your role in each
duvo teams org <org-id>                                            # list all teams in an organization you belong to
duvo teams create-org-team <org-id> --name <name>                  # create a new team in an organization you administer (org Admin, Executive, or Owner)
duvo teams create-workspace                                        # get your workspace: its organization and team, Clarity access, interviews left, and the link to upgrade the plan
duvo teams org-agents <org-id> [--team <team-id>] [--scheduled|--unscheduled] [--auto-disabled|--not-auto-disabled]  # every agent in the org with its last run and schedule state (org admins and above)
duvo teams org-runs <org-id> [--status <status>] [--created-after <iso>] [--created-before <iso>] [--started-after <iso>] [--started-before <iso>] [--completed-after <iso>] [--completed-before <iso>]  # runs across every team in the org, filterable for monitoring (org admins and above)
duvo teams org-insights <org-id> [--start-date] [--end-date]       # org-wide run KPIs across all teams (org admins and above)
duvo teams org-metrics <org-id> [--start-date] [--end-date]        # per-team run metrics across the org (org admins and above)
duvo teams org-usage <org-id> [--granularity day|week|month]       # org-wide run volume over time (org admins and above)
```

If `--team` is omitted, member listing uses the team scoped to your API key or active profile. Add `--json` to any command for machine-readable output.

The `org-*` commands are the exception to the team scoping above. They read across every team in the organization, so a key pinned to a single team is rejected — use one created with access set to all teams you can access, and an organization Admin, Executive, or Owner role.

`org-runs` carries one time window per lifecycle timestamp, and they are not interchangeable. Reach for `--created-after` / `--created-before` to ask "everything in this period": every run has a creation time, so that window drops nothing. `--started-after` / `--started-before` excludes runs that never started — pair both ends with `--status running` to bound a stuck-run sweep, since a lower bound is what stops it also counting runs left running months ago. `--completed-after` / `--completed-before` filter on *completion*, so they never match a run that is still going — they are also accepted as `--since` / `--until`, the names `duvo runs list` ships, but the column-named pair is the one to reach for here, where all three windows exist side by side. Every bound is half-open (`[after, before)`), so consecutive windows tile without counting a run twice, and the three windows combine.

With no time bound at all, `org-runs` returns the last 7 days of runs and says so (`default window: last 7 days` in the summary line). An organization's history is unbounded and a monitor wants what is recent, so the default keeps an unfiltered poll cheap however long the organization has been running. Pass any bound — on creation, start or completion — to replace it.

`org-runs` does not count matches unless asked: without `--include-total` the response carries no total, so a full page is reported as `More may be available` alongside the `--offset` that reaches the next one. Pass `--include-total` for `Showing X of Y` — it walks every match, which is the expensive half of an org-wide query.

`org-runs` pages up to 500 runs at a time (`--limit 500`), five times the team `runs list` cap, because pulling an organization's history is rate-bound rather than query-bound: the API allows 100 requests a minute per key, so page size decides how fast a month of runs comes back.

To read more than one page, follow the cursor: every page that has a successor prints `Next page: --cursor <value>`, and passing that value (with the same filters) returns exactly the runs after the one you last saw. There is no `--offset` here, unlike `runs list` and `teams org-agents`: runs are created constantly, so an offset sweep can repeat a run at a page boundary or, on a `--status needs_attention` poll where runs are also being resolved, skip one. A cursor does neither. Agents are a small, slow-changing directory, which is why that list keeps `--offset`.

### Manage people already on the team

These change who is on the team and what they can do. `duvo invite` is for people who haven't joined yet.

```bash theme={"dark"}
duvo team set-role <member-id> --role <role>   # change a member's role
duvo team remove-member <member-id> [--yes]    # remove someone from the team
duvo team leave [--yes]                        # leave a team yourself
```

Pass `--team <team-id>` to act on a team other than the active one, and `--json` for machine-readable output. Get member ids from `duvo team members`.

Both `remove-member` and `leave` ask for confirmation before acting; pass `--yes` to skip the prompt in scripts. In a non-interactive shell they refuse rather than treat piped input as consent.

| Command | Role required |
| - | - |
| `set-role` | Manager and above. Only an Owner can grant or remove the Owner role, and the last remaining Owner cannot be demoted. |
| `remove-member` | Superadmin and above. The last remaining Owner cannot be removed. |
| `leave` | Any member. A member whose Owner role is inherited from the organization can leave, but cannot be removed by someone else. |

### Invite people

`duvo invite` covers both team and organization invitations. Team commands honour `--team`; `invite org-member` takes the organization id positionally and needs an org Admin, Executive, or Owner role.

<Note>`duvo teams invite-org-member` was removed in 1.46.0 with no alias. Use `duvo invite org-member <org-id>` instead.</Note>

```bash theme={"dark"}
duvo invite list                                                   # pending invitations for the current team
duvo invite list --process <process-id>                            # pending invitations for one Clarity process
duvo invite create --email <email> [--role <role>] [--send-email]  # invite one person (Manager and above)
duvo invite create --email <email> --process <process-id> [--process-role <role-id>] [--send-email]  # invite them to a Clarity process (team:clarity-member)
duvo invite bulk --member <email> --member <email>=team:manager     # invite several people and email each (max 50)
duvo invite update <invite-id> --role <role>                       # change the role on a pending invitation
duvo invite resend <invite-id>                                     # email an invitation to its recipient
duvo invite delete <invite-id> [--yes]                             # revoke a pending invitation (alias: revoke)
duvo invite org-member <org-id> --email <email> [--role <role>] [--team-id <team-id>] [--send-email]  # invite a person to an org, optionally onto a team
duvo invite link get                                               # show the team's shareable invite link
duvo invite link create                                            # create or regenerate it (invalidates the previous URL)
duvo invite link delete [--yes]                                    # delete it
```

Use `--process-role` with `--process` to attach one of that Process's configured roles. The team invitation remains a Clarity Member invitation; an existing teammate keeps their team role. Reusing an invitation with a different Process assignment fails without replacing the original assignment.

<Warning>Creating an invitation does not email anyone. `duvo invite create` and `duvo invite org-member` only send mail when you pass `--send-email`. Without it the invitation exists but nobody is notified; run `duvo invite resend <invite-id>` to deliver it. `duvo invite bulk` always emails.</Warning>

<Note>When you ask for an email and it does not go out, the command still prints the invitation ID and then exits non-zero, so a script can tell that the delivery failed. If the failure was ambiguous — a timeout or a gateway error, where the server may already have sent the mail — the message says so rather than claiming nobody was notified; check with the recipient before resending, or you may deliver a second invitation. `duvo invite bulk` exits non-zero when any invitation was rolled back.</Note>

<Note>No command takes a frontend URL. The accept link is built server-side from the environment's configured app origin, so an invitation email always points at the real Duvo app.</Note>

### Confirm your team before a destructive command

```bash theme={"dark"}
duvo team current --json | jq -r '.team.name'
```

<Warning>Running this first is a cheap way to make sure a bulk delete or delegate lands on the team you intend.</Warning>

## Related

<CardGroup cols={2}>
  <Card title="Duvo CLI" icon="terminal" href="/cli/index">
    installation and first sign-in
  </Card>

  <Card title="Scripting and CI/CD Patterns" icon="git-branch" href="/cli/scripting-and-ci">
    authenticating with API keys in pipelines
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.