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

# Publish a team to CliqHub

> Packages the manifest you send (plus `dockerfile`, `dependencies` and `roles`
when given) and publishes it to CliqHub as the version in the manifest's
top-level `version:` field. The local catalog is not read, so a team does not
have to be installed to be published.

Use `dry_run: true` to run every local check (scope, version, sign-in, target
CliqHub) without uploading; the reply then has `published: false`.

`force` is accepted but has no effect: CliqHub never overwrites a published
version (`HUB_VERSION_ALREADY_EXISTS`).

From the CLI: `cliq team publish ./path/to/team --access private`.

No credential is needed from this machine. From another host, send `Authorization: Bearer` with a dispatch token CliqHub signed for this daemon or a `cliq_tok_…` personal token of a user in the daemon's realm; this only works once the daemon is connected to CliqHub. See [Authentication](/daemon-api/overview#authentication).



## OpenAPI

````yaml /openapi/daemon-by-tag/daemon-teams.yaml post /v1/teams/publish
openapi: 3.1.0
info:
  title: cliqd API
  version: 1.9.48
  description: >-
    HTTP API of `cliqd`, the local Cliq daemon. Generated from the daemon source
    by `scripts/generate_daemon_openapi.mjs` — do not edit by hand. See the
    [overview](/daemon-api/overview).
servers:
  - url: http://127.0.0.1:4900
    description: Local daemon (default port; `CLIQ_DAEMON_PORT` changes it)
security: []
tags:
  - name: Daemon Teams
    description: >-
      The daemon's **local team catalog**: the teams this cliqd can run. Install
      a team

      from a manifest you hold (`teams/install`) or from CliqHub
      (`teams/hub_install`),

      read it back, update it, remove it, and publish manifests to CliqHub.


      A team is addressed by **scope + slug** (`@acme/code-review` → `scope:
      "acme"`,

      `slug: "code-review"`). The scope `local` is offline-only: it needs no
      CliqHub

      sign-in and can never be published. Every other scope needs `cliq login`
      first.
paths:
  /v1/teams/publish:
    post:
      tags:
        - Daemon Teams
      summary: Publish a team to CliqHub
      description: >-
        Packages the manifest you send (plus `dockerfile`, `dependencies` and
        `roles`

        when given) and publishes it to CliqHub as the version in the manifest's

        top-level `version:` field. The local catalog is not read, so a team
        does not

        have to be installed to be published.


        Use `dry_run: true` to run every local check (scope, version, sign-in,
        target

        CliqHub) without uploading; the reply then has `published: false`.


        `force` is accepted but has no effect: CliqHub never overwrites a
        published

        version (`HUB_VERSION_ALREADY_EXISTS`).


        From the CLI: `cliq team publish ./path/to/team --access private`.


        No credential is needed from this machine. From another host, send
        `Authorization: Bearer` with a dispatch token CliqHub signed for this
        daemon or a `cliq_tok_…` personal token of a user in the daemon's realm;
        this only works once the daemon is connected to CliqHub. See
        [Authentication](/daemon-api/overview#authentication).
      operationId: daemon_post_teams_publish
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                  minLength: 1
                  description: Team scope (org namespace)
                slug:
                  type: string
                  minLength: 1
                  description: Team slug
                manifest:
                  type: string
                  minLength: 1
                  description: Team manifest (YAML)
                dependencies:
                  description: Dependency manifest
                  type: string
                  minLength: 1
                dockerfile:
                  description: Dockerfile shipped with the team
                  type: string
                  minLength: 1
                roles:
                  description: Role files (`roles/*.md`)
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                        minLength: 1
                        description: Role file name
                      content:
                        type: string
                        minLength: 1
                        description: Role file content
                    required:
                      - name
                      - content
                access:
                  default: public
                  description: Hub visibility
                  type: string
                  enum:
                    - draft
                    - public
                    - private
                message:
                  description: Release note
                  type: string
                  minLength: 1
                registry_url:
                  description: Hub registry override
                  type: string
                  minLength: 1
                force:
                  description: Publish over an existing version
                  type: boolean
                dry_run:
                  description: Validate without publishing
                  type: boolean
              required:
                - scope
                - slug
                - manifest
            examples:
              publish:
                summary: Publish privately with a release note
                value:
                  scope: acme
                  slug: code-review
                  manifest: |
                    name: code-review
                    version: 1.5.0
                    description: Reviews a pull request and posts findings.
                    phases:
                      - name: review
                        agent: claude-code
                  roles:
                    - name: reviewer.md
                      content: |-
                        # Reviewer
                        You review pull requests for correctness.
                  access: private
                  message: Adds the reviewer role.
              dry_run:
                summary: Check without uploading
                value:
                  scope: acme
                  slug: code-review
                  manifest: |
                    name: code-review
                    version: 1.5.0
                    description: Reviews a pull request and posts findings.
                    phases:
                      - name: review
                        agent: claude-code
                  dry_run: true
      responses:
        '200':
          description: Success.
          content:
            application/json:
              schema:
                type: object
                required:
                  - ok
                  - data
                properties:
                  ok:
                    type: boolean
                    const: true
                  data:
                    $ref: '#/components/schemas/TeamPublishResult'
              example:
                ok: true
                data:
                  scope: acme
                  slug: code-review
                  version: 1.5.0
                  registry_url: https://api.cliqhub.io
                  published: true
        '400':
          description: >-
            `TEAM_VALIDATE_FAILED` — The scope is `local` (offline-only), or the
            manifest has no top-level `version:`.


            `PAYLOAD_INVALID` — The body (query string for `GET`) fails the
            request schema. `details` lists each issue.


            `BAD_REQUEST` — The body is not valid JSON or is larger than the
            route allows (10 MB; artifact uploads more).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                TEAM_VALIDATE_FAILED:
                  summary: TEAM_VALIDATE_FAILED
                  value:
                    ok: false
                    error:
                      code: TEAM_VALIDATE_FAILED
                      message: >-
                        Manifest has no 'version' field — set one before
                        publishing
                PAYLOAD_INVALID:
                  summary: PAYLOAD_INVALID
                  value:
                    ok: false
                    error:
                      code: PAYLOAD_INVALID
                      message: >-
                        scope: Invalid input: expected string, received
                        undefined; slug: Invalid input: expected string,
                        received undefined; manifest: Invalid input: expected
                        string, received undefined
                      details:
                        - path: scope
                          message: 'Invalid input: expected string, received undefined'
                        - path: slug
                          message: 'Invalid input: expected string, received undefined'
                        - path: manifest
                          message: 'Invalid input: expected string, received undefined'
                BAD_REQUEST:
                  summary: BAD_REQUEST
                  value:
                    ok: false
                    error:
                      code: BAD_REQUEST
                      message: >-
                        Request body could not be read: Unexpected token } in
                        JSON at position 12
        '401':
          description: >-
            `UNAUTHORIZED` — A caller on another host sent no `Authorization:
            Bearer` token, or one that does not verify (expired, wrong
            audience).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                UNAUTHORIZED:
                  summary: UNAUTHORIZED
                  value:
                    ok: false
                    error:
                      code: UNAUTHORIZED
                      message: Missing or invalid Authorization Bearer token
        '403':
          description: >-
            `FOREIGN_HUB_REFUSED` — `registry_url` is on a different origin than
            the CliqHub this daemon is signed in to.


            `WEB_REQUEST_REFUSED` — The request carries an `Origin` header (it
            came from a web page).


            `HOST_NOT_LOCAL` — A loopback caller addressed a `Host` other than
            localhost (DNS rebinding guard).


            `LOCAL_ONLY` — The daemon isn't connected to CliqHub (no dispatch
            key) and the caller is on another host.


            `FORBIDDEN` — A `cliq_tok_…` token's user is not in this daemon's
            realm ACL, or the ACL is not loaded yet.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                FOREIGN_HUB_REFUSED:
                  summary: FOREIGN_HUB_REFUSED
                  value:
                    ok: false
                    error:
                      code: FOREIGN_HUB_REFUSED
                      message: cliqd won't send your CliqHub sign-in to another site
                WEB_REQUEST_REFUSED:
                  summary: WEB_REQUEST_REFUSED
                  value:
                    ok: false
                    error:
                      code: WEB_REQUEST_REFUSED
                      message: cliqd doesn't accept requests from web pages
                HOST_NOT_LOCAL:
                  summary: HOST_NOT_LOCAL
                  value:
                    ok: false
                    error:
                      code: HOST_NOT_LOCAL
                      message: cliqd only answers requests addressed to localhost
                LOCAL_ONLY:
                  summary: LOCAL_ONLY
                  value:
                    ok: false
                    error:
                      code: LOCAL_ONLY
                      message: >-
                        This cliqd isn't connected to CliqHub yet, so from
                        another machine it only accepts a local token (minted by
                        tokens/create on the machine running cliqd)
                FORBIDDEN:
                  summary: FORBIDDEN
                  value:
                    ok: false
                    error:
                      code: FORBIDDEN
                      message: Access denied — identity not in realm ACL
        '409':
          description: >-
            `HUB_VERSION_ALREADY_EXISTS` — That version of the team is already
            published on CliqHub. Bump `version:` in the manifest.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                HUB_VERSION_ALREADY_EXISTS:
                  summary: HUB_VERSION_ALREADY_EXISTS
                  value:
                    ok: false
                    error:
                      code: HUB_VERSION_ALREADY_EXISTS
                      message: Version 1.5.0 of @acme/code-review already exists
        '422':
          description: '`HUB_NOT_CONFIGURED` — No CliqHub URL or token is configured.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                HUB_NOT_CONFIGURED:
                  summary: HUB_NOT_CONFIGURED
                  value:
                    ok: false
                    error:
                      code: HUB_NOT_CONFIGURED
                      message: 'No hub token configured. Run: cliq login'
        '500':
          description: >-
            `INTERNAL_ERROR` — An unexpected daemon fault. The message names the
            request id; the cause is in the cliqd log.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                INTERNAL_ERROR:
                  summary: INTERNAL_ERROR
                  value:
                    ok: false
                    error:
                      code: INTERNAL_ERROR
                      message: >-
                        cliqd hit an unexpected error (request 7f3a…). Details
                        are in the cliqd log.
        '502':
          description: >-
            `HUB_PUBLISH_FAILED` — CliqHub could not be reached or rejected the
            package. The message is CliqHub's.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorReply'
              examples:
                HUB_PUBLISH_FAILED:
                  summary: HUB_PUBLISH_FAILED
                  value:
                    ok: false
                    error:
                      code: HUB_PUBLISH_FAILED
                      message: >-
                        Failed to reach Hub at https://api.cliqhub.io: fetch
                        failed
      security:
        - {}
        - DaemonBearer: []
components:
  schemas:
    TeamPublishResult:
      type: object
      required:
        - scope
        - slug
        - version
        - registry_url
        - published
      properties:
        scope:
          type: string
          example: acme
        slug:
          type: string
          example: code-review
        version:
          type: string
          description: The manifest's top-level `version`, which is the version published.
          example: 1.5.0
        registry_url:
          type: string
          format: uri
          description: >-
            The CliqHub API the team was (or, on a dry run, would be) published
            to.
          example: https://api.cliqhub.io
        published:
          type: boolean
          description: '`true` when CliqHub accepted the package; `false` on a dry run.'
          example: true
        unregistered_agents:
          type: array
          items:
            type: string
          description: >
            Agents the manifest uses that are not registered in your CliqHub
            org. Present

            only when there are some. The publish still succeeded, but runs will
            fail

            until the agents are registered (`cliq agent register`).
          example:
            - jira-sync
    ErrorReply:
      type: object
      description: >-
        Every failure. Switch on `error.code` — it is stable; `message` is for
        people and may change.
      required:
        - ok
        - error
      properties:
        ok:
          type: boolean
          const: false
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Stable error code. See [Errors](/daemon-api/errors).
              example: TEAM_NOT_FOUND
            message:
              type: string
              description: What went wrong and, where possible, what to do.
              example: Team 'acme/code-review' not found
            details:
              description: >-
                Structured detail when there is some: the list of schema issues
                for `PAYLOAD_INVALID`, the agent problems for
                `TEAM_AGENT_CONFIG_REQUIRED`, …
  securitySchemes:
    DaemonBearer:
      type: http
      scheme: bearer
      description: >-
        Not needed from the same machine. From another host: a dispatch JWT
        CliqHub signed for this daemon, or a `cliq_tok_…` personal token whose
        user is in the daemon's realm.

````

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