Skip to main content

vexy-lines-apy

Python bindings to the Vexy Lines MCP API and style engine.

Connect to the Vexy Lines app over TCP and drive it from Python: open documents, change fill parameters, render, export. Transfer or blend artistic styles between images without touching the GUI.

Requires the Vexy Lines app (macOS or Windows) for all MCP operations. If the app isn't running, the client launches it.

Install

pip install vexy-lines-apy

For SVG object manipulation (svg_parsed()), install the svg extra:

pip install "vexy-lines-apy[svg]"

or directly: pip install svglab

Quick start

from vexy_lines_api import MCPClient

with MCPClient() as vl:
    vl.open_document("photo.lines")

    info = vl.get_document_info()
    print(f"{info.width_mm:.0f} x {info.height_mm:.0f} mm @ {info.resolution} dpi")

    tree = vl.get_layer_tree()          # LayerNode tree
    vl.render()                          # render all layers, wait for completion
    vl.export_svg("output.svg")

MCPClient() connects to localhost:47384. If the app isn't open, the client launches it and waits up to 30 seconds.

Export formats

with MCPClient() as vl:
    vl.open_document("art.lines")
    vl.render()

    vl.export_svg("out.svg")
    vl.export_pdf("out.pdf")
    vl.export_png("out.png", dpi=150)
    vl.export_jpeg("out.jpg")
    vl.export_eps("out.eps")

    # SVG as a string (useful for embedding or piping)
    svg_text = vl.svg()

    # SVG as a parsed svglab object (requires svglab)
    svg_obj = vl.svg_parsed()

Edit fill parameters

with MCPClient() as vl:
    vl.open_document("art.lines")
    tree = vl.get_layer_tree()

    # Find a fill node and change its colour
    fill_id = tree.children[0].children[0].children[0].id
    vl.set_fill_params(fill_id, color="#3a7bd5", opacity=0.9)

    vl.render()
    vl.export_png("result.png")

Edit image filters

Fills can carry an ordered source-image filter chain. The MCP API uses names such as brightness, levels, invert, color, and gradient.

with MCPClient() as vl:
    vl.open_document("art.lines")
    fill_id = 42

    vl.set_image_filters(fill_id, [
        {"type": "brightness", "params": {"value": 25.0}},
        {"type": "levels", "params": {"left": 10, "right": 240}},
    ])

    filters = vl.get_image_filters(fill_id)

Style engine

Extract the complete fill structure from a .lines file and apply it to any source image. No GUI required.

from vexy_lines_api import MCPClient, extract_style, apply_style

style = extract_style("reference.lines")   # parse fill tree from file

with MCPClient() as vl:
    svg = apply_style(vl, style, "photo.jpg", dpi=72)

with open("result.svg", "w") as f:
    f.write(svg)

Style interpolation

Blend two compatible styles at any mix ratio. Numeric fill parameters and colours interpolate linearly.

from vexy_lines_api import MCPClient, extract_style, interpolate_style, apply_style

painterly = extract_style("painterly.lines")
technical = extract_style("technical.lines")

mid = interpolate_style(painterly, technical, t=0.5)   # halfway blend

with MCPClient() as vl:
    svg = apply_style(vl, mid, "photo.jpg")

Two styles are compatible for interpolation when they share the same group/layer/fill structure with matching fill types and matching image-filter chains. Check with styles_compatible(a, b) before blending.

Explicit .lines interpolation

Generate an actual intermediate .lines file between two compatible documents without opening the app:

from vexy_lines_api import interpolate_lines

interpolate_lines("start.lines", "end.lines", "mid.lines", t=0.5)

The output keeps the XML structure and embedded images from start.lines, then rewrites matching interpolatable numeric XML attributes across the document, layers, fills, image filters, masks, and grid edges. Structural IDs, enum-like modes, flags, captions, and text stay intact. Native .lines colours are blended in their XML format, including #AARRGGBB. t=0 is the start document, t=1 is the end document.

Rendered timelines require the app:

from vexy_lines_api import render_interpolation_video, record_interpolation_screen

render_interpolation_video("start.lines", "end.lines", "blend.mp4", frames=120, fps=30)

record_interpolation_screen(
    "start.lines",
    "end.lines",
    "screen-frames/",
    frames=120,
    fps=30,
    zoom_steps=2,
    video_path="screen-recording.mp4",
)

render_interpolation_video() renders generated .lines frames via MCP, exports SVG from the app, rasterizes PNG frames locally, resizes mismatched frame dimensions to the first frame, and assembles an MP4. record_interpolation_screen() opens the start document in the GUI, applies optional zoom keystrokes on macOS, steps through generated interpolation documents, and captures the Vexy Lines window. Pass video_path to assemble those screenshots into MP4. If temporary work is auto-cleaned, the result omits intermediate frame and .lines paths unless you pass keep_work=True or work_dir.

AI-assisted rename of layers & fills

Rename a document's layers and fills based on what each fill actually draws. The renamer renders each fill in isolation, builds an "inspection image" (the fill framed by a red box over the faint full artwork), asks a vision model to describe it in three words, and writes a renamed copy of the .lines that preserves every fill parameter, mask, and image.

from vexy_lines_api import rename_lines

plan = rename_lines("road-12.lines")          # -> road-12-renamed.lines
for f in plan.fills:
    print(f.object_id, f.old_caption, "->", f.new_caption, f"({f.description})")

The renamer uses any OpenAI-compatible /v1 endpoint, configured from the environment: VEXY_LINES_LLM_API_URL, VEXY_LINES_LLM_API_KEY, VEXY_LINES_LLM_MODEL_VISION (vision), and VEXY_LINES_VLM_MODEL (text). Install the extra with pip install "vexy-lines-apy[ai]".

Visibility is baked into a temporary copy of the .lines (vexy_lines.set_visibility) rather than toggled live over MCP, because set_visible does not affect the export.

Full guide: AI Rename. Also available as vexy-lines-cli ai-rename and Lines ▸ AI Rename Layers & Fills… in the GUI.

Job folder (resumable exports)

Long-running exports (especially video) save every intermediate artifact to a persistent job folder alongside the output. If a job is interrupted, re-running the same command resumes where it left off.

from vexy_lines_api.export import ExportRequest, process_export

request = ExportRequest(
    mode="video",
    input_paths=["clip.mp4"],
    style_path="look.lines",
    end_style_path=None,
    output_path="styled.mp4",
    format="MP4",
    size="1x",
)
process_export(request)
# Creates styled-vljob/ with all intermediates:
#   src/src--styled--001.png, styled--001.lines, styled--001.svg, styled--001.png, ...

Use force=True to discard previous progress and start fresh. Use cleanup=True to delete the job folder after the final output is written.

Override the job folder location with the VEXY_LINES_JOB_FOLDER environment variable.

API reference

Document

Method Description
new_document(width, height, dpi, source_image) Create a new document
open_document(path) Open a .lines file
save_document(path) Save (or Save As)
export_document(path, format, dpi) Export to svg/pdf/png/jpg/eps
get_document_info() Returns DocumentInfo

Structure

Method Description
get_layer_tree() Returns root LayerNode
add_group(parent_id, caption) Add a group
add_layer(group_id) Add a layer to a group
add_fill(layer_id, fill_type, color, params) Add a fill to a layer
delete_object(object_id) Delete any object

Fill parameters

Method Description
get_fill_params(fill_id) Get all params as a dict
set_fill_params(fill_id, **params) Set params by keyword
get_image_filters(fill_id) Get a fill's image-filter chain
set_image_filters(fill_id, filters) Replace a fill's image-filter chain
add_image_filter(fill_id, filter_type, params, index) Add one image filter
remove_image_filter(fill_id, index) Remove one image filter

Visual

Method Description
set_source_image(image_path, group_id) Set source image for a group
set_caption(object_id, caption) Rename an object
set_visible(object_id, visible) Toggle visibility
set_layer_mask(layer_id, paths, mode) Set SVG vector mask
get_layer_mask(layer_id) Get layer mask data
transform_layer(layer_id, ...) Translate, rotate, scale
set_layer_warp(layer_id, ...) Perspective warp corners

Control

Method Description
render() Render all layers and wait
render_all() Trigger render (no wait)
wait_for_render(timeout) Poll until render completes
get_render_status() Returns RenderStatus
undo() / redo() Undo/redo last action
get_selection() Get selected objects
select_object(object_id) Select by ID

Export shortcuts

Method Returns
export_svg(path, dpi) Resolved Path
export_pdf(path, dpi) Resolved Path
export_png(path, dpi) Resolved Path
export_jpeg(path, dpi) Resolved Path
export_eps(path, dpi) Resolved Path
svg() SVG content as str
svg_parsed() svglab.Svg object (requires svglab)

Style engine

Function Description
extract_style(path) Parse a .lines file into a Style
apply_style(client, style, source_image, dpi, save_lines_to) Apply style to an image, return SVG string. Optionally save the intermediate .lines file.
interpolate_style(a, b, t) Blend two styles at ratio t in [0, 1], including matching image filters
interpolate_lines(start, end, output, t) Write one intermediate .lines file between compatible documents, interpolating matching numeric XML attributes and native colours
render_interpolation_video(start, end, output, frames, fps) Render a full .lines interpolation timeline to MP4
record_interpolation_screen(start, end, output, frames, fps, zoom_steps) Capture Vexy Lines window screenshots, optionally assembled to video
styles_compatible(a, b) Check if two styles can be interpolated
JobFolder(output_path, force) Persistent job folder for resumable exports

Types

DocumentInfo, InterpolationVideoResult, JobFolder, LayerNode, NewDocumentResult, RenderStatus, ScreenRecordingResult, Style

Dependencies

Full documentation

Read the docs for the complete API reference, style engine guide, MCP protocol specification, and more examples.

License

MIT

Release files for vexy-lines-apy 1.0.48

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vexy-lines-apy 1.0.48
File Size Uploaded
vexy_lines_apy-1.0.48.tar.gz 13.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for vexy-lines-apy 1.0.48
File Interpreter ABI Platform
vexy_lines_apy-1.0.48-py3-none-any.whl Python 3 none any Details

Total release size: 85.5 kB

Release files / vexy_lines_apy-1.0.48.tar.gz

Download URL vexy_lines_apy-1.0.48.tar.gz
Size 13.0 kB
Tags Source
SHA-256 checksum
How to use checksums
fe1cd5aa49d7a31c5adcaeef6e7a0dc427e6ab6a54531d148e50fe0c0d5b415c
BLAKE2b-256 checksum
How to use checksums
bc0007ae264ce0f5dcaf2139a9e13939d04bb0bd2bb9d1786fe7ac076f71a2b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / vexy_lines_apy-1.0.48-py3-none-any.whl

Download URL vexy_lines_apy-1.0.48-py3-none-any.whl
Size 72.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
65eecc96d2487b34ab50499132640c1e2d0ac1027db18ed5b4d238579243134f
BLAKE2b-256 checksum
How to use checksums
1063581cfd77d4167d205eb4590968e193ce9916463e0dbde13e106830933e52
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.18 {"installer":{"name":"uv","version":"0.12.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

1.0.48 This release

2 release files

1.0.46

2 release files

1.0.45

2 release files

1.0.44

2 release files

1.0.43

2 release files

1.0.42

2 release files

1.0.28

2 release files

1.0.27

2 release files

1.0.26

2 release files

1.0.25

2 release files

1.0.24

2 release files

1.0.23

2 release files

1.0.22

2 release files

1.0.21

2 release files

1.0.20

2 release files

1.0.19

2 release files

1.0.18

2 release files

1.0.17

2 release files

1.0.16

2 release files

1.0.15

2 release files

1.0.14

2 release files

1.0.13

2 release files

1.0.12

2 release files

1.0.11

2 release files

1.0.10

2 release files

1.0.9

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page