medium について
ユーザーの Cookie を使って Medium の記事を読み書きするコマンドラインスキルです。ブラウザーや外部依存なしで Medium の内部 Web API を利用し、公開操作には確認を求めます。
主な機能
- 01アカウント情報の確認
- 02記事と反応数の一覧表示
- 03記事詳細の確認
- 04Markdownを下書きまたは公開記事として投稿
- 05Markdown形式をMedium向けに変換
活用シーン
- 01公開済み記事と反応数の確認
- 02Mediumの下書き作成
- 03承認済み記事の公開
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ acedatacloud/ skills --skill mediumインストール後、Claude Code で/mediumを入力して読み込まれたか確認します。
同梱ファイルscripts/medium.py
詳細
medium — 自分の Cookie を使って Medium で読んだり公開したりできます
Medium が 2023 年に公開書き込み API を廃止したため、サイトと同じ内部 Web API を使って、ユーザーの実際の Medium アカウントを操作します。ACE 拡張機能で取得したログイン Cookie を使って認証します。ブラウザーやサードパーティ製の依存関係はなく、urllib のみを使用します。
コネクターは Cookie jar を環境変数として渡します。
MEDIUM_COOKIES— Cookie(sid、uid、xsrf)の JSON 配列です。秘密情報です。絶対にエコーしたり、出力したりしないでください。 CLI は書き込み時にxsrfCookie をx-xsrf-tokenヘッダーとして自動的にエコーします。取得した jar にxsrfCookie がない場合(よくあります)、CLI は書き込み前に自動で作成するため、「Missing xsrf token」による公開エラーは発生しなくなります。
CLI
このスキルには、標準ライブラリのみで動作する単独の scripts/medium.py が含まれています。
# $SKILL_DIR can point at another skill loaded this turn — anchor on our own
# script, and re-run this at the top of every Bash block (fresh shell each time).
MED="$SKILL_DIR/scripts/medium.py"; [ -f "$MED" ] || MED=$(find /tmp -maxdepth 8 -path '*/skills/*/scripts/medium.py' 2>/dev/null | head -1)
[ -f "$MED" ] || { echo "medium script not found (SKILL_DIR=$SKILL_DIR)" >&2; exit 1; }
python3 "$MED" whoami # who is logged in
python3 "$MED" articles --limit 20 # my posts + clap/response stats
python3 "$MED" article <post-id> # one post's details
まず接続を確認してください
MED="$SKILL_DIR/scripts/medium.py"; [ -f "$MED" ] || MED=$(find /tmp -maxdepth 8 -path '*/skills/*/scripts/medium.py' 2>/dev/null | head -1)
python3 "$MED" whoami
# → {"user_id": "...", "name": "...", "username": "..."}
認証エラーが発生した場合、Cookie の有効期限が切れています。ユーザーに https://studio.acedata.cloud/console/connectors で再接続してもらってください。再試行を繰り返してはいけません。
公開 — 要確認(末尾に --confirm がない場合はドライラン)
publish はユーザーの実際のアカウントに書き込みます。コンテンツは Markdown 形式で、Medium の段落ブロックに変換されます(#/##→見出し、###→小見出し、>→引用、
```→code, -/*→bullet list, 1.→numbered list, tables→aligned
code block). Inline bold, italic, code, and [links](url) render as
real Medium formatting (clickable links included). Bare https://… URLs in text
are auto-linked too (URLs inside code spans are left untouched).
Without a trailing --confirm it dry-runs. --confirm is honored only as the
last argument. Always show the dry-run, get an explicit "yes", then re-run.
MED="$SKILL_DIR/scripts/medium.py"; [ -f "$MED" ] || MED=$(find /tmp -maxdepth 8 -path '*/skills/*/scripts/medium.py' 2>/dev/null | head -1)
python3 "$MED" publish --title "Title" --content-file a.md # dry-run
python3 "$MED" publish --title "Title" --content-file a.md --draft-only --confirm # private draft
python3 "$MED" publish --title "Title" --content-file a.md --confirm # PUBLIC story
Publishing is Medium's multi-step editor flow (new-story → write deltas →
publish). --draft-only stops at the draft (visible only at the user's
/me/stories/drafts). Default to --draft-only unless the user asked to go live.
Images
publish automatically uploads each external markdown image () to
Medium and inserts it as a real image block — Medium has no markdown-image
syntax, so this is the only way images render. Pass --no-rehost-images to
degrade images to link-only paragraphs. An image that fails to upload falls back
to a link paragraph (never blocks the post).
Gotchas
- This is the user's real Medium account. Confirm before any publish.
- Markdown→Medium conversion covers headings, quotes, fenced code, bullet/
numbered lists, images, and inline markups (bold/italic/code/links). Medium's
editor has no table element: a narrow markdown table renders as an aligned
monospace code block, while a wide one (long cells / URLs, which would wrap into
an unreadable grid) is rendered as per-row records — the first column bolded as
a lead-in, the remaining columns as
header: valuebullets. - Medium sits behind Cloudflare; an occasional 403/429 is transient — the CLI auto-retries once after a short pause. A persistent 403 means the cookie is genuinely expired (reconnect).
- Never print
MEDIUM_COOKIES— it is full account access. - ToS: acts only on the user's own account with their own captured cookie.
Record the output
After you successfully publish and obtain the live result URL, call the built-in
publish_artifact tool ONCE so the user can track this deliverable in My Outputs:
publish_artifact(kind="article", channel="medium", title="<title>", url="<the REAL returned URL>", status="delivered")
Use the real returned URL — never fabricate one. Call it once per published item,
only after delivery is confirmed; skip it (or use status="failed") if publishing failed.
See _shared/artifacts.md.