fablecut 1.12.1 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -37,7 +37,10 @@ Every Claude Code session then has these tools:
37
37
  - `fablecut_export` — render the timeline to a file in `exports/` with the editor's own
38
38
  Fast export (open tab, or headless Chrome / Edge). See "Export" below.
39
39
  - `fablecut_scopes` — measure the graded picture at a moment (levels, clipping, colour
40
- cast), as the editor's scopes see it. See "Color" below.
40
+ cast), as the editor's scopes see it; also what a grade layer or a clip's masks
41
+ select. See "Color" and "Masks" below.
42
+ - `fablecut_track` — motion tracking: follow a region of a video clip, store it as
43
+ a track, and make a mask or another clip follow it. See "Tracking" below.
41
44
 
42
45
  ### Token-efficient editing (important for agents)
43
46
 
@@ -313,7 +316,8 @@ Examples in `library/svg/`: `sparkles.svg` (loop), `lower-third.svg`,
313
316
  | `scale` | 1 | |
314
317
  | `rotation` | 0 | degrees |
315
318
  | `opacity` | 1 | 0–1 |
316
- | `blend` | "normal" | multiply · screen · overlay · lighter · soft-light · hard-light · color-dodge · darken · lighten · difference |
319
+ | `blend` | "normal" | how the clip lays over what is under it (see Track mattes and blending) |
320
+ | `matte` · `matteTrack` | — | a track matte (see Track mattes and blending) |
317
321
 
318
322
  **Layout** (video/image/svg):
319
323
  | prop | default | notes |
@@ -424,6 +428,10 @@ intensity. Keyframe/transition it like any clip. Put it on V2/V3 above the
424
428
  footage. Example: 0.3 s impact shake over everything =
425
429
  `{kind:"adjust", track:"V3", duration:0.3, props:{shake:18}}`.
426
430
 
431
+ **Masks** (`masks`, video/image/svg/text/adjust): shapes that cut what the clip
432
+ shows — rect, ellipse, bezier, free-hand; feather, expand, invert, add /
433
+ subtract / intersect, keyframes. See "Masks" below.
434
+
427
435
  **Animatable props** (usable in `keyframes`): x, y, scale, rotation, opacity,
428
436
  volume, pan, duck, speed, brightness, contrast, saturation, hue, blur, grayscale, sepia,
429
437
  invert, temperature, tint, vignette, cornerRadius, shake, rgbSplit, grain,
@@ -619,12 +627,12 @@ each one's qualifier looks at the picture as it reaches that layer.
619
627
  | `qualifier.hue` | `[centre°, width°, soft°]` — hues within ±width/2 of the centre, easing out over `soft`; wraps through red. Greys carry no hue, so a hue range leaves them out |
620
628
  | `qualifier.sat` · `qualifier.luma` | `[low, high, soft]` on 0…1 — saturation (HSV) / Rec.709 luma between low and high |
621
629
  | `qualifier.invert` | select everything else |
622
- | `mask.shape` | `ellipse` · `rect` · `poly` |
630
+ | `mask.shape` | `ellipse` · `rect` · `poly` · `bezier` (or `freehand` with a `stroke`, fitted into a bezier — see "Masks") |
623
631
  | `mask.x` · `mask.y` | centre, as fractions of the clip's picture (0…1, y down) |
624
632
  | `mask.w` · `mask.h` | size, fractions of the picture's width / height (ellipse, rect) |
625
633
  | `mask.rotation` | degrees, clockwise |
626
634
  | `mask.feather` | soft edge, a fraction of the picture's height (0…0.5), centred on the outline |
627
- | `mask.points` | poly: 3–16 `[dx, dy]` corners around `x, y` (fractions of width / height) |
635
+ | `mask.points` | poly: 3–16 `[dx, dy]` corners around `x, y` (fractions of width / height); bezier: 3–24 anchors `[dx, dy]` or `[dx, dy, inX, inY, outX, outY]` with curve handles |
628
636
  | `mask.invert` | grade outside the shape |
629
637
  | `mask.keys` | animate it: `[{t, x?, y?, w?, h?, rotation?, feather?, ease?}]`, `t` in seconds from the clip's start; each param eases between the keys that set it (`ease` on the arriving key, as for clip keyframes) |
630
638
 
