{"id":"e64884d2-f210-466d-aefe-486023f4c942","shortId":"QVFqGE","kind":"skill","title":"slack-gif-creator","tagline":"Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like \"make me a GIF of X doing Y for Slack.\"","description":"# Slack GIF Creator\n\nA toolkit providing utilities and knowledge for creating animated GIFs optimized for Slack.\n\n## Slack Requirements\n\n**Dimensions:**\n- Emoji GIFs: 128x128 (recommended)\n- Message GIFs: 480x480\n\n**Parameters:**\n- FPS: 10-30 (lower is smaller file size)\n- Colors: 48-128 (fewer = smaller file size)\n- Duration: Keep under 3 seconds for emoji GIFs\n\n## Core Workflow\n\n```python\nfrom core.gif_builder import GIFBuilder\nfrom PIL import Image, ImageDraw\n\n# 1. Create builder\nbuilder = GIFBuilder(width=128, height=128, fps=10)\n\n# 2. Generate frames\nfor i in range(12):\n    frame = Image.new('RGB', (128, 128), (240, 248, 255))\n    draw = ImageDraw.Draw(frame)\n\n    # Draw your animation using PIL primitives\n    # (circles, polygons, lines, etc.)\n\n    builder.add_frame(frame)\n\n# 3. Save with optimization\nbuilder.save('output.gif', num_colors=48, optimize_for_emoji=True)\n```\n\n## Drawing Graphics\n\n### Working with User-Uploaded Images\nIf a user uploads an image, consider whether they want to:\n- **Use it directly** (e.g., \"animate this\", \"split this into frames\")\n- **Use it as inspiration** (e.g., \"make something like this\")\n\nLoad and work with images using PIL:\n```python\nfrom PIL import Image\n\nuploaded = Image.open('file.png')\n# Use directly, or just as reference for colors/style\n```\n\n### Drawing from Scratch\nWhen drawing graphics from scratch, use PIL ImageDraw primitives:\n\n```python\nfrom PIL import ImageDraw\n\ndraw = ImageDraw.Draw(frame)\n\n# Circles/ovals\ndraw.ellipse([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)\n\n# Stars, triangles, any polygon\npoints = [(x1, y1), (x2, y2), (x3, y3), ...]\ndraw.polygon(points, fill=(r, g, b), outline=(r, g, b), width=3)\n\n# Lines\ndraw.line([(x1, y1), (x2, y2)], fill=(r, g, b), width=5)\n\n# Rectangles\ndraw.rectangle([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)\n```\n\n**Don't use:** Emoji fonts (unreliable across platforms) or assume pre-packaged graphics exist in this skill.\n\n### Making Graphics Look Good\n\nGraphics should look polished and creative, not basic. Here's how:\n\n**Use thicker lines** - Always set `width=2` or higher for outlines and lines. Thin lines (width=1) look choppy and amateurish.\n\n**Add visual depth**:\n- Use gradients for backgrounds (`create_gradient_background`)\n- Layer multiple shapes for complexity (e.g., a star with a smaller star inside)\n\n**Make shapes more interesting**:\n- Don't just draw a plain circle - add highlights, rings, or patterns\n- Stars can have glows (draw larger, semi-transparent versions behind)\n- Combine multiple shapes (stars + sparkles, circles + rings)\n\n**Pay attention to colors**:\n- Use vibrant, complementary colors\n- Add contrast (dark outlines on light shapes, light outlines on dark shapes)\n- Consider the overall composition\n\n**For complex shapes** (hearts, snowflakes, etc.):\n- Use combinations of polygons and ellipses\n- Calculate points carefully for symmetry\n- Add details (a heart can have a highlight curve, snowflakes have intricate branches)\n\nBe creative and detailed! A good Slack GIF should look polished, not like placeholder graphics.\n\n## Available Utilities\n\n### GIFBuilder (`core.gif_builder`)\nAssembles frames and optimizes for Slack:\n```python\nbuilder = GIFBuilder(width=128, height=128, fps=10)\nbuilder.add_frame(frame)  # Add PIL Image\nbuilder.add_frames(frames)  # Add list of frames\nbuilder.save('out.gif', num_colors=48, optimize_for_emoji=True, remove_duplicates=True)\n```\n\n### Validators (`core.validators`)\nCheck if GIF meets Slack requirements:\n```python\nfrom core.validators import validate_gif, is_slack_ready\n\n# Detailed validation\npasses, info = validate_gif('my.gif', is_emoji=True, verbose=True)\n\n# Quick check\nif is_slack_ready('my.gif'):\n    print(\"Ready!\")\n```\n\n### Easing Functions (`core.easing`)\nSmooth motion instead of linear:\n```python\nfrom core.easing import interpolate\n\n# Progress from 0.0 to 1.0\nt = i / (num_frames - 1)\n\n# Apply easing\ny = interpolate(start=0, end=400, t=t, easing='ease_out')\n\n# Available: linear, ease_in, ease_out, ease_in_out,\n#           bounce_out, elastic_out, back_out\n```\n\n### Frame Helpers (`core.frame_composer`)\nConvenience functions for common needs:\n```python\nfrom core.frame_composer import (\n    create_blank_frame,         # Solid color background\n    create_gradient_background,  # Vertical gradient\n    draw_circle,                # Helper for circles\n    draw_text,                  # Simple text rendering\n    draw_star                   # 5-pointed star\n)\n```\n\n## Animation Concepts\n\n### Shake/Vibrate\nOffset object position with oscillation:\n- Use `math.sin()` or `math.cos()` with frame index\n- Add small random variations for natural feel\n- Apply to x and/or y position\n\n### Pulse/Heartbeat\nScale object size rhythmically:\n- Use `math.sin(t * frequency * 2 * math.pi)` for smooth pulse\n- For heartbeat: two quick pulses then pause (adjust sine wave)\n- Scale between 0.8 and 1.2 of base size\n\n### Bounce\nObject falls and bounces:\n- Use `interpolate()` with `easing='bounce_out'` for landing\n- Use `easing='ease_in'` for falling (accelerating)\n- Apply gravity by increasing y velocity each frame\n\n### Spin/Rotate\nRotate object around center:\n- PIL: `image.rotate(angle, resample=Image.BICUBIC)`\n- For wobble: use sine wave for angle instead of linear\n\n### Fade In/Out\nGradually appear or disappear:\n- Create RGBA image, adjust alpha channel\n- Or use `Image.blend(image1, image2, alpha)`\n- Fade in: alpha from 0 to 1\n- Fade out: alpha from 1 to 0\n\n### Slide\nMove object from off-screen to position:\n- Start position: outside frame bounds\n- End position: target location\n- Use `interpolate()` with `easing='ease_out'` for smooth stop\n- For overshoot: use `easing='back_out'`\n\n### Zoom\nScale and position for zoom effect:\n- Zoom in: scale from 0.1 to 2.0, crop center\n- Zoom out: scale from 2.0 to 1.0\n- Can add motion blur for drama (PIL filter)\n\n### Explode/Particle Burst\nCreate particles radiating outward:\n- Generate particles with random angles and velocities\n- Update each particle: `x += vx`, `y += vy`\n- Add gravity: `vy += gravity_constant`\n- Fade out particles over time (reduce alpha)\n\n## Optimization Strategies\n\nOnly when asked to make the file size smaller, implement a few of the following methods:\n\n1. **Fewer frames** - Lower FPS (10 instead of 20) or shorter duration\n2. **Fewer colors** - `num_colors=48` instead of 128\n3. **Smaller dimensions** - 128x128 instead of 480x480\n4. **Remove duplicates** - `remove_duplicates=True` in save()\n5. **Emoji mode** - `optimize_for_emoji=True` auto-optimizes\n\n```python\n# Maximum optimization for emoji\nbuilder.save(\n    'emoji.gif',\n    num_colors=48,\n    optimize_for_emoji=True,\n    remove_duplicates=True\n)\n```\n\n## Philosophy\n\nThis skill provides:\n- **Knowledge**: Slack's requirements and animation concepts\n- **Utilities**: GIFBuilder, validators, easing functions\n- **Flexibility**: Create the animation logic using PIL primitives\n\nIt does NOT provide:\n- Rigid animation templates or pre-made functions\n- Emoji font rendering (unreliable across platforms)\n- A library of pre-packaged graphics built into the skill\n\n**Note on user uploads**: This skill doesn't include pre-built graphics, but if a user uploads an image, use PIL to load and work with it - interpret based on their request whether they want it used directly or just as inspiration.\n\nBe creative! Combine concepts (bouncing + rotating, pulsing + sliding, etc.) and use PIL's full capabilities.\n\n## Dependencies\n\n```bash\npip install pillow imageio numpy\n```","tags":["slack","gif","creator","skills","anthropics","agent-skills"],"capabilities":["skill","source-anthropics","skill-slack-gif-creator","topic-agent-skills"],"categories":["skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/anthropics/skills/slack-gif-creator","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add anthropics/skills","source_repo":"https://github.com/anthropics/skills","install_from":"skills.sh"}},"qualityScore":"0.950","qualityRationale":"deterministic score 0.95 from registry signals: · indexed on github topic:agent-skills · official publisher · 136948 github stars · SKILL.md body (7,527 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:50:07.770Z","embedding":null,"createdAt":"2026-04-18T20:24:09.556Z","updatedAt":"2026-05-18T18:50:07.770Z","lastSeenAt":"2026-05-18T18:50:07.770Z","tsv":"'-128':78 '-30':70 '0':599,792,801 '0.0':586 '0.1':846 '0.8':716 '1':104,357,593,794,799,916 '1.0':588,857 '1.2':718 '10':69,114,507,921 '12':122 '128':110,112,126,127,503,505,936 '128x128':62,940 '2':115,347,699,928 '2.0':848,855 '20':924 '240':128 '248':129 '255':130 '3':86,147,256,279,307,937 '4':944 '400':601 '48':77,155,525,933,971 '480x480':66,943 '5':291,659,952 'acceler':741 'across':314,1019 'add':362,396,427,460,511,517,677,859,886 'adjust':711,779 'alpha':780,787,790,797,897 'alway':344 'amateurish':361 'and/or':687 'angl':757,766,876 'anim':10,20,26,52,136,183,662,988,998,1008 'appear':773 'appli':594,684,742 'around':753 'ask':902 'assembl':493 'assum':317 'attent':420 'auto':960 'auto-optim':959 'avail':488,607 'b':250,254,273,277,289,301,305 'back':620,833 'background':368,371,641,644 'base':720,1061 'bash':1091 'basic':337 'behind':411 'blank':637 'blur':861 'bounc':616,722,726,731,1079 'bound':815 'branch':472 'builder':96,106,107,492,500 'builder.add':144,508,514 'builder.save':151,521,967 'built':1028,1043 'burst':867 'calcul':455 'capabl':1089 'care':457 'center':754,850 'channel':781 'check':535,563 'choppi':359 'circl':140,395,417,648,651 'circles/ovals':241 'color':76,154,422,426,524,640,930,932,970 'colors/style':220 'combin':412,450,1077 'common':629 'complementari':425 'complex':376,444 'compos':625,634 'composit':442 'concept':21,663,989,1078 'consid':174,439 'constant':890 'constraint':16 'contrast':428 'conveni':626 'core':91 'core.easing':573,581 'core.frame':624,633 'core.gif':95,491 'core.validators':534,543 'creat':9,51,105,369,636,642,776,868,996 'creativ':335,474,1076 'creator':4,43 'crop':849 'curv':468 'dark':429,437 'depend':1090 'depth':364 'detail':461,476,550 'dimens':59,939 'direct':181,214,1070 'disappear':775 'doesn':1038 'drama':863 'draw':131,134,160,221,225,238,392,405,647,652,657 'draw.ellipse':242 'draw.line':281 'draw.polygon':268 'draw.rectangle':293 'duplic':531,946,948,977 'durat':83,927 'e.g':182,193,377 'eas':571,595,604,605,609,611,613,730,736,737,823,824,832,993 'effect':841 'elast':618 'ellips':454 'emoji':60,89,158,311,528,558,953,957,966,974,1015 'emoji.gif':968 'end':600,816 'etc':143,448,1083 'exist':322 'explode/particle':866 'fade':770,788,795,891 'fall':724,740 'feel':683 'fewer':79,917,929 'file':74,81,906 'file.png':212 'fill':247,270,286,298 'filter':865 'flexibl':995 'follow':914 'font':312,1016 'fps':68,113,506,920 'frame':117,123,133,145,146,188,240,494,509,510,515,516,520,592,622,638,675,749,814,918 'frequenc':698 'full':1088 'function':572,627,994,1014 'g':249,253,272,276,288,300,304 'generat':116,872 'gif':3,11,27,34,42,53,61,65,90,480,537,546,555 'gifbuild':98,108,490,501,991 'glow':404 'good':329,478 'gradient':366,370,643,646 'gradual':772 'graphic':161,226,321,327,330,487,1027,1044 'graviti':743,887,889 'heart':446,463 'heartbeat':705 'height':111,504 'helper':623,649 'higher':349 'highlight':397,467 'imag':102,167,173,202,209,513,778,1051 'image.bicubic':759 'image.blend':784 'image.new':124 'image.open':211 'image.rotate':756 'image1':785 'image2':786 'imagedraw':103,231,237 'imagedraw.draw':132,239 'imageio':1095 'implement':909 'import':97,101,208,236,544,582,635 'in/out':771 'includ':1040 'increas':745 'index':676 'info':553 'insid':384 'inspir':192,1074 'instal':1093 'instead':576,767,922,934,941 'interest':388 'interpol':583,597,728,821 'interpret':1060 'intric':471 'keep':84 'knowledg':5,49,983 'land':734 'larger':406 'layer':372 'librari':1022 'light':432,434 'like':30,196,485 'line':142,280,343,353,355 'linear':578,608,769 'list':518 'load':198,1055 'locat':819 'logic':999 'look':328,332,358,482 'lower':71,919 'made':1013 'make':31,194,326,385,904 'math.cos':673 'math.pi':700 'math.sin':671,696 'maximum':963 'meet':538 'messag':64 'method':915 'mode':954 'motion':575,860 'move':803 'multipl':373,413 'my.gif':556,568 'natur':682 'need':630 'note':1032 'num':153,523,591,931,969 'numpi':1096 'object':666,692,723,752,804 'off-screen':806 'offset':665 'optim':12,54,150,156,496,526,898,955,961,964,972 'oscil':669 'out.gif':522 'outlin':251,274,302,351,430,435 'output.gif':152 'outsid':813 'outward':871 'overal':441 'overshoot':830 'packag':320,1026 'paramet':67 'particl':869,873,881,893 'pass':552 'pattern':400 'paus':710 'pay':419 'philosophi':979 'pil':100,138,204,207,230,235,512,755,864,1001,1053,1086 'pillow':1094 'pip':1092 'placehold':486 'plain':394 'platform':315,1020 'point':261,269,456,660 'polish':333,483 'polygon':141,260,452 'posit':667,689,810,812,817,838 'pre':319,1012,1025,1042 'pre-built':1041 'pre-mad':1011 'pre-packag':318,1024 'primit':139,232,1002 'print':569 'progress':584 'provid':15,46,982,1006 'puls':703,708,1081 'pulse/heartbeat':690 'python':93,205,233,499,541,579,631,962 'quick':562,707 'r':248,252,271,275,287,299,303 'radiat':870 'random':679,875 'rang':121 'readi':549,567,570 'recommend':63 'rectangl':292 'reduc':896 'refer':218 'remov':530,945,947,976 'render':656,1017 'request':25,1064 'requir':58,540,986 'resampl':758 'rgb':125 'rgba':777 'rhythmic':694 'rigid':1007 'ring':398,418 'rotat':751,1080 'save':148,951 'scale':691,714,836,844,853 'scratch':223,228 'screen':808 'second':87 'semi':408 'semi-transpar':407 'set':345 'shake/vibrate':664 'shape':374,386,414,433,438,445 'shorter':926 'simpl':654 'sine':712,763 'size':75,82,693,721,907 'skill':325,981,1031,1037 'skill-slack-gif-creator' 'slack':2,14,29,40,41,56,57,479,498,539,548,566,984 'slack-gif-cr':1 'slide':802,1082 'small':678 'smaller':73,80,382,908,938 'smooth':574,702,827 'snowflak':447,469 'solid':639 'someth':195 'source-anthropics' 'sparkl':416 'spin/rotate':750 'split':185 'star':257,379,383,401,415,658,661 'start':598,811 'stop':828 'strategi':899 'symmetri':459 'target':818 'templat':1009 'text':653,655 'thicker':342 'thin':354 'time':895 'tool':18 'toolkit':45 'topic-agent-skills' 'transpar':409 'triangl':258 'true':159,529,532,559,561,949,958,975,978 'two':706 'unreli':313,1018 'updat':879 'upload':166,171,210,1035,1049 'use':22,137,179,189,203,213,229,310,341,365,423,449,670,695,727,735,762,783,820,831,1000,1052,1069,1085 'user':24,165,170,1034,1048 'user-upload':164 'util':7,47,489,990 'valid':17,533,545,551,554,992 'variat':680 'veloc':747,878 'verbos':560 'version':410 'vertic':645 'vibrant':424 'visual':363 'vx':883 'vy':885,888 'want':177,1067 'wave':713,764 'whether':175,1065 'width':109,255,278,290,306,346,356,502 'wobbl':761 'work':162,200,1057 'workflow':92 'x':36,686,882 'x1':243,262,282,294 'x2':245,264,284,296 'x3':266 'y':38,596,688,746,884 'y1':244,263,283,295 'y2':246,265,285,297 'y3':267 'zoom':835,840,842,851","prices":[{"id":"c32f5983-841d-4510-835c-e1c8a38bf0ec","listingId":"e64884d2-f210-466d-aefe-486023f4c942","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"anthropics","category":"skills","install_from":"skills.sh"},"createdAt":"2026-04-18T20:24:09.556Z"}],"sources":[{"listingId":"e64884d2-f210-466d-aefe-486023f4c942","source":"github","sourceId":"anthropics/skills/slack-gif-creator","sourceUrl":"https://github.com/anthropics/skills/tree/main/skills/slack-gif-creator","isPrimary":false,"firstSeenAt":"2026-04-18T21:24:29.531Z","lastSeenAt":"2026-05-18T18:50:07.770Z"},{"listingId":"e64884d2-f210-466d-aefe-486023f4c942","source":"skills_sh","sourceId":"anthropics/skills/slack-gif-creator","sourceUrl":"https://skills.sh/anthropics/skills/slack-gif-creator","isPrimary":true,"firstSeenAt":"2026-04-18T20:24:09.556Z","lastSeenAt":"2026-05-07T22:40:14.007Z"}],"details":{"listingId":"e64884d2-f210-466d-aefe-486023f4c942","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"anthropics","slug":"slack-gif-creator","github":{"repo":"anthropics/skills","stars":136948,"topics":["agent-skills"],"license":null,"html_url":"https://github.com/anthropics/skills","pushed_at":"2026-05-17T22:47:19Z","description":"Public repository for Agent Skills","skill_md_sha":"16660d8ceb77af47986bba1c9176c2ff3f287a91","skill_md_path":"skills/slack-gif-creator/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/anthropics/skills/tree/main/skills/slack-gif-creator"},"layout":"multi","source":"github","category":"skills","frontmatter":{"name":"slack-gif-creator","license":"Complete terms in LICENSE.txt","description":"Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like \"make me a GIF of X doing Y for Slack.\""},"skills_sh_url":"https://skills.sh/anthropics/skills/slack-gif-creator"},"updatedAt":"2026-05-18T18:50:07.770Z"}}