| name | publish-medium |
| description | Publish or cross-post to Medium via the medium-publisher CLI (Playwright). Use when the user asks to publish on Medium, cross-post from dev.to/TabNews, import a story URL, or run medium-publisher login/session-check/import/publish. |
| disable-model-invocation | true |
Publish to Medium
Uses @paladini/medium-publisher from the publish-agents repo — not harness-score or other product repos.
⚠️ Wrong directory = Missing script: "medium"
npm run medium only works inside publish-agents:
cd D:\code\publish-agents
npm run medium -- login
From any directory (Windows):
D:\code\publish-agents\scripts\medium.ps1 login
Or after npm link in packages/medium-publisher:
medium-publisher login
Set PUBLISH_AGENTS_ROOT=D:\code\publish-agents if the repo lives elsewhere.
Prerequisites
- Node.js 20+
- Repo at
D:\code\publish-agents (or PUBLISH_AGENTS_ROOT)
- Built once:
npm install && npm run build
- One-time login: see commands above
Login (reuse your Chrome/Edge session)
Default config uses system-profile — your real Chrome Default profile.
If already logged into Medium in Chrome:
- Close all Chrome windows.
medium-publisher login → press Enter when /me/stories loads.
If Chrome must stay open:
medium-publisher browser-start
medium-publisher login --browser cdp
Isolated Playwright Chromium (no profile):
medium-publisher login --browser bundled
Config: %APPDATA%\medium-publisher\config.json — copy from packages/medium-publisher/config.example.json.
Workflow (cross-post — preferred)
- Confirm source URL is public (dev.to or TabNews).
- Session check:
npm run medium -- session-check
- Dry-run import (creates draft + extract, no publish):
npm run medium -- import --url "https://dev.to/..." --dry-run --json
- Import draft:
npm run medium -- import --url "https://dev.to/..." --json
-
Review formatting — follow skills/review-medium-import/SKILL.md (compare DEV.to markdown, fix code blocks/headings via fix-draft).
-
Publish only when user confirms:
npm run medium -- import --url "https://dev.to/..." --publish --json
- Record returned
medium_url in the announcement markdown frontmatter (medium_url:).
Workflow (local markdown — fallback)
When no public URL exists:
npm run medium -- publish --title "..." --body-file ./post.md --dry-run
npm run medium -- publish --title "..." --body-file ./post.md --publish --json
When session fails (exit 3)
Tell the user to run interactive login — do not store passwords in repo files:
npm run medium -- login
Style / content
For tone and structure, consult mcp-me (ask_about_me) before writing. After DEV.to import, run review-medium-import or use publish-devto-to-medium for the full pipeline. See docs/devto-to-medium.md.
Do not
- Commit
storageState.json or .env with credentials
- Gate CI on Medium publish (flaky browser)
- Use Playwright when TabNews API CLI exists (future
tabnews-publisher)
Troubleshooting
See TROUBLESHOOTING.md.