Workspaces & teams
Workspace = billing/admin boundary + owns apps. Team = member sub-group inside the workspace. Grants link teams to apps.
The model
Workspace ─── billing + admin boundary, owns apps
├── plan (Free / Pro / Enterprise)
├── billing contact, invoices
├── workspace-level audit log
├── Workspace members ──► role: owner / admin / member
├── Teams ──► sub-groups of members
│ └── Team members ──► role: owner / manager / member
└── Apps ──► owned by the workspace
└── App-team grants ──► viewer / deployer / adminThe thing this diagram does not show is "apps belonging to a team" — because they don't. Apps belong to the workspace. A team's relationship to an app is granted, not owned. This matters when you're thinking about access:
- A workspace admin sees all apps in the workspace.
- A team member sees only the apps that the team (or their email) has been granted.
Workspace member roles
| Role | What it unlocks |
|---|---|
member | Be in the workspace; see what app-level grants give you |
admin | Create teams, manage workspace settings, see all apps |
owner | Plus billing, plan changes, workspace deletion |
You can belong to multiple workspaces (e.g. personal + work). The CLI defaults to the workspace stored in ~/.config/vibehost/config.json — switch with vibehost workspace use <slug>.
When to add a team
For a 1–3 person account, one team is usually enough. Add more when:
- You want grant isolation: members of Team A shouldn't pick up app grants from Team B.
- You're modeling org structure: each team mirrors a real-world group (squad, department, contractor).
- You want to share many apps with one grant: "everyone on the Web team can deploy to all marketing apps" is one grant per app on the team, not N grants per email.
vibehost team create web # slug — DNS-safe, lowercase
vibehost team ls
vibehost team switch web # make 'web' the current team
vibehost team info # current team settingsTeam slugs appear in every generated app URL (<app>-<slug>.vibehost.space), so pick a short DNS-safe one.
Team member roles
| Role | What it unlocks |
|---|---|
member | Be in the team; receive whatever app grants the team has |
manager | Manage team members + team settings |
owner | Plus delete the team |
These are roles within the team. They don't grant anything on apps by themselves — the team has to receive an app grant separately (see Grants and visibility).
Inviting people
Invites work at two layers — workspace and team — and the right one depends on how broad you want the access to be.
# Invite to the current workspace (workspace owner/admin only).
# Use this when the invitee's email isn't covered by the workspace's
# allowed-domain list. Prints a single-use link.
vibehost workspace invite teammate@x.com --role member # admin | member
# Invite to the current team. Prints a sign-in link to paste into
# Slack/email. Only the invitee's email can accept; forwarded links
# are rejected server-side.
vibehost team invite teammate@x.com --role member # member | managerIf your workspace has a verified domain (see below), users matching that domain auto-join — you don't need to invite them individually.
Linking teams to apps
A team gaining access to an app is a separate operation from team membership. Use app grants:
vibehost app grants add-team <team-slug> deployer --app my-siteNow every member of the team has the deployer role on my-site. Add more grants for more apps; revoke per-app with app grants remove-team.
For one-off invites without a team, grant by email:
vibehost app grants add-email contractor@x.com viewer --app my-siteWorkspace-level actions
vibehost workspace ls # workspaces you belong to
vibehost workspace use <slug> # switch active workspace
vibehost workspace info # current workspace detail
vibehost workspace members # who's in this workspace
vibehost workspace role <email> <role> # change a member's roleWorkspace verified domains (auto-join)
For company workspaces, add a verified domain so anyone signing up with a matching email auto-joins:
vibehost workspace domain ls
vibehost workspace domain add yourcompany.com --tier verified
# → prints a DNS TXT record. Add it at your registrar, then:
vibehost workspace domain verify <id>Two tiers:
verified— DNS TXT proves the workspace owns the domain. Matching users auto-join at thememberrole.member— no DNS, must match an existing member's domain. Matching users see a prompt to join, no auto-join.
Common gotchas
- Apps are unique per workspace —
apps.workspaceIdis the owning column; the per-appprimaryTeamIdis just optional metadata. - Team slugs appear in URLs — picking a short DNS-safe slug matters; rename with
vibehost team rename-slug <new-slug>(the slug stays stable when the team's display name changes, by design). - PATs are bound to one workspace — a PAT created in workspace A can't call workspace B's API even if you also belong to B. Create separate PATs per workspace. (See Hard Rule #8 —
TOKEN_WORKSPACE_MISMATCH.) - A workspace admin doesn't auto-pick up team membership — admins see all apps, but actions that check team-based grants still require the admin to be a team member. (Usually a non-issue because workspace admins are also team members of every relevant team.)