# Fizzy

> Operate a self-hosted Fizzy kanban board via fizzy-cli. Use when creating cards or migrating Jira issues to Fizzy.

- **Type:** Skill
- **Install:** `agentstack add skill-cskwork-fizzy-skill-fizzy`
- **Verified:** Pending review
- **Seller:** [cskwork](https://agentstack.voostack.com/s/cskwork)
- **Installs:** 0
- **Category:** [Productivity](https://agentstack.voostack.com/c/productivity)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [cskwork](https://github.com/cskwork)
- **Source:** https://github.com/cskwork/fizzy-skill/tree/main/skills/fizzy
- **Website:** https://cskwork.github.io/fizzy-skill/

## Install

```sh
agentstack add skill-cskwork-fizzy-skill-fizzy
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# fizzy

Operate `tobiasbischoff/fizzy-cli` against a **self-hosted Fizzy instance**. Single skill covers:

1. **Onboarding** — install, base-URL, auth (PAT or magic-link), default account
2. **Daily ops** — board/card/comment CRUD with the markdown gotchas baked in
3. **Jira → Fizzy migration** — pull a Jira issue's description, attachments, and 14-comment thread into a card (+ sub-cards) without losing formatting

## Quick decision

```
Need to set up fizzy-cli from scratch?         → §1 Onboarding
Need to create/update cards or comments?       → §2 Daily ops
Need to import a Jira issue into Fizzy?        → §3 Jira → Fizzy migration
Markdown looks broken after posting to Fizzy?  → §4 Markdown quirks
```

## Inputs (env)

- `FIZZY_HOST` — base URL (e.g. `https://fizzy.example.com`)
- `FIZZY_EMAIL` — account email
- `FIZZY_TOKEN` (preferred) OR magic-link from inbox

For Jira import: `acli` must be authenticated to the source site (`acli auth status` → ✓).

---

## §1 Onboarding

### 1.1 Install

Homebrew (documented):
```bash
brew install tobiasbischoff/tap/fizzy-cli
```

If brew is blocked, build from source:
```bash
git clone https://github.com/tobiasbischoff/fizzy-cli.git ~/.local/src/fizzy-cli
cd ~/.local/src/fizzy-cli && go build -o ~/.local/bin/fizzy-cli ./cmd/fizzy-cli
```

> **Pitfall — `go install` does NOT work.** `go.mod` declares `module fizzy-cli` (short form), so `go install github.com/...` fails. Always clone + `go build -o`.

### 1.2 Point at the host
```bash
fizzy-cli config set --base-url "$FIZZY_HOST"
fizzy-cli config show
```
Config: macOS `~/Library/Application Support/fizzy/config.json`, Linux `~/.config/fizzy/config.json`.

### 1.3 Authenticate

**A. PAT (preferred, idempotent):**
```bash
fizzy-cli auth login --token "$FIZZY_TOKEN"
fizzy-cli auth status   # → "Authenticated using token."
```

**B. Magic-link in non-TTY (Claude Code / CI):**
> `fizzy-cli auth login --email --code` is broken in non-TTY — each call re-issues a code, invalidating any pasted one. Workaround: see `references/magic-link-curl-two-step.md`.

### 1.4 Pick default account
```bash
fizzy-cli account list
fizzy-cli account set     # required even with only one account
```

> **Pitfall — single-account auto-select is NOT done by the CLI.** Skipping this makes `board list` etc. error cryptically.

### 1.5 Verify
```bash
fizzy-cli board list
fizzy-cli card create --board-id  --title "fizzy setup test" --description "ok" --status published
fizzy-cli card list --board-id  | head -3
```

---

## §2 Daily ops

| Goal                 | Command |
|----------------------|---------|
| List boards          | `fizzy-cli board list` |
| List cards           | `fizzy-cli card list --board-id ` |
| Get card             | `fizzy-cli card get ` |
| Create card          | `fizzy-cli card create --board-id  --title T --description D --status published` |
| Update card          | `fizzy-cli card update  --description D` |
| Attach main image    | `fizzy-cli card update  --image ` (one image per card) |
| List comments (JSON) | `fizzy-cli --json comment list ` |
| Add comment          | `fizzy-cli comment create  --body "text"` |
| Delete comment       | `fizzy-cli comment delete  ` |

> `--json` is a **global** flag — it must come before the subcommand (`fizzy-cli --json comment list 36`), not after.

### Filter user-only comments

```bash
fizzy-cli --json comment list  \
  | jq -r '.[] | select(.creator.name != null) | .id'
```
(Status-change comments have `creator: {name: "System"}`, sort of — filter on a known username instead.)

### Card description / comment body — markdown rules

Fizzy renders **CommonMark** strictly: single `\n` is collapsed; only blank lines start a new paragraph. See §4.

---

## §3 Jira → Fizzy migration

End-to-end migrator: pulls issue + comments via Atlassian MCP, converts ADF → Fizzy-friendly markdown, creates parent card + optional sub-cards, posts every comment, retries on timeout.

```bash
# Prereq: Fizzy authenticated (§1), Atlassian MCP available, acli logged in
python3 ~/.claude/skills/fizzy/scripts/jira_to_fizzy.py \
  --issue PROJ-123 \
  --board  \
  --site your-site.atlassian.net \
  --split-numbered   # auto-create sub-cards from "1.", "2.", "3." in description
```

What it does (see `scripts/jira_to_fizzy.py` for the full flow):
1. Fetches the issue + comments JSON via `mcp__claude_ai_Atlassian__getJiraIssue` (or reads a cached JSON file with `--from-json PATH`).
2. Converts every ADF body to Fizzy-friendly markdown via `scripts/adf_to_md.py`.
3. Creates the parent card (compact summary + Jira URL + link to attachments).
4. If `--split-numbered`, creates one sub-card per top-level numbered item in the description.
5. Posts every Jira comment as `**[YYYY-MM-DD] author**\n\n`.
6. Retries each fizzy-cli call up to 3× on `context deadline exceeded`.

**Attachment handling (images):** Atlassian's `acli` OAuth scope lacks `read:attachment-content:jira`, so URL-based downloads return 401. Use a user-issued **Personal Access Token (PAT)** with Basic auth (`scripts/atlassian_attachments.py`).

Setup once:
1. Issue a PAT at `https://id.atlassian.com/manage-profile/security/api-tokens`
2. Save to `~/.config/fizzy/.env` (chmod 600):
   ```
   ATLASSIAN_EMAIL=you@example.com
   ATLASSIAN_PAT=ATATT3...
   ATLASSIAN_SITE=your-site.atlassian.net
   ```

Download + attach:
```bash
# Download every attachment to /tmp/fizzy-attachments/
python3 ~/.claude/skills/fizzy/scripts/atlassian_attachments.py \
    download-issue --from-json /tmp/issue.json

# Then attach a representative image as the card's main image (one per card)
fizzy-cli card update  --image /tmp/fizzy-attachments/_.png
```

Note: Fizzy strips `` from description bodies, so embed-in-description is impossible — only the card's main image slot works (one image per card).

**Idempotency:** to re-run cleanly, first wipe stale user comments:
```bash
python3 ~/.claude/skills/fizzy/scripts/jira_to_fizzy.py --card  --wipe-user-comments 
```

---

## §4 Rendering — Fizzy accepts HTML, NOT markdown

> **CRITICAL discovery (2026-05-21):** Fizzy server takes the body as HTML and auto-converts it to a Fizzy-rendered string. Markdown is NOT parsed — `**bold**` appears as literal asterisks. **Send hybrid HTML** for the best result.

### What Fizzy auto-renders well (use these tags)

| Tag | Result in UI |
|---|---|
| `...` | paragraph with blank-line separation |
| `X` | `• X` (auto bullet) |
| `X` | `1. X` (auto numbering) |
| nested `` inside `` | `  • X` (auto 2-space indent) |
| `X` | `“X”` (auto curly quotes) |
| `` | line break inside paragraph |

### What Fizzy STRIPS (encode in text yourself)

| Tag | Fizzy behavior | Workaround |
|---|---|---|
| ``…`` | shown as plain text, no marker | wrap: `▶ title` (use emoji prefix as marker) |
| `` / `` | stripped | use emoji or `「 」` symbols if emphasis matters |
| `` | disappears | emit `━━━━━━━━━━━━━━━━━━━━` |
| `label` | text only, **URL is gone** | emit `label: X` or `🔗 X` |
| `` | disappears | emit `이미지: ` (no emoji) |
| ``/`` | stripped | emit `코드:…---` |
| `` | all cells concatenated, no structure | emit rows as `\| a \| b \|` |

### Other quirks

| Quirk | Symptom | Fix |
|---|---|---|
| `comment list` silent pagination | Only ~3 items per call; the rest are invisible | Loop list+delete until empty when wiping; never assume `length == total` |
| Bash heredoc + `(` / backtick | `unexpected EOF` or `command not found` | Build bodies in Python with `subprocess.run([cmd, '--description', text])` |
| `--json` after subcommand | Silently ignored | Place it **before** subcommand: `fizzy-cli --json comment list 36` |
| Single-account auto-default | `board list` errors after fresh auth | Run `fizzy-cli account set ` even with one account |
| `--image PATH` | Local file path only, one main image per card | Download first; extras → inline URLs in description |

## Recommended layout for migrated cards

> **POLICY — No emoji in deliverables.** Cards, comments, reports are business artifacts.
> Use bracket labels (`[목적]`, `[상세 작업]`) and box-drawing rules (`━`, `·`) only.
> No pictographic emoji (📌 🎯 ✅ 📎 etc.). Geometric arrows (▶ ▸ ■) are also discouraged
> because some clients render them with emoji presentation.

```html
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[KEY] 제목 영역
프로젝트: MyProject  ·  타입: Bug  ·  상태: 진행 중  ·  담당: 홍길동
Jira: https://...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[개요]
본문 단락 1
핵심 1핵심 2
[첨부 (로그인 필요)]
오류 화면: https://...
```

This is what `scripts/adf_to_fizzy.py` + `header_block()` / `section()` produce automatically.

## Common mistakes

- **Sending markdown and hoping it renders** — Fizzy treats `**X**` as literal text. Use HTML or wrap content with `adf_to_fizzy`.
- **Trusting `comment list` length** — it's page 1 (~3 items) only. Loop until empty when wiping.
- **Filtering by `creator.name != "System"`** — some events have empty `creator.name`. Match on a specific username.
- **Posting via `bash -c` with `--description "...\`x\`..."`** — backticks trigger command substitution. Always use Python `subprocess.run([...])`.
- **`` for important URLs** — Fizzy strips the href. Always print the URL as visible text.
- **`` for important tabular data** — cells get concatenated with no separator. Build the table yourself with `| a | b |` rows.

## Files

- `scripts/adf_to_fizzy.py` — **(recommended)** ADF → Fizzy hybrid HTML with auto-renderable tags + text fallbacks for stripped ones. Provides `adf_to_fizzy()`, `header_block()`, `section()`, `HR`.
- `scripts/adf_to_plain.py` — ADF → pure plain text (use only when you specifically want to avoid HTML).
- `scripts/adf_to_md.py` — ADF → markdown (for non-Fizzy targets; do NOT send to Fizzy).
- `scripts/jira_to_fizzy.py` — end-to-end Jira issue → Fizzy card(s) migrator with retry + pagination-safe wipe, using hybrid HTML.
- `references/magic-link-curl-two-step.md` — non-TTY magic-link workaround.
- `references/operations.md` — extended fizzy-cli command reference.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [cskwork](https://github.com/cskwork)
- **Source:** [cskwork/fizzy-skill](https://github.com/cskwork/fizzy-skill)
- **License:** MIT
- **Homepage:** https://cskwork.github.io/fizzy-skill/

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-cskwork-fizzy-skill-fizzy
- Seller: https://agentstack.voostack.com/s/cskwork
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
