# kcmd CLI reference

> kcmd commands, init flags per source type, pull and push options including dry-run, force, validate-only, reference pull, and authentication via gcloud ADC.

- Repository: GoogleCloudPlatform/knowledge-catalog
- GitHub: https://github.com/GoogleCloudPlatform/knowledge-catalog
- Human docs: https://grok-wiki.com/public/docs/googlecloudplatform-knowledge-catalog-9cee6ee3cba5
- Complete Markdown: https://grok-wiki.com/public/docs/googlecloudplatform-knowledge-catalog-9cee6ee3cba5/llms-full.txt

## Source Files

- `agents/mdcode/src/tool/main.ts`
- `agents/mdcode/src/tool/commands.ts`
- `agents/mdcode/README.md`
- `toolbox/mdcode/src/tool/main.ts`
- `toolbox/mdcode/src/tool/commands.ts`
- `agents/mdcode/src/libts/gcp/context.ts`

---

---
title: "kcmd CLI reference"
description: "kcmd commands, init flags per source type, pull and push options including dry-run, force, validate-only, reference pull, and authentication via gcloud ADC."
---

`kcmd` is the Metadata as Code CLI in `agents/mdcode`. It initializes a workspace (`catalog.yaml` plus a `catalog/` tree), syncs Knowledge Catalog (Dataplex) metadata with `pull` and `push`, fetches read-only reference layers with `reference`, and exposes an MCP server for agent workflows. All catalog API calls authenticate through gcloud Application Default Credentials (ADC).

<Info>
The published npm package name is `kcmd` (version `0.1.0`). The compiled binary reports CLI version `1.0.0`. Build from source with `npm run build` in `agents/mdcode`, or run via `npx kcmd`.
</Info>

## Command summary

| Command | Purpose | Key flags |
| --- | --- | --- |
| `kcmd init` | Create `catalog.yaml` for a source scope | Source-type flags (exactly one required), `--pull` |
| `kcmd pull` | Download editable metadata into `catalog/` | `--dry-run` |
| `kcmd push` | Publish local edits to the catalog service | `--dry-run`, `--force`, `--validate-only` |
| `kcmd reference` | Pull read-only `.ref.yaml` reference layers | None |
| `kcmd mcp` | Start the MCP server over stdio | `--path` |

`pull`, `push`, and `reference` require a workspace root containing `catalog.yaml`. Command handlers resolve the snapshot from the current working directory (`.`).

## Authentication

`kcmd` does not accept API keys on the command line. `ApiContext.default()` shells out to gcloud for project, region, and token:

```bash
gcloud auth application-default login
gcloud config set project YOUR_PROJECT_ID
gcloud config set compute/region YOUR_REGION
```

On HTTP 401 responses, the API client refreshes the ADC token and retries once. If project, region, or token cannot be resolved, initialization fails with:

`Unable to retrieve project, location, or token. Ensure gcloud is configured.`

Set `GCP_LOG` to any truthy value to enable request/response debug logging.

## `kcmd init`

Creates `catalog.yaml` in the current directory and prints the manifest to stdout. Provide **exactly one** primary source flag. An optional `--pull` runs `kcmd pull` immediately after initialization.

### Source types and ID formats

| Source type | Flag | ID format | Local layout |
| --- | --- | --- | --- |
| BigQuery dataset | `--bigquery-dataset` | `projectId.datasetId` | YAML (`.yaml`) |
| Knowledge base | `--kb` | `projectId.locationId.entryGroupId` | Markdown (`.md`) |
| Entry group | `--entry-group` | `projectId.locationId.entryGroupId` | YAML |
| BigLake Iceberg namespace | `--biglake-namespace` + `--iceberg` | `projectId.catalogId.namespaceId` | YAML |
| Business glossary | `--glossary` | See glossary formats below | YAML under `catalog/glossaries/` |

<ParamField body="--entry-group" type="string">
Dataplex EntryGroup identifier as `project.location.id`. The entry group may not exist yet; init succeeds and the group can be created on a later `push`.
</ParamField>

<ParamField body="--bigquery-dataset" type="string[]">
One or more BigQuery datasets as `project.datasetId`. Repeat the flag for multiple datasets (`--bigquery-dataset ds1 --bigquery-dataset ds2`). Each dataset must exist in BigQuery before init.
</ParamField>

<ParamField body="--kb" type="string">
Knowledge Base EntryGroup as `project.location.id`. Selects the Markdown layout for human-authored wiki content.
</ParamField>

<ParamField body="--biglake-namespace" type="string">
BigLake namespace as `project.catalogId.namespaceId`. Must be paired with `--iceberg`; non-Iceberg metastores are rejected.
</ParamField>

<ParamField body="--iceberg" type="boolean">
Required when using `--biglake-namespace`. Without it, init exits with an error.
</ParamField>

<ParamField body="--glossary" type="string">
Glossary scope in one of these forms:
- **Single glossary by ID**: `project.location.glossary-id`
- **Multiple glossaries**: `project.location.glossary-a,glossary-b` (comma-separated)
- **By display name**: `project.location.My Business Glossary` (falls back from ID lookup)
- **Location mode** (all glossaries in a location): `project.location`
</ParamField>

<ParamField body="--pull" type="boolean">
After writing `catalog.yaml`, immediately run `kcmd pull` to populate `catalog/`.
</ParamField>

<RequestExample>

```bash title="BigQuery workspace"
kcmd init --bigquery-dataset my-project.my_dataset --pull
```

```bash title="Knowledge base (Markdown layout)"
kcmd init --kb my-project.us-central1.my-kb-id
```

```bash title="BigLake Iceberg namespace"
kcmd init --biglake-namespace my-project.my-catalog.my-namespace --iceberg
```

```bash title="Glossary (location mode)"
kcmd init --glossary my-project.us-central1
```

</RequestExample>

If no source flag is provided, init prints an error and exits with code `1`.

## `kcmd pull`

Lists resources in the manifest `scope`, fetches matching entries and configured aspects from the Dataplex Catalog API, and writes them under `catalog/`. When `snapshot.entryLinks` is declared in `catalog.yaml`, `pull` also calls `lookupEntryLinks` and inlines links into entry YAML (column-level links under `aspects.schema.fields[].links`).

<ParamField body="--dry-run" type="boolean">
List resources that would be pulled without writing local files. Each candidate is logged as `[DRY-RUN] Pull Resource: <resource-name>`.
</ParamField>

<ResponseExample>

```text title="Successful pull"
Pulling catalog entries...
Successfully updated local snapshot.
```

</ResponseExample>

Entries the service returns as missing or inaccessible (non-200 `lookupEntry`) are skipped silently during pull.

## `kcmd push`

Reads modifiable local entries (files with a non-`.ref.yaml` path), compares them to remote state, and applies creates, updates, and EntryLink reconciliation. Files ending in `.ref.yaml` are never pushed.

Push behavior highlights:

- **Auto-provision entries**: Missing entries trigger `createEntry`; missing parent entry groups trigger `createEntryGroup`.
- **Glossary hierarchy**: `kcmd` does **not** create `Glossary`, `GlossaryCategory`, or `GlossaryTerm` resources. Missing glossary nodes fail fast. Existing glossary resources can have descriptions and labels updated.
- **EntryLink reconciliation**: When `publishing.entryLinks` is set, push compares local and remote links (project ID/number normalized, `@dataplex` proxy unwrapped), deletes remote-only links, and creates local-only links.

<ParamField body="--dry-run" type="boolean">
Simulate push mutations without calling the catalog API. Logs planned creates, modifies, deletes, and EntryLink operations prefixed with `[DRY-RUN]`.
</ParamField>

<ParamField body="--force" type="boolean">
Documented intent: overwrite service metadata, ignoring conflicts. **Not yet wired** in `CatalogSync.push`; passing this flag currently has no effect on sync behavior.
</ParamField>

