Session Log — 2026-07-11¶
OpenCode as a chat agent / MCP discussion¶
- User asked whether an MCP could turn OpenCode into a general chat agent.
- Conclusion: OpenCode is already a general chat agent; MCPs extend capabilities (tools/data/channels), they don't change the core nature.
- Noted available local tooling for image work: ImageMagick (
convert/mogrify) and Pillow 12.3 are installed.
Built: canva-design OpenCode skill (local Canva-style generator)¶
User wanted "more like Canva" — i.e. design generation (templates, text overlays, branded graphics), not just pixel edits.
Researched two paths:
1. Official Canva MCP — hosted at https://mcp.canva.com/mcp, OAuth2 via mcp-remote bridge, needs a Canva account. True Canva, cloud-bound.
2. Local skill — generate designs locally, no account. Chosen by user (all design types: social posts, thumbnails/banners, flyers, quote/branded graphics).
Confirmed global skill path: ~/.config/opencode/skills/<name>/SKILL.md (name must be lowercase-hyphen, match dir).
Files created (~/.config/opencode/skills/canva-design/)¶
SKILL.md— frontmatter + workflow + dimensions catalog + render/preview commandstemplates/— 9 starter HTML/CSS templates:social-post.html1080×1080 ·story.html1080×1920 ·linkedin-banner.html1584×396youtube-thumbnail.html1280×720 ·banner.html1200×628 ·flyer.html1080×1350quote-card.html1080×1080 ·announcement.html1080×1080 ·logo.html600×600lib/render.js—node lib/render.js <in.html> <out.png> <w> <h> [scale]; renders via cached Chromium (Playwright). Installedplaywrightintolib/(browsers already cached). Default scale 2 → 2× crisp output.lib/serve.js—node lib/serve.js <file> [port]; serves over localhost + opens in browser (xdg-open). For HTML previews user can refresh after edits.lib/brand.json— default brand kit (colors/fonts/logo) to persist the user's brand.
Browser preview added¶
- Agent cannot read images, so added
serve.jsto display designs in the user's browser. - Verified
DISPLAY=:1is set →xdg-openopens a real window. Remote note:ssh -L 8787:localhost:8787.
Verification¶
- All 9 templates rendered to correct dimensions (e.g. 1080×1080 → 2160×2160 at 2×).
- End-to-end test: custom "Summer Sale" post (orange + black) rendered successfully.
Test: LEMO Instagram post¶
Generated an Instagram post for LEMO EGG.2B.302.CLL as a skill demo (user confirmed it was just a test, "well done").
- Source image: original product image
EGG_CLL.webpfrom the Shopify store (https://cdn.shopify.com/s/files/1/1050/7662/1393/files/EGG_CLL.webp), converted toegg_cll.png(450×450). - Product context (from store + lemo.com): EGG.2B.302.CLL = 2-pin panel socket, fixed panel front mount, solder, IP50, −55→+250°C, 5000 mating cycles, chrome-plated brass, push-pull self-latching, B Series.
- Output:
/home/dini/designs/lemo/instagram-post.{html,png}(2160×2160), served athttp://localhost:8787/instagram-post.png.
Notes / follow-ups¶
~does NOT expand in the OpenCode bash tool shell — use absolute paths (/home/dini/...).- Could add a
/designslash command and more template styles later. - Official Canva MCP remains an option if true Canva integration is ever wanted.
Edited: Shopify Import Tool V12 — added global Tags column¶
User wanted the v12 metafield tool (/home/dini/Downloads/work/Shopify_import_tool_V12.html) to output a Tags column.
Decision: a manual global Tags box (not auto-derived from metafields). User types comma-separated tags once; that value is written to the Tags column of every exported product row.
Changes made to Shopify_import_tool_V12.html¶
- New
#globalTagstext input in the Metafields card (under the bulk-apply row). - New
#pTagspreview in the Preview card (live badge preview as you type). globalTagsvariable, persisted tolocalStorage(v12_global_tags); input listener updates it + the preview live.render()shows#pTags.exportCSV(): header nowHandle,Title,Body (HTML),Variant SKU,Tags,...; every row gets the tags value (normalized: trimmed, comma-joined).- Backup saved as
Shopify_import_tool_V12.bak.htmlbefore editing.
Verification (headless Playwright)¶
- Unit: normalization + preview correct.
- E2E: loaded real
shopify_metafield_export.csv(47 products) → 47 export rows →Tagscolumn at index 4 (afterVariant SKU) → all 47 rows contain the entered tags. PASS.
Notes¶
- Tags are global (one value → all rows), per user's "on every product line" intent.
- Out of scope (user dropped earlier idea): auto-deriving tags from Series/Size metafields.