# Admin API

> Authenticated endpoints that edit the site's content through validated git commits.

All admin endpoints need `Authorization: Bearer <admin token>` (Jenks keeps it in the macOS Keychain as `agent-env:JENKSGUO_ADMIN_TOKEN`; tools read env `JENKSGUO_ADMIN_TOKEN`).
Writes are validated with the same schema as the build, then committed to GitHub. CI translates changed entries into every language, rebuilds and deploys: `main` → jenksguo.xyz, `dev` → dev.jenksguo.xyz.

| Method | Path | Tool |
| --- | --- | --- |
| GET | `/api/admin/whoami` | — |
| POST | `/api/admin/login` · `/api/admin/logout` | — (console session cookie) |
| GET | `/api/admin/schema` | `admin_schema` |
| GET | `/api/admin/files` | `admin_list_files` |
| GET | `/api/admin/file` | `admin_read_file` |
| POST | `/api/admin/validate` | `admin_validate` |
| PUT | `/api/admin/file` | `admin_write_file` |
| DELETE | `/api/admin/file` | `admin_delete_file` |
| POST | `/api/admin/changes` | `admin_commit_changes` |
| POST | `/api/admin/ai-edit` | `admin_ai_edit` |
| GET | `/api/admin/deploys` | `admin_deploy_status` |
| POST | `/api/admin/promote` | `admin_promote` |

Errors: `401 unauthorized`, `403 forbidden_path` (only content files are writable), `422 invalid` with `errors[]`, `409/502 github_error`, `503 github_not_configured`.

## `admin_schema` — Content schema

The content model: entry fields and rules, tags, lenses, kinds, writable paths, documents, and editing conventions. Read this before writing.

- **MCP:** `admin_schema` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `GET /api/admin/schema` (admin token)
- **CLI:** `jenks admin schema`

_No arguments._

```bash
curl -s "https://jenksguo.xyz/api/admin/schema" \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN"
```

## `admin_list_files` — List content files

List editable content files on a branch (path, size, sha), optionally inside one folder such as content/corpus/experiences.

- **MCP:** `admin_list_files` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `GET /api/admin/files?dir=&branch=` (admin token)
- **CLI:** `jenks admin ls [dir]`

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `dir` | string | no | e.g. content/corpus/projects (default: all content) |
| `branch` | `main` · `dev` | no | main publishes to jenksguo.xyz; dev previews on dev.jenksguo.xyz (default main). |

```bash
curl -s "https://jenksguo.xyz/api/admin/files" \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN"
```

## `admin_read_file` — Read a content file

Read the raw Markdown/JSON source of a content file (with its sha). Pass `path`, or `slug` for an entry, lens or skill.

- **MCP:** `admin_read_file` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `GET /api/admin/file?path=&slug=&branch=` (admin token)
- **CLI:** `jenks admin get <slug|path>`

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `path` | string | no |  |
| `slug` | string | no |  |
| `branch` | `main` · `dev` | no | main publishes to jenksguo.xyz; dev previews on dev.jenksguo.xyz (default main). |

```bash
curl -s "https://jenksguo.xyz/api/admin/file" \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN"
```

## `admin_validate` — Validate a change

Validate file content against the content schema without committing. Returns a list of problems (empty = valid).

- **MCP:** `admin_validate` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `POST /api/admin/validate` (admin token)
- **CLI:** `jenks admin validate <path> <file>`

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `path` | string | yes |  |
| `content` | string | yes |  |

```bash
curl -s -X POST https://jenksguo.xyz/api/admin/validate \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"path":"content/corpus/projects/example.md","content":"<content>"}'
```

## `admin_write_file` — Create or update a content file

Validate and commit one content file (create or replace). Publishing is automatic: CI re-translates changed entries into all languages, rebuilds and deploys (main → jenksguo.xyz, dev → dev.jenksguo.xyz) in a few minutes.

- **MCP:** `admin_write_file` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `PUT /api/admin/file` (admin token)
- **CLI:** `jenks admin put <path> <file> -m <message>`

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `path` | string | yes |  |
| `content` | string | yes |  |
| `message` | string | yes | Commit message |
| `branch` | `main` · `dev` | no | main publishes to jenksguo.xyz; dev previews on dev.jenksguo.xyz (default main). |

```bash
curl -s -X PUT https://jenksguo.xyz/api/admin/file \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"path":"content/corpus/projects/example.md","content":"<content>","message":"<message>"}'
```

## `admin_delete_file` — Delete a content file

Delete one content file (e.g. remove an entry) with a commit message. Git history keeps it recoverable.

- **MCP:** `admin_delete_file` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `DELETE /api/admin/file?path=&message=&branch=` (admin token)
- **CLI:** `jenks admin rm <path> -m <message>`

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `path` | string | yes |  |
| `message` | string | yes |  |
| `branch` | `main` · `dev` | no | main publishes to jenksguo.xyz; dev previews on dev.jenksguo.xyz (default main). |

```bash
curl -s -X DELETE https://jenksguo.xyz/api/admin/file \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"path":"content/corpus/projects/example.md","message":"<message>"}'
```

## `admin_commit_changes` — Commit several files at once

Validate and commit several file changes as ONE commit. Each change is {path, content} or {path, delete: true}.

- **MCP:** `admin_commit_changes` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `POST /api/admin/changes` (admin token)
- **CLI:** `jenks admin commit <changes.json> -m <message>`

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `changes` | array | yes |  |
| `message` | string | yes |  |
| `branch` | `main` · `dev` | no | main publishes to jenksguo.xyz; dev previews on dev.jenksguo.xyz (default main). |

```bash
curl -s -X POST https://jenksguo.xyz/api/admin/changes \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"changes":"<changes>","message":"<message>"}'
```

## `admin_ai_edit` — Draft an edit with AI

Ask the site's model to rewrite one content file from a plain-English instruction. Returns the proposed content, a diff and validation problems. Does NOT commit — review, then call admin_write_file.

- **MCP:** `admin_ai_edit` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `POST /api/admin/ai-edit` (admin token)
- **CLI:** `jenks admin ai-edit <slug|path> "<instruction>" [--apply]`

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `path` | string | no |  |
| `slug` | string | no |  |
| `instruction` | string | yes |  |
| `branch` | `main` · `dev` | no | main publishes to jenksguo.xyz; dev previews on dev.jenksguo.xyz (default main). |
| `content` | string | no | Optional unsaved file text to draft from (default: the saved file). |

```bash
curl -s -X POST https://jenksguo.xyz/api/admin/ai-edit \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"instruction":"<instruction>"}'
```

## `admin_deploy_status` — Deploy status

Recent CI runs (translate → build → deploy) with status, branch, commit and links.

- **MCP:** `admin_deploy_status` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `GET /api/admin/deploys?branch=` (admin token)
- **CLI:** `jenks admin deploys`

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `branch` | `main` · `dev` | no | main publishes to jenksguo.xyz; dev previews on dev.jenksguo.xyz (default main). |

```bash
curl -s "https://jenksguo.xyz/api/admin/deploys" \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN"
```

## `admin_promote` — Promote dev to production

Merge the dev branch into main, publishing everything previewed on dev.jenksguo.xyz to jenksguo.xyz.

- **MCP:** `admin_promote` on `https://jenksguo.xyz/mcp/admin`
- **REST:** `POST /api/admin/promote` (admin token)
- **CLI:** `jenks admin promote`

| Argument | Type | Required | Notes |
| --- | --- | --- | --- |
| `message` | string | no |  |

```bash
curl -s -X POST https://jenksguo.xyz/api/admin/promote \
  -H "Authorization: Bearer $JENKSGUO_ADMIN_TOKEN" \
  -H 'content-type: application/json' \
  -d '{}'
```