<ParamField body="--validate-only" type="boolean">
Documented intent: validate the local snapshot against the service without publishing. **Not yet wired** in `CatalogSync.push`; passing this flag currently has no effect on sync behavior.
</ParamField>

<Warning>
Use `--dry-run` to preview push side effects today. `--force` and `--validate-only` are exposed on the CLI but are not implemented in the sync engine yet (`CatalogSync.validate()` and `CatalogSync.status()` are also unimplemented). A planned `kcmd status` command is described in design docs but is not registered in the current CLI.
</Warning>

<RequestExample>

```bash title="Preview push changes"
kcmd push --dry-run
```

```bash title="Publish local edits"
kcmd push
```

</RequestExample>

## `kcmd reference`

Pulls read-only metadata defined in the manifest `reference:` block into sibling `*.ref.yaml` files. Requires `reference.scope` and optional `reference.snapshot` (entries, aspects, entryLinks) in `catalog.yaml`. When `reference.snapshot.entryLinks` is set, reference pull includes pre-edit link state so diffs against enriched `.yaml` files surface only your changes.

Reference files are indexed separately from editable files and are excluded from `push` via `isModifiable()`.

<Steps>
<Step title="Configure reference in catalog.yaml">
Add a `reference:` block with `scope` and `snapshot` matching the grounding metadata you need (for example, authoritative schemas).
</Step>
<Step title="Run reference pull">
From the workspace root, run `kcmd reference`.
</Step>
<Step title="Verify output">
Confirm `*.ref.yaml` siblings appear next to editable entry files under `catalog/`.
</Step>
</Steps>

## `kcmd mcp`

Starts an MCP server on stdio bound to a workspace path. Tools: `list-entries`, `lookup-entry`, and `modify-entry` (local snapshot updates only; does not call `push`).

<ParamField body="--path" type="string" default=".">
Absolute or relative path to the workspace root containing `catalog.yaml`. Defaults to the current directory when omitted in code, but agent configs typically pass an absolute path.
</ParamField>

<CodeGroup>

```json title="Gemini CLI / MCP client config"
{
  "mcpServers": {
    "kcmd": {
      "command": "npx",
      "args": ["-y", "kcmd", "mcp", "--path", "/absolute/path/to/workspace"]
    }
  }
}
```

```bash title="Local binary"
kcmd mcp --path /path/to/workspace
```

</CodeGroup>

## Exit codes and errors

| Code | Meaning |
| --- | --- |
| `0` | Command succeeded |
| `1` | Command failed (validation error, sync failure, missing manifest, unknown subcommand) |

Sync failures print `Error pulling/pushing catalog entries:` or `Error pulling reference entries:` followed by `result.details`. Uncaught exceptions print `Error: <message>`.

## Workspace layout

After `init` and `pull`, a typical BigQuery workspace looks like:

:::files
/
├── catalog.yaml          # Manifest: scope, snapshot, publishing, reference
└── catalog/
    └── bigquery/
        └── project-id/
            └── dataset-id/
                ├── table.yaml
                └── table.ref.yaml   # From kcmd reference (read-only)
:::

Knowledge Base workspaces use `.md` files with YAML frontmatter instead of standalone `.yaml` entry files. See the manifest and layout pages for full `catalog.yaml` field reference.

## Related pages

<CardGroup>
<Card title="Installation" href="/installation">
Prerequisites, package install, and gcloud ADC setup.
</Card>
<Card title="Sync catalog metadata" href="/sync-catalog-metadata">
End-to-end init, pull, status check, and push workflow by source type.
</Card>
<Card title="catalog.yaml manifest reference" href="/catalog-manifest-reference">
`scope`, `snapshot`, `publishing`, `reference`, and entry link configuration.
</Card>
<Card title="kcmd MCP server reference" href="/kcmd-mcp-reference">
MCP tool schemas, workspace binding, and agent integration patterns.
</Card>
<Card title="Troubleshooting" href="/troubleshooting">
Auth failures, push conflicts, and glossary provisioning errors.
</Card>
</CardGroup>