@@ -639,8 +647,9 @@ curves edit that layer, and three more sections appear: the layer's name,
639
647
  reorder, **Delete**; **Qualifier** — **Pick** then click a colour in the
640
648
  monitor to select its hue, saturation and luma, then tune the ranges; and
641
649
  **Mask** — pick a shape and drag it on the monitor (inside moves it, the
642
- handles resize it, the knob rotates it, Shift snaps to 15°; on a poly,
643
- Ctrl-click adds a point and double-click removes one). **◆ Key** keys the
650
+ handles resize it, the knob rotates it, Shift snaps to 15°; on a poly or
651
+ bezier, Ctrl-click adds a point and double-click removes one), or **Draw** a
652
+ free-hand outline on the monitor (it becomes a bezier). **◆ Key** keys the
644
653
  shape at the playhead; once it has keys, every change to the shape keys.
645
654
 
646
655
  **Wheel colours.** A wheel's `r, g, b` normally carry no brightness: they are a
@@ -703,6 +712,219 @@ other shot of the scene until its median and cast land near the hero's. In the
703
712
  editor, **Copy** / **Paste** on the Color tab pastes one clip's grade onto every
704
713
  selected clip.
705
714
 
715
+ ### Masks
716
+
717
+ A clip's masks cut what it shows: only the parts the masks keep reach the
718
+ frame, so a clip can be isolated, revealed or cut through, and anything under
719
+ it shows in the gaps. They live in `props.masks` on any video, image, svg,
720
+ text or adjustment clip. On an adjustment layer they limit where its effects
721
+ and grade apply. They run in preview and export alike. The clip draws as usual,
722
+ the masks cut it, and then its `opacity` and `blend` composite it.
723
+
724
+ ```jsonc
725
+ "masks": [
726
+ { "name": "Subject", "shape": "ellipse", "x": 0.52, "y": 0.45, "w": 0.4, "h": 0.7, "feather": 40 },
727
+ { "name": "Hole", "shape": "rect", "mode": "subtract", "x": 0.6, "y": 0.4, "w": 0.1, "h": 0.1 },
728
+ { "shape": "bezier", "x": 0.3, "y": 0.7, "expand": 8,
729
+ "points": [[0, -0.1], [0.12, 0.08, 0, -0.05, 0, 0.05], [-0.12, 0.08]],
730
+ "keys": [{ "t": 0, "x": 0.3 }, { "t": 2, "x": 0.6, "ease": "linear" }] }
731
+ ]
732
+ ```
733
+
734
+ | key | default | does |
735
+ |---|---|---|
736
+ | `shape` | — | `rect` · `ellipse` · `bezier` (write `freehand` with a `stroke` to have one drawn for you) |
737
+ | `x` · `y` | 0.5 | centre, as fractions of the clip's picture (0…1, y down) |
738
+ | `w` · `h` | 0.5 | size, fractions of the picture's width / height (rect, ellipse) |
739
+ | `points` | — | bezier: 3–64 anchors around `x, y`, each `[dx, dy]` (a corner) or `[dx, dy, inX, inY, outX, outY]` (with curve handles relative to the anchor), all fractions of the picture's width / height |
740
+ | `stroke` | — | freehand only: `[[u, v], …]` picture fractions along an outline; it is simplified and stored as an editable `bezier` |
741
+ | `scale` · `rotation` | 1 · 0 | about the centre; degrees clockwise |
742
+ | `mode` | `add` | how this mask combines with the ones before it: `add` · `subtract` · `intersect` · `difference` |
743
+ | `invert` | false | use everything outside the shape |
744
+ | `opacity` | 1 | 0…1, how strongly this mask counts |
745
+ | `feather` | 0 | soft edge, project pixels, centred on the outline |
746
+ | `expand` | 0 | grow (+) or shrink (−) the outline, project pixels |
747
+ | `name` · `on` | — | a label; `on:false` turns the mask off |
748
+ | `keys` | — | animate it: `[{t, x?, y?, w?, h?, scale?, rotation?, feather?, expand?, opacity?, points?, ease?}]`, `t` in seconds from the clip's start; each param eases between the keys that set it (`ease` on the arriving key, as for clip keyframes). `points` keys morph the outline and need the shape's point count |
749
+
750
+ Masks combine bottom-up (first in the list first). The first one starts from
751
+ nothing when it adds and from the whole picture otherwise, so a lone
752
+ `subtract` cuts a hole in a full picture. At most 8 masks per clip.
753
+
754
+ The picture a mask lives in is the clip's drawn rectangle for video, image
755
+ and svg (after fit and crop), the text block for text, and the whole canvas
756
+ for an adjustment layer. Masks follow the clip when it is moved, scaled,
757
+ rotated or flipped, and keep the clip's keyframes.
758
+
759
+ In the editor, the **Masks** section of the Inspector has **+ Rect**,
760
+ **+ Ellipse**, **Pen** (click points on the monitor, drag while placing one to
761
+ pull curve handles, click the first point or press Enter to close) and
762
+ **Draw** (drag a free-hand outline). **Matte** shows the clip's matte in the
763
+ monitor (white = visible). Pick a mask's chip to edit it: mode, **Invert**,
764
+ the sliders, ↑ ↓ to reorder, **Copy**, **Delete**, and on the monitor, drag
765
+ inside to move it, the edge handles to resize it and the knob to rotate it
766
+ (Shift snaps to 15°). On a bezier, drag a point to move it, drag its handles
767
+ to curve it (Alt breaks the pair), Alt-drag a point to pull fresh handles,
768
+ Ctrl-click the outline to add a point, and double-click a point to remove
769
+ it. **◆ Key** keys the whole mask at the playhead; once it has keys, every
770
+ change keys. Esc steps back (point, then mask).
771
+
772
+ **Agents** edit masks with patch ops:
773
+
774
+ - `{op:"setMask", id, set:{shape:"ellipse", x:0.5, y:0.45, w:0.4, h:0.7, feather:40}}`
775
+ adds a mask (no `mask`, an index one past the end or a new name adds one; a
776
+ new mask needs `shape`). `{op:"setMask", id, mask:"Subject", set:{x:0.6}}`
777
+ edits one, by index (0 = first) or name, merging key by key (`null` resets a
778
+ key). `replace:true` starts it over, keeping its name. `ids:[…]` edits several clips.
779
+ - A drawn outline: `set:{shape:"freehand", stroke:[[0.4, 0.3], [0.6, 0.32], …]}`.
780
+ It is stored as an editable bezier.
781
+ - `{op:"setMaskKeys", id, mask, keys:[{t:0, x:0.3}, {t:2, x:0.7}]}` animates
782
+ one (`keys:null` stops it); `{op:"removeMask", id, mask}` deletes one.
783
+ - `props.masks` written through `addClip` / `updateClip` is validated the same
784
+ way. Bad keys, shapes or values refuse the whole patch. Locks apply
785
+ (`force:true` as elsewhere).
786
+ - `fablecut_scopes {time, mask:{clip}}` measures them: the % of the clip's
787
+ picture its masks keep (the feathered matte, measured alone) and the % of
788
+ the frame the masked clip covers. The compact project view lists each
789
+ clip's masks as `[2 masks: ellipse feather 40, rect subtract]`.
790
+
791
+ Recipes: **spotlight** — a feathered ellipse on the clip; **split screen** —
792
+ two clips on V1 / V2, a `rect` on the top one covering its half; **cut a
793
+ logo out of the background** — a bezier around it, `feather` 2–4;
794
+ **reveal** — a rect whose `w` (or `x`) keys from 0 to full; **effects only
795
+ on the face** — an adjustment layer with a feathered ellipse, keyed to follow
796
+ it; **vignette through an adjustment layer** — an inverted ellipse with
797
+ `feather:200` and the layer's `brightness` down.
798
+
799
+ ### Track mattes and blending
800
+
801
+ A **track matte** cuts a clip with the picture on another track: where that
802
+ picture is opaque (alpha) or bright (luma), the clip shows. Set it on the
803
+ clip being cut, the fill:
804
+
805
+ | prop | does |
806
+ |---|---|
807
+ | `matte` | `alpha` · `alpha-inverted` · `luma` · `luma-inverted`. Alpha keeps the clip where the matte's pixels are opaque, luma where they are bright (white = shows, black = gone, Rec. 709 weights). The inverted modes keep the opposite |
808
+ | `matteTrack` | the video track the matte comes from. Default: the video track directly above the clip (V2 for a clip on V1) |
809
+
810
+ The matte track does not draw into the frame while a clip on screen uses it;
811
+ it only cuts. Its clips keep their own transform, keyframes, opacity, masks
812
+ and effects, so the matte can move, scale and animate on its own. When the
813
+ matte track has nothing at that moment, `alpha` / `luma` show nothing of the
814
+ clip and the inverted modes show all of it. Track mattes and masks combine:
815
+ the matte cuts the clip, then its masks cut what is left, then `opacity` and
816
+ `blend` composite it. A clip used as a matte is drawn without its own track
817
+ matte. Audio clips take neither.
818
+
819
+ `blend` is how a clip lays over what is under it: `normal` · `multiply` ·
820
+ `screen` · `overlay` · `darken` · `lighten` · `color-dodge` · `color-burn` ·
821
+ `hard-light` · `soft-light` · `difference` · `exclusion` · `hue` ·
822
+ `saturation` · `color` · `luminosity` · `lighter` (add). Blending happens after
823
+ masks and mattes, so a masked clip only blends where it is kept.
824
+
825
+ In the editor, **Track matte** and **Matte track** sit under **Blend** in the
826
+ Inspector's Transform section (the Adjustment layer section for an adjustment
827
+ layer). The timeline marks a clip with a track matte ◐ and shows the clips
828
+ that serve as its matte hatched, labelled **Matte**.
829
+
830
+ **Agents:** `{op:"setMatte", id, matte:"luma"}` (or `ids:[…]`; `track:"V3"`
831
+ picks the matte track, `track:null` goes back to the one above;
832
+ `matte:null` removes it). `blend`, `matte` and `matteTrack` written through
833
+ `addClip` / `updateClip` are validated too. `fablecut_scopes` lists each clip
834
+ on screen with its `matte` (e.g. `luma from V2`), `blend`, and whether it is a
835
+ matte itself.
836
+
837
+ Recipes: **text filled with video** — the text on V2, the video on V1 with
838
+ `matte:"alpha"`; **a shape reveal** — an svg or a masked solid on V2 whose
839
+ scale keys up, the shot on V1 with `matte:"alpha"`; **light leaks / film
840
+ burn** on V2 with `blend:"screen"`; **a grade only in the bright areas** — an
841
+ adjustment layer with `matte:"luma"` over a copy of the shot;
842
+ **a cut-out through a texture** — `luma-inverted` against a black-and-white
843
+ texture.
844
+
845
+ ### Tracking
846
+
847
+ Motion tracking follows something in a video clip frame by frame: a corner, a
848
+ logo, a face, a sign. The result is a **track** stored on the clip, and masks
849
+ and other clips **follow** it by having it written into their keys. Rendering
850
+ never reads a track, so a followed mask or title renders and exports exactly
851
+ like a hand-keyed one, and you can edit its keys afterwards.
852
+
853
+ ```jsonc
854
+ "tracks": [
855
+ { "name": "Logo", "kind": "point", "w": 0.08, "h": 0.14,
856
+ "samples": [[0, 0.31, 0.42, 1, 0, 1], [0.0333, 0.312, 0.421, 1, 0, 0.98]] }
857
+ ]
858
+ ```
859
+
860
+ | key | does |
861
+ |---|---|
862
+ | `name` | how masks, clips and agents refer to it (default `Track n`, or the mask's name) |
863
+ | `kind` | `point` (position) or `box` (position, size and rotation were followed) |
864
+ | `w` · `h` | the region that was matched, fractions of the clip's picture |
865
+ | `samples` | one per frame: `[t, x, y, s, r, q]`. `t` is seconds from the clip's start, `x, y` is the centre (fractions of the picture, like masks), `s` is the scale and `r` the rotation (°) relative to the first sample, `q` is the match quality 0…1 |
866
+
867
+ The tracker matches a small greyscale template of the region (normalized
868
+ cross-correlation, sub-pixel, optionally over scale and rotation) and keeps
869
+ the template fresh while anchoring it to the first frame so it does not
870
+ drift. It stops where the match quality drops below 0.45 (the region was
871
+ covered, left the frame or changed too much) and keeps what it tracked up to
872
+ there. Pick regions with detail: corners, text, edges. Flat sky or a blank
873
+ wall can't be tracked. A track without scale follows position only: if the
874
+ thing grows, shrinks or turns noticeably, turn on Scale / Rotate (`scale` /
875
+ `rotation`), or the match fades and the track stops early. Tracks are stored in clip time, so they move with the clip and follow
876
+ trims and splits (re-track after changing its speed).
877
+
878
+ In the editor:
879
+
880
+ - **Mask tracking.** Select a mask on a video clip. Under its mode row,
881
+ **◀ Back** and **On ▶** follow what the mask covers from the playhead to
882
+ the clip's start or end, and key the mask's `x` / `y`. Turn on **Scale**
883
+ and **Rotate** to key those too. The keys are linear and simplified (a key
884
+ only where the motion turns, within ~1.5 px). Keys the mask had in that range lose their
885
+ position and keep everything else.
886
+ - **Point tracking.** The Inspector's **Tracking** section (video clips):
887
+ **+ Track point**, then click the spot on the monitor. It tracks from the
888
+ playhead to the clip's end. **Region** sets the matched area (% of the
889
+ picture's width). Pick a track's chip to see its path and region on the
890
+ monitor, **◀ Track back** / **Track on ▶** to extend it from the playhead,
891
+ and **Delete** it.
892
+ - **Attach a clip.** With a track picked, choose a clip in **Attach**
893
+ (any visual clip that overlaps it in time) and press **Attach to the track**. The clip
894
+ gets `x` / `y` keyframes (plus `scale` / `rotation` with those toggles on)
895
+ that ride on the track and keep it where it is at the playhead. Stickers,
896
+ titles, a blur box or a highlight then stay pinned to the moving thing.
897
+ - Tracking runs from a private copy of the video, so the monitor does not
898
+ move. Progress shows in the Inspector, and **Esc** stops it and keeps what
899
+ it has. Each finished track is one undo step.
900
+
901
+ **Agents:** `fablecut_track` runs the tracker in the editor (an open tab, else
902
+ headless Chrome / Edge) and saves the result:
903
+
904
+ - `{clip, point:{x:0.62, y:0.4}, at:12}` follows a spot from `at` to the
905
+ clip's end. `region:{x, y, w, h}` gives the area instead, `size` sets a
906
+ point's region (default 0.08 of the width), `direction:"backward"|"both"`
907
+ and `to` (timeline seconds) set the range, and `scale` / `rotation` follow
908
+ those too.
909
+ - `apply:{mask:"Face"}` bakes the result into that mask's keys. Leave out
910
+ `point` / `region` and the mask's own outline is what gets followed.
911
+ - `apply:{clip:"c_sticker", scale?, rotation?, at?}` pins another clip to
912
+ the track.
913
+ - `name` names the track. Passing an existing name with `apply` and no
914
+ region re-applies the stored track without tracking again.
915
+ - The reply gives the range, the match quality (min / mean; ≥ 0.8 is solid),
916
+ where it was lost, and what was keyed.
917
+ - `{op:"removeTrack", id, track}` deletes a stored track; what followed it
918
+ keeps its keys. The compact project view lists tracks as
919
+ `[tracks: "Logo" point 0.00–4.20 s (127 samples)]`, never their samples.
920
+
921
+ Recipes: **a title that follows a car** — track a point on the car, attach
922
+ the title; **blur a face or a plate** — an ellipse mask on a blurred copy of
923
+ the shot on the track above, then `apply:{mask:"Face"}`; **a screen replacement** —
924
+ track the screen with Scale and Rotate on and attach the new picture, cropped
925
+ to fit; **a highlight that stays on a UI element** in a screen recording —
926
+ track the button, attach a rect svg.
927
+
706
928
  ### Semantics
707
929
 
708
930
  - Rendering order: V1 is drawn first, then V2, V3, … on top. SVG/image/text clips
package/README.md CHANGED
@@ -178,15 +178,29 @@ same time.
178
178
  pivot, soft rolloff and saturation, plus **curves** — luma and R / G / B,
179
179
  hue vs hue, hue vs saturation, hue vs luma and saturation vs luma, with a
180
180
  picker that marks a colour from the monitor, and **layers** (secondaries):
181
- a correction limited by an HSL **qualifier** and / or an ellipse, rect or
182
- polygon **mask** (feathered, invertible, keyframable, dragged on the
183
- monitor), with a matte view. Copy / paste a grade across shots.
181
+ a correction limited by an HSL **qualifier** and / or an ellipse, rect,
182
+ polygon, bezier or free-hand **mask** (feathered, invertible, keyframable,
183
+ dragged on the monitor), with a matte view. Copy / paste a grade across shots.
184
184
  Agents grade with the `setGrade` patch op and read the result as numbers
185
185
  with `fablecut_scopes` (levels, clipping, colour cast)
186
186
  - Quick filter sliders: brightness/contrast/saturation/hue, **temperature & tint**,
187
187
  blur, grayscale/sepia/invert, **vignette**, animated **film grain**
188
- - Blend modes (screen, multiply, overlay…), fit modes (contain/cover/stretch),
188
+ - 17 blend modes (screen, multiply, overlay, color-burn, exclusion, hue,
189
+ luminosity…), fit modes (contain/cover/stretch),
189
190
  per-edge cropping, corner radius, flip H/V
191
+ - **Masks** — isolate any part of a clip (video, image, SVG, text or an
192
+ adjustment layer): rectangle, ellipse, **bezier pen** and **free-hand**
193
+ shapes, several per clip, combined with add / subtract / intersect /
194
+ difference, each with feather, expansion, invert and opacity, all
195
+ keyframable (outlines morph). Draw and edit them on the monitor, with a
196
+ matte view. Agents use the `setMask` patch op and measure with `fablecut_scopes`
197
+ - **Motion tracking** — follow a point or a region (with its scale and
198
+ rotation) through a video clip, then make a mask follow it or pin a title,
199
+ sticker or any clip to it; the result is ordinary editable keys. Agents use
200
+ `fablecut_track`
201
+ - **Track mattes** — cut a clip with the picture on the track above by its
202
+ alpha or its luma (inverted or not): text filled with video, shape reveals,
203
+ texture cut-outs. The matte track hides itself. Agents use `setMatte`
190
204
  - **Chroma key** (green screen) with tolerance/softness + spill suppression
191
205
  - **AI background removal** (person cut-out, in-browser via MediaPipe)
192
206
 
@@ -379,7 +393,7 @@ Three equivalent control surfaces:
379
393
  `fablecut_get_project`, `fablecut_set_project`, `fablecut_patch_project`,
380
394
  `fablecut_import_media`, `fablecut_analyze_reference`,
381
395
  `fablecut_encode_profiles`, `fablecut_normalize_audio`, `fablecut_auto_duck`,
382
- `fablecut_denoise`, `fablecut_export`, `fablecut_scopes`.
396
+ `fablecut_denoise`, `fablecut_export`, `fablecut_scopes`, `fablecut_track`.
383
397
 
384
398
  FableCut is also published on the **official MCP registry** as
385
399
  [`io.github.ronak-create/fablecut`](https://registry.modelcontextprotocol.io/v0/servers?search=fablecut)
@@ -555,11 +569,11 @@ examples in [`library/svg/`](library/svg/).
555
569
 
556
570
  ## Sponsors
557
571
 
558
- <a href="https://fluxionai.world/register?source=github&amp;campaign=github-fablecut&amp;promo=FABLECUT" target="_blank" rel="noopener noreferrer sponsored">
559
- <img src="docs/sponsors/fluxion-ai-banner.png" alt="Fluxion AI — unified access to GPT, Claude and other leading AI models" width="640">
572
+ <a href="https://fluxionai.space/register?source=github&amp;campaign=github-sidrune-fablecut&amp;promo=SDRFABLECUT" target="_blank" rel="noopener noreferrer sponsored">
573
+ <img src="docs/sponsors/sidrune-ai-banner.png" alt="Sidrune AI — one API for GPT, Claude and other leading AI models" width="640">
560
574
  </a>
561
575
 
562
- **[Fluxion AI](https://fluxionai.world/register?source=github&campaign=github-fablecut&promo=FABLECUT)** provides reliable, cost-efficient access to GPT, Claude, and other leading AI models through one unified API. Save up to 70% compared with official API pricing — and get $3 in API credits when you sign up through this link.
576
+ **[Sidrune AI](https://fluxionai.space/register?source=github&campaign=github-sidrune-fablecut&promo=SDRFABLECUT)** — One API for GPT, Claude, and other leading AI models. Sign up and get $3 in API credit.
563
577
 
564
578
  ## Community
565
579