Markdown Converter
Agent skill for markdown-converter
> **Role:** Claude Code is the **primary implementer and orchestrator**. It plans, runs commands, generates patches, and opens PRs.
Sign in to like and favorite skills
Role: Claude Code is the primary implementer and orchestrator. It plans, runs commands, generates patches, and opens PRs.
Delegation: It may call secondary codegen tools (e.g., Gemini/Codex) for heavy lifting (large codegen, multi-file edits, scaffolding, refactors, bulk tests/fixtures), but Claude remains responsible for the final patches and PRs.
Source of truth: AGENTS.md (or
) defines scope. If anything conflicts, AGENTS.md wins.TASKS.mdRuntime: Execute inside WSL (Ubuntu) from the repo root. Shell = bash. Editor = VS Code (or Visual Studio with WSL integration).
feat/<short-kebab-slug>Work one task at a time. Do not begin the next task until the current PR is merged.
TODO(reason) and proceed..env (not committed).One task → one branch → one PR → merge → next task.
# Ensure local is current git checkout dev && git pull # Create feature branch git checkout -b feat/<short-kebab-slug>
# Detect stack & install # Python [ -f requirements.txt ] && pip install -r requirements.txt || true [ -f pyproject.toml ] && pip install -e . || true # Node [ -f package-lock.json ] && npm ci || true [ -f pnpm-lock.yaml ] && corepack enable && pnpm i --frozen-lockfile || true [ -f yarn.lock ] && yarn install --frozen-lockfile || true # Go / Rust / Java [ -f go.mod ] && go mod download || true [ -f Cargo.toml ] && cargo fetch || true [ -f pom.xml ] && mvn -q -DskipTests package || true [ -f build.gradle ] && ./gradlew -q assemble || true # Lint/format/tests (run what exists) [ -f .pre-commit-config.yaml ] && pre-commit run -a || true [ -f pyproject.toml ] && ruff check . || true [ -f pyproject.toml ] && black --check . || true [ -f pytest.ini ] && pytest -q || true [ -f package.json ] && npm test -s || true [ -f go.mod ] && go test ./... || true [ -f Cargo.toml ] && cargo test -q || true
git add -A # Conventional Commit style git commit -m "feat(<area>): short imperative summary"
git push -u origin HEAD # Open PR to `dev` with the template below
git checkout dev && git pull # prune local/remote branch git branch -d feat/<slug> && git push origin :feat/<slug>
Branch naming:
feat/<slug> for features, fix/<slug> for fixes, chore/<slug> for chores.
Protected branches: Protect
main (and usually dev); require CI pass (format/lint/test/build).
On failure:{ "ok": true, "data": <payload>, "error": null, "meta": {"version": "x.y.z"} }
{ "ok": false, "data": null, "error": {"code":"…","message":"…"} }.?sort=<field>&order=asc|desc and applies it. Client never sorts authoritative data locally.page, page_size, total fields. Exports ignore pagination and include all filtered rows..env (not committed) and/or CI secrets. No plaintext keys in code or tests.dev using the template below; include preflight logs and smoke outputs.TODO(<ticket or reason>) for scoped deferrals.HTTP API
curl -s "http://localhost:PORT/api/resource?sort=created_at" \ | jq '{ok, data: (.data[:2] // []), meta} ' curl -s "http://localhost:PORT/api/resource/export?format=csv" | head -n 5
CLI
./bin/tool list --sort created_at --format json | jq '{ok, count: (.data|length)}' ./bin/tool export --format csv | head -n 5
Claude detects the stack by repo markers and runs only what applies.
requirements.txt → pip install -r; pyproject.toml → pip install -e .; run ruff, black --check, pytest if present.npm ci/pnpm i --frozen-lockfile/yarn install --frozen-lockfile; run npm test if present.go mod download then go test ./....cargo fetch then cargo test.mvn -DskipTests package or ./gradlew assemble.docker-compose*.yml exists and service is required for tests, run docker compose up -d <service>./mnt/c).PLAN
Read AGENTS.md → CURRENT FOCUS. Output: 1) Task summary 2) Files to touch (≤5) 3) LOC estimate (≤300) 4) Risks and how to honor Contracts/Guardrails Do not exceed the current task.
IMPLEMENT
Generate a minimal patch for ONLY the current task. Rules: - ≤ ~300 LOC, ≤ 5 files - Keep I/O envelopes, sort, and export behavior EXACT - Prefer editing existing files; list any new files up front - Output UNIFIED DIFFs (```diff fenced). Include a short smoke test.
VERIFY
Provide smoke steps proving: - Envelope keys present and shaped correctly - Server-side sort honored (?sort=...) - Exports return full filtered dataset (not just current page)
PR
Open a PR to dev using the template. Attach preflight logs + smoke outputs.
RECOVER (on failure)
Stop work. Summarize failing preflight/tests, what was attempted, and minimal next step. Open PR with findings instead of guessing.
Task: N — files changed (≤ 5), ~LOC Why: 2–5 bullets
<lint/format/test logs>
<curl/jq outputs or CLI steps>
To prevent “hung” local runs without killing healthy work, wrap long‑running commands with a watchdog that stops the process if there’s no activity for a period, while allowing active servers to continue.
/healthz)A) Minimal wall‑clock guard (least smart):
# Kills after 20m; sends TERM then KILL after 10s # (Does not watch output/health; use only as a backstop.) timeout --preserve-status --signal=TERM --kill-after=10s 20m your-command
B) Full idle watchdog (recommended):
scripts/run_with_watchdog.py
#!/usr/bin/env python3 import argparse, os, signal, subprocess, sys, time, threading, queue, requests def enqueue(stream, q): for line in iter(stream.readline, b""): q.put(time.time()) sys.stdout.buffer.write(line) if stream is sys.stdin else sys.stderr.buffer.write(line) stream.close() def healthy(urls): ok=False for u in urls: try: r=requests.get(u, timeout=2) if r.status_code==200: ok=True except Exception: pass return ok def main(): ap=argparse.ArgumentParser() ap.add_argument('--idle-secs', type=int, default=int(os.getenv('IDLE_SECS', '240'))) ap.add_argument('--hard-timeout', type=int, default=int(os.getenv('HARD_TIMEOUT', '1800'))) ap.add_argument('--check-interval', type=int, default=5) ap.add_argument('--kill-after', type=int, default=10) ap.add_argument('--ready-regex', default=None) ap.add_argument('--http-check', action='append', default=[]) ap.add_argument('--heartbeat-file', default=None) ap.add_argument('cmd', nargs=argparse.REMAINDER, help='-- your command and args') args=ap.parse_args() if args.cmd and args.cmd[0]=='--': args.cmd=args.cmd[1:] if not args.cmd: print('need a command after --', file=sys.stderr); return 2 start=time.time(); last=time.time(); p=subprocess.Popen(args.cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid, bufsize=1, text=False) q=queue.Queue() t1=threading.Thread(target=enqueue, args=(p.stdout,q), daemon=True); t1.start() t2=threading.Thread(target=enqueue, args=(p.stderr,q), daemon=True); t2.start() while True: try: while True: last=q.get_nowait(); except queue.Empty: pass now=time.time() # Treat heartbeat file update as activity if args.heartbeat_file and os.path.exists(args.heartbeat_file): last=max(last, os.path.getmtime(args.heartbeat_file)) # Treat healthy HTTP check as activity if args.http_check and healthy(args.http_check): last=now # Hard timeout if now-start > args.hard_timeout: reason=f"hard-timeout>{args.hard_timeout}s" break # Idle timeout if now-last > args.idle_secs: reason=f"idle>{args.idle_secs}s" break if p.poll() is not None: return p.returncode time.sleep(args.check_interval) # Graceful termination of the whole process group try: os.killpg(p.pid, signal.SIGTERM) except ProcessLookupError: pass deadline=time.time()+args.kill_after while time.time()<deadline and p.poll() is None: time.sleep(0.2) if p.poll() is None: try: os.killpg(p.pid, signal.SIGKILL) except ProcessLookupError: pass print(f"[watchdog] stopped '{' '.join(args.cmd)}' due to {reason}", file=sys.stderr) return 124 if 'idle' in reason else 137 if __name__=='__main__': sys.exit(main())
Save as
andscripts/run_with_watchdog.pyin your dev venv. The script mirrors stdout/stderr, treats successful health checks as activity, and kills the process group to avoid orphans.pip install requests
Usage examples
# HTTP server with health check and idle cap env IDLE_SECS=300 HARD_TIMEOUT=3600 \ python3 scripts/run_with_watchdog.py --http-check http://localhost:3000/healthz -- \ npm run dev # CLI that prints intermittently; add a heartbeat file in your code touch tmp/.hb && \ python3 scripts/run_with_watchdog.py --idle-secs 180 --heartbeat-file tmp/.hb -- \ python -m mytool long-job # Docker compose, backstop only HARD_TIMEOUT=1800 timeout --preserve-status --signal=TERM --kill-after=15s 30m docker compose up
Makefile shim (optional)
.PHONY: dev DEV_CMD = npm run dev IDLE_SECS ?= 300 HARD_TIMEOUT ?= 3600 dev: python3 scripts/run_with_watchdog.py --http-check http://localhost:3000/healthz -- \ $(DEV_CMD)
App heartbeat helper (optional)
console.log('[hb]', Date.now()) or print('[hb]', flush=True).fs.utimes('tmp/.hb', new Date(), new Date()) or Path('tmp/.hb').touch().Claude Code usage
Applies to both Claude Code (CLI) and Codex (VS Code / CLI).
Assumes MCP servers,context7,chrome-devtools, andplaywrightare available.git
If a server is missing, degrade gracefully (explain what you would have done).
context7 — Deep Library Docs & ExamplesWhen to use
How to use
context7 with a very specific query:
“ffmpeg opus to wav 16k mono options”,“streamlit file uploader multiple files examples”.Prompt pattern
“Use the
MCP to fetch current docs forcontext7, focused on<library or CLI>.<feature>
Summarise the relevant options for this repo, choose one consistent configuration, and show the exact code/CLI you will implement.”
chrome-devtools / playwright — Seeing & Poking the FrontendWe have a UI for the WhatsApp pipeline (M5/M6). Don’t guess from code alone; look at the running app.
chrome-devtools — Inspecting DOM, CSS, ConsoleUse
chrome-devtools when you need:
Assume the app is running at the local dev URL (e.g.
http://localhost:8501 or whatever is configured).
Prompt pattern
“Assume the frontend is running at
.http://localhost:8501
Use theMCP to:chrome-devtools
- open that URL,
- inspect the DOM around the main transcript/chat view, and
- list layout or usability problems you see (especially on small widths).
Then propose concrete code changes (with diffs) to the UI files in this repo to fix them.”
playwright — End-to-End FlowsUse
playwright when you need to validate full user flows, not just layout:
_chat.txt → run pipeline → see outputs” works,Prompt pattern
“Use the
MCP to openplaywright,http://localhost:8501
click through the flow: select sample fixture → run pipeline → open transcript preview,
and report:
– which UI elements you clicked,
– any error messages,
– and a short list of UX issues.
Then propose code changes in the UI files to fix those issues, with diffs.”
git — Branches, Diffs, and HistoryUse the
git MCP for read-only repo introspection instead of raw git shell commands:
main,Rules
M3.2, M5.1) so changes stay traceable to AGENTS.md.git MCP to confirm:
Prompt pattern
“Use the
MCP on this repo to:git
– show the diff betweenand the current branch,main
– group changes by milestone task (M2.x/M3.x/M5.x/M6.x), and
– draft a PR description that:
• summarises behaviour changes,
• lists new/updated tests & fixtures, and
• notes any new config or MCP dependencies.”
If any of these MCP servers are misconfigured or unavailable: