# Youtrack

> Read and selectively write YouTrack issues, comments, attachments, activities, commands, projects, users, custom-field schema, and knowledge-base articles through a UTF-8 JSON REST CLI. Use for explicit YouTrack requests, including creating tickets and publishing or updating KB articles, with approval-first workflows.

- Skill: `bgevorkian/youtrack` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add bgevorkian/youtrack`
- Raw SKILL.md: https://api.skillmd.com/api/skills/bgevorkian/youtrack/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- License: MIT
- Author: bgevorkian (https://skillmd.com/u/bgevorkian)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/bgevorkian/youtrack

---


# YouTrack

Generic YouTrack REST JSON CLI with stdlib HTTP only. Reads cover the current user, projects, users, issues, comments, attachments, activity history, custom-field schema, and knowledge-base articles. Writes are intentionally gated.

For approval-first procedural guidance, read the matching reference before acting:

- issue creation: `references/create-issue.md`;
- Knowledge Base publication/update: `references/kb-article.md`.

## Local `.env`

The CLI automatically loads a private `.env` beside this `SKILL.md` through `pass-cli`. Copy `.env.example` to `.env`; never commit the real file.

A single `.env` may hold namespaced profiles. Select one explicitly:

```bash
uv run --python 3.13 python scripts/yt.py --profile work me
```

Without `--profile`, ordinary `YOUTRACK_*` variables are used.

## Configuration

| Variable | Required | Default |
|---|---:|---|
| `YOUTRACK_URL` | yes (or `--url`) | none |
| `YOUTRACK_TOKEN` | yes | none |
| `YOUTRACK_PROJECT` | no | used as default `--project` |
| `YOUTRACK_ALLOW_WRITE` | no | `false` |

Use a token with the minimum scope needed. Never print or paste the token.

## Secret setup

Before configuring credentials, ask which secret manager and local profile the user wants. Follow [Secure secret profiles](https://github.com/bgevorkian/agent-skills/blob/main/docs/secure-secrets.md). Do not invent or publish profile names, hosts, templates, or secret references. If the user asks for the author's method, use a per-profile Proton Pass pointer file with process-scoped `pass-cli run`. Never request or display resolved values.

## Run

From this skill directory:

```bash
uv run --python 3.13 python scripts/yt.py me
uv run --python 3.13 python scripts/yt.py projects --query Demo
uv run --python 3.13 python scripts/yt.py users --query alice
uv run --python 3.13 python scripts/yt.py issues --query "project: DEMO State: Open" --top 20
uv run --python 3.13 python scripts/yt.py issue DEMO-123
uv run --python 3.13 python scripts/yt.py comments DEMO-123
uv run --python 3.13 python scripts/yt.py fields --project DEMO
uv run --python 3.13 python scripts/yt.py articles --query "project: DEMO"
uv run --python 3.13 python scripts/yt.py article DEMO-A-1
```

Pass `--url https://youtrack.example.net` to override `YOUTRACK_URL` for one run. Global options such as `--profile`, `--url`, and `--confirm-write` go before the subcommand.

## Write gate

Every mutation requires both of these:

1. `YOUTRACK_ALLOW_WRITE=true`
2. explicit `--confirm-write`

Without both, create/update/comment/article mutations fail locally before any request is sent.

## Reads

| Command | Purpose |
|---|---|
| `me` | current user |
| `projects --query Q [--top N] [--skip N]` | list/search projects |
| `users --query Q [--top N] [--skip N]` | list/search users |
| `issues --query Q [--top N] [--skip N]` | issue search |
| `issue ID` | one issue |
| `comments ID [--top N] [--skip N]` | issue comments |
| `attachments ID [--top N] [--skip N]` | issue attachments |
| `activities ID [--top N] [--skip N]` | issue activity/changelog |
| `fields --project KEY [--top N] [--skip N]` | project custom-field schema |
| `articles --query Q [--top N] [--skip N]` | article search |
| `article ID` | one article with content |
| `article-attachments ID [--top N] [--skip N]` | article attachments |

`KEY` can be a project short name or internal id. Output is UTF-8 JSON.

## Controlled writes

```bash
YOUTRACK_ALLOW_WRITE=true \
uv run --python 3.13 python scripts/yt.py --confirm-write create \
  --project DEMO \
  --summary "Add generic YouTrack skill" \
  --description @body.md

YOUTRACK_ALLOW_WRITE=true \
uv run --python 3.13 python scripts/yt.py --confirm-write update DEMO-123 \
  --summary "Updated title"

YOUTRACK_ALLOW_WRITE=true \
uv run --python 3.13 python scripts/yt.py --confirm-write comment DEMO-123 \
  --text "Done."

YOUTRACK_ALLOW_WRITE=true \
uv run --python 3.13 python scripts/yt.py --confirm-write article-create \
  --project DEMO \
  --summary "Runbook" \
  --content @article.md

YOUTRACK_ALLOW_WRITE=true \
uv run --python 3.13 python scripts/yt.py --confirm-write article-update DEMO-A-1 \
  --content @article.md

YOUTRACK_ALLOW_WRITE=true \
uv run --python 3.13 python scripts/yt.py --confirm-write attach DEMO-123 screenshot.png

YOUTRACK_ALLOW_WRITE=true \
uv run --python 3.13 python scripts/yt.py --confirm-write command \
  --query "State Fixed" --issues DEMO-123
```

Additional controlled writes are `comment-update`, `comment-delete`, `article-attach`, and multi-issue `command`. Attachment uploads are bounded to 100 MiB combined per invocation.

`--description`, `--text`, `--content`, and `--custom-fields` accept a literal string, `@file`, or `-` for stdin.

## Field discovery and selectors

Before creating an issue, inspect the project schema instead of hardcoding internal field values:

```bash
uv run --python 3.13 python scripts/yt.py fields --project DEMO
uv run --python 3.13 python scripts/yt.py users --query alice
```

`create --custom-fields` and `update --custom-fields` accept either raw YouTrack `customFields` JSON or selector objects that resolve against the live schema and user search results. For selector-based updates, pass `--project` or set `YOUTRACK_PROJECT`.

Example selectors:

```json
[
  {"name": "Priority", "$byName": "Critical"},
  {"name": "Assignee", "$user": "alice"},
  {"name": "Tags", "$byNames": ["api", "docs"]}
]
```

The CLI converts these to REST payloads using project field schema and user lookup, so agents can discover valid options first and avoid hardcoded ids.

## Safety and behavior

- Uses Python stdlib `urllib`; no MCP and no third-party HTTP client.
- Uses UTF-8 JSON for stdin, files, stdout, and request bodies.
- Read commands support pagination with `--top` and `--skip`.
- Comment edits/deletes, attachment uploads, commands, and article attachment uploads use the same double gate as every other mutation.
- Helpful HTTP errors include status and server message when available.
- The token is read from `YOUTRACK_TOKEN` and is never printed.
- Keep `--top` bounded; the CLI rejects oversized page sizes.

## Tests

```bash
uv run --python 3.13 python tests/test_yt.py
```

