PranavandFredApps f5030432fc Data: Solver Options (#3087)
* Data: Solver Load/Save Model and Reset All

data.solverSaveModel writes a model (the sheet's saved model, or one
given as data.solver params) down a column of its sheet as formulas:
the objective and goal (=MAX(...), =MIN(...) or =cell=value), the
variable cells (=COUNT(...)), one =AND(relation) per constraint, which
shows TRUE while the constraint holds, and the method and its options
as an array constant. It refuses a range that overlaps the model's
cells or runs off the sheet.

data.solverLoadModel reads such a range (or reads down from its first
cell), checks the model and makes it the active sheet's model.
data.solverReset (Reset All) removes the active sheet's model. Each is
one undo step.

The Solver Parameters dialog has Reset All and Load/Save buttons; the
dialog can also be opened with fields that go over the saved model.

* Data: Solver Reset All also clears a model read from workbook-level names

A sheet's Solver model can come from workbook-level names, which every
sheet without a model of its own reads. Reset All removed only the
sheet-level names, so such a model stayed and the dialog showed it
again.

Removing the workbook-level names would change every other sheet that
reads them. Reset All instead leaves them in place and writes an empty
sheet-level solver_opt over them on the active sheet only; the result
says masked: true. saved_model now reads a sheet's own names when the
sheet has a solver_opt, and the workbook-level names only otherwise,
never a mix of both, and treats an empty solver_opt as no model. The
mask survives XLSX and is replaced when a model is saved on the sheet.

* Data: Solver Save Model clears the rest of a longer model saved at the same cell

Saving a model over a longer one saved at the same cell left the old
model's last rows on the sheet, so Load Model from that cell read the new
options row followed by stale constraint rows and refused the range.
Save Model now clears what is left of a model saved there before (only
when those cells hold a complete model written by Save Model, and never
the new model's own cells), keeping the cells' formatting, in the same
undo step. Load Model reading down from one cell also stops at the
options row, so formulas just below a saved model no longer break it.

* Data: Solver Load Model keeps the Evolutionary convergence and generations

Save Model writes Convergence and the generations without improvement in
its options row and Load Model reads them, but the sheet's saved model
(hidden names) did not hold them, so after Load Model, or any solve,
they fell back to their defaults. The saved model now keeps them for the
Evolutionary method: Convergence as solver_cvg, which means the same in
Excel, and the generations as gridcraft_solver_stall, because Excel's
solver_mni is a time in seconds. Saving a model again and Reset All
remove the GridCraft name with the solver_* names.

* Data: Solver Load Model refuses a range with a gap

Load Model from a range of several cells kept only the cells that hold a
formula, so the rows below a cell without one moved up. A constraint cell
overwritten by a constant gave a model without that constraint, and an
empty cell before the options row gave the default options, both without
an error. Load Model now refuses a range in which a cell before the last
formula holds no formula, and names that cell. Empty cells after the
model are still allowed.

* Data: Solver removes only its own names when it saves or resets a model

Saving a model (by a solve or Load Model) and Reset All removed every
name of the sheet that starts with solver_, so a user's own name such as
solver_budget was deleted with the model. They now remove only the
Solver's names: the ones Excel's Solver writes (solver_opt, solver_adj,
solver_lhs1, solver_rel1, solver_rhs1 and so on) and GridCraft's own.
The names are matched by name rather than by the hidden flag, so a model
whose names lost that flag is still replaced in full.

* Data: Solver Save Model refuses a place where the options cannot spill

The options row that Save Model writes is an array constant of eight
values, which spills into the seven cells to the right of its first
cell. Content in any of those cells blocked the spill and the options
cell showed #SPILL!. Save Model now checks the whole spill range before
it writes anything and refuses, naming the cell, when a cell there holds
content or another formula's spilled values or is a cell of the model,
when merged cells or a table meet the row (a dynamic array cannot spill
into a table), or when the range runs past the last column. It also
refuses a place where the model's column would cover another formula's
spilled values, which that formula would lose to #SPILL!. The options of
a model saved at the same cell before may be replaced, as before.

* Data: Solver Reset All and Load Model drop the old model's options

Reset All cleared the model fields of the Solver Parameters form but
kept the Evolutionary options (Convergence, Mutation Rate, Population
Size, Random Seed, generations without improvement and Require Bounds),
and Load Model kept any of them that the loaded model omits, such as all
of them for a GRG Nonlinear or Simplex LP model. A new Evolutionary model
then solved with the old options, for example with Require Bounds off.
Both now remove the model's options from the form first (one list of
their keys), so an option the model doesn't set takes its default.

* Data: Solver Save Model asks before it replaces data

Save Model wrote its formulas over whatever the model range held.
It is now refused, with the sheet unchanged, when a cell of the
range holds a value or a formula (a model saved there before
included), unless `overwrite: true` is passed. The message names
the first such cell and carries the same "already holds data"
phrase as Data Analysis, so the Solver Parameters dialog asks
"Replace it with the model?" with Replace and Don't Replace. The
question belongs to the range it asked about: editing the range,
Load or Reset All drops it. The check runs after the spill checks,
so the question is asked only when replacing would succeed. A save
remains one undo step.

Tests: the engine test refuses a value, a formula and an earlier
model, accepts only a true boolean, and undoes and redoes the
replacing save in one step; the dialog test covers Don't Replace,
an edited range and Replace. Both fail without the change.

* Data: Solver Load Model and Reset All tests for limits and undo

Tests for behaviour already in place: reading down from one cell of
a column of 5,000 formulas stops after the most rows a model takes,
a range larger than a model is refused before any cell is read, and
malformed or hostile cells and ranges (unbalanced brackets, an
overflowing number, an unknown sheet, 10,000 nested brackets, a
non-text `from`) each give an error and leave no model. Undoing
Reset All brings the model back with its options (the population
size).

* Data: Solver Load Model refuses a model without its options row

Load Model from one cell read down to the first cell without a
formula, and a range dropped its trailing cells without formulas.
A constraint cleared in the middle of a saved model, or its options
row cleared or replaced by a constant, therefore left a prefix of
the model, which was loaded as the whole model with default options
and replaced the sheet's model. Every load now requires the model's
last row to be the options row ({...}) that Save Model writes last;
otherwise it is refused, naming the cell without a formula when
reading down from one cell, and the sheet's model stays as it was.

The test clears a middle constraint, clears the options row and
replaces it by a constant, loads from the first cell and as two
ranges, and checks after each refusal that the old model (three
constraints, Simplex LP) is unchanged. It fails without the change.

* Data: Solver Options

The Solver Parameters dialog's Options button shows the Solver Options
in the same window: Max Evaluations and Integer Optimality for all
methods, and Convergence, Mutation Rate, Population Size, Random Seed,
Maximum Generations without Improvement and Require Bounds on Variables
for Evolutionary. OK keeps the changes for the next solve; Cancel
restores them.

The evaluation limit and Integer Optimality are now part of the model:
they are saved in the hidden names (solver_itr, which counts evaluations
in place of iterations, and solver_tol) and in the options row of Save
Model. Both accept numbers or text, as the other options do.

* Data: Solver keeps its own limits out of Excel's Solver names

The evaluation limit was saved as solver_itr. Excel uses that name for
its iteration limit (100 by default), so a workbook saved by Excel would
give GridCraft 100 evaluations and stop its search early. GridCraft now
saves the evaluation limit as gridcraft_solver_evals, which Excel
ignores, and no longer reads solver_itr. Saving a model again and Reset
All remove it with the other model names. Integer Optimality
(solver_tol) keeps Excel's name, as its meaning is the same.

* Data: Solver Reset All also resets the Solver Options

Reset All removes the model's options from the Solver Parameters form,
the Solver Options fields (the evaluation limit, Integer Optimality and
the Evolutionary options) and Require Bounds, so the next Solve uses the
defaults. It now also removes the copy of the options that Options keeps
for Cancel. A test checks that the options are gone after Reset All and
that Options then shows the defaults.

* Data: Solver reads Integer Optimality with a percent sign as percent

Integer Optimality is given in percent, but text such as "5%" was read
by the number parser as 0.05 and then divided by 100 again, so the
solver used 0.05 % instead of 5 %. A trailing percent sign is now
dropped before the number is read, so "5", "5%" and 5 all mean 5 %.

* Data: Solver Options closes with Escape back to the Solver Parameters

Escape in the Solver Options view went to the shared dialog handler,
which closed the whole Solver dialog: the options were not restored and
parameter edits made before opening Options were lost. Escape (and
closing the window) in Solver Options now does what Cancel does: it
restores the options and returns to the Solver Parameters. Escape in the
parameters still closes the dialog.

* Data: Solver keeps the Evolutionary options when another method solves

Solver Options sets the Evolutionary options whatever the solving
method, but the saved model and the model in data.solver's result held
them only for the Evolutionary method. A GRG Nonlinear or Simplex LP
solve (which saves the model by default) dropped them, and switching
back to Evolutionary brought back the defaults. They are now saved and
returned for every method. Two tests that expected them to be absent
for other methods now check their values.

* Data: Solver Options keeps its OK and Cancel row at button height

The Solver Options' OK and Cancel row was a right-to-left layout placed
straight in the window, which takes all the height it is offered, so
the buttons sat well below the last option and the window was taller
than its content. The row is now wrapped in a horizontal row as tall as
the buttons, as the other form dialogs do (ok_cancel).

The window's height now changes when it switches between the parameters
and the options, and the window re-centres over the next frames, so the
test that switches back and forth lets a few frames pass after each
switch before it clicks.

* Data: Solver Parameters keeps its Solve and Close row at button height

The Solve and Close row was a right-to-left layout placed straight in
the window. The window keeps its size when its content gets shorter, as
it does when the Load/Save area or a note is hidden again, and that
layout then filled the space left over, so Solve moved further below
the last row. The row is now a horizontal row as tall as the buttons,
as ok_cancel and the Solver Options do.

* Data: Solver dialog opened in its options sets them up as the Options button does

Opening the Solver dialog straight in the Solver Options (optionsView:
true) only changed the title. It skipped what the Options button does:
filling each option the form lacks with its default and keeping the
current values for Cancel. With no saved model the fields were blank,
and Cancel or Escape found nothing to restore, so the edits stayed and
the next Solve used them. The button and the dialog now share one
function for this.

* Data: Solver reads Integer Optimality back without floating-point noise

Integer Optimality is stored as a fraction, and the product with 100 is not exact for many percents (0.07 * 100 is 7.000000000000001). The percent is now rounded to 1E-10 % wherever it is read back: the saved model, the solve's model params and Save Model's options row.

* Data: Solver reads whole-number options back as integers

The model's numeric options were returned as floating-point JSON, so after a solve the Solver Options showed 20000.0, 100.0, 0.0 and 50.0. Values read from the hidden names, and Integer Optimality in the solve's result, are now JSON integers where they are whole, and the dialog shows 20000, 100, 0 and 50.

* Data: Solver test checks the model saved by the second solve

The test of Excel's iteration and time limits ignored the result of
its second `data.solver` call and checked only names the first call
had already created. It now reads the saved model afterwards and
checks the values the second call changed (Simplex LP and an
evaluation limit of 700). The call itself still fails, as Simplex LP
refuses the nonlinear model, after the model is saved.

* Data: Solver Load Model refuses an options row cut short

The options row of a saved model was read leniently: a missing value
or one that isn't a number took its default, and values after the
sixteenth were not read at all. A row cut short or edited by hand,
such as ={1}, therefore loaded the model with default options in
place of the saved ones (here: GRG Nonlinear in place of Simplex
LP). The row must now hold at least the eight numbers Save Model
writes (method, non-negative, population size, mutation rate, random
seed, require bounds, convergence, generations without improvement),
and every value in it, however many, must be a number; otherwise
Load Model is refused and the sheet's model stays as it was. Only
the first sixteen values are kept. More numbers than eight are still
read, so a row with options a later version adds loads too.

The test loads rows of one value, seven values, a text value among
the eight, after them and after the sixteenth, and a TRUE, from the
first cell and as a range, checking the old model after each
refusal, and a row of ten numbers, which loads. It fails without the
change.

---------

Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-01 20:23:08 +01:00
2026-10-26 14:13:04 -06:00
2026-11-01 12:18:01 -05:00
2026-11-01 20:23:08 +01:00
2026-11-01 20:23:08 +01:00
2026-11-01 13:57:31 -05:00
2026-11-01 13:57:31 -05:00
2026-10-25 14:55:00 -04:00
2026-10-11 15:13:02 -03:00

ArtCraft

GridCraft icon: a spreadsheet page on a green tile

GridCraft

Spreadsheets and data; an open-source, high-performance modern spreadsheet application, built in pure Rust.

A fast, open-source, clean-room take on modern spreadsheet workflows. It runs natively on macOS, Windows, Linux and BSD, and in the browser via WebAssembly.
By the ArtCraft team.

Written in Rust Runs on macOS, Windows, Linux, BSD and the web License: MIT OR Apache-2.0 Agent-drivable over MCP
Scanned by SonarCloud Reviewed by CodeRabbit

Join the ArtCraft community on Discord

GridCraft on getartcraft.com · ArtCraft · All Crafting Apps


GridCraft showing a quarterly sales dashboard: a styled table with banded rows, filter buttons, a totals row, data bars, arrow icons and sparklines, next to a clustered column chart and a pie chart
Quarterly Sales Dashboard: a table with a totals row, conditional formatting, sparklines and two live charts — built entirely from GridCraft commands (File → New → Sample).

Note

ArtCraft is a community of artists from all walks of life. Painters, photographers, filmmakers, illustrators, designers, animators, hobbyists, and people who picked up a pencil last week. If you make things, you're one of us. Come say hi on Discord.

A look around · Why GridCraft · Quick start · For agents · Architecture · Roadmap · The Crafting Apps · License and credits

A look around

A household budget with accounting number formats, red highlights for overspent categories, a green-yellow-red colour scale on the percent-used column, a totals row with a double border, and a horizontal bar chart comparing budget with actual

Formatting. Accounting formats, cell styles, conditional rules and colour scales, frozen headers and a bar chart.

A gradebook table with averages and letter grades computed with IFS, green highlights on A grades and data bars, with the Formulas ribbon tab open showing the function library

Formulas. 500+ functions, dynamic arrays, LET and LAMBDA, structured table references.

The sales dashboard in dark mode with the Insert ribbon tab open, showing Pivot Table, Table, Pictures, Shapes, chart, sparkline, link, comment, text box and symbol buttons

Dark mode and the Insert tab: tables, charts, sparklines, pictures, shapes, links and comments.

A pivot table summarising revenue by region and product with a Channel report filter, grand totals and currency formatting, with the Pivot Table Fields pane open on the right showing ticked fields and the Filters, Columns, Rows and Values areas

Pivot tables. Field list, filters, layouts, date grouping and show-values-as, saved to and read from XLSX.

The sales dashboard with the column chart selected: resize handles on the chart, its source data outlined in the table, the Chart Design tab open and the Format Chart Area pane on the right

Charts. Seventeen chart types, Chart Design tab and a Format pane; selecting a chart outlines its source data.

The household budget in Page Break Preview: the print area outlined in blue with a dashed page break, Page 1 and Page 2 watermarks, and the area outside the print range greyed out

Page Break Preview, print settings, and PDF export and printing.

Why GridCraft

  • Familiar. Ribbon, formula bar, Name Box, sheet tabs, keyboard shortcuts, fill handle, point-mode formula entry with coloured references, Format Cells, Paste Special, conditional formatting, tables, charts and more. Everything is right where you expect it.
  • Compatible. XLSX is the native format: styles, themes, formulas (including dynamic arrays), tables, conditional formats, validation, comments, hyperlinks, charts, pictures, sparklines, pivot tables and print settings round-trip. CSV and TSV too. Legacy 97-2003 .xls workbooks open with their values, formulas and number formats (formatting and objects not yet). XLSB worksheet data can be imported, using saved values instead of formulas. ODS worksheet data can be imported, using saved values instead of formulas. Static pictures can live inside cells, fitting their size and moving with the data.
  • Capable. A dependency-graph calculation engine with dynamic arrays and spilling, 500+ worksheet functions plus LET, LAMBDA, MAP, REDUCE, SCAN, BYROW, BYCOL and MAKEARRAY, structured table references, a comprehensive number-format language, sort and AutoFilter, Flash Fill, data validation, outlining and subtotals.
  • Fast. Copy-on-write workbooks (undo snapshots are nearly free), incremental recalculation, and a virtualised grid that only lays out what's on screen.
  • Agent-native. Every ribbon button, menu item, dialog, keystroke and mouse gesture is a command that agents can run over a JSON control channel, an MCP server, or the CLI.
  • Everywhere. One Rust codebase for desktop and the web. No subscription, no licence server, no telemetry.

Quick start

cargo run --release -p gridcraft                              # desktop app
cargo run --release -p gridcraft -- --sample sales            # open a sample (sales, budget, grades)
cargo run --release -p gridcraft -- book.xlsx                 # open a workbook
cargo run --release -p gridcraft -- --sample sales --control 7979   # + JSON control channel
cargo xtask ci                                                 # fmt, clippy, tests, assets, layering, wasm

Choose Español under View → Interface language for Spanish formula names, decimal commas, and semicolon arguments. Workbooks, clipboard exchange, and programmatic APIs retain canonical English syntax.

Web

cd apps/gridcraft-web && trunk build --release     # → dist/web (serve it with any static server)
cd apps/gridcraft-web && trunk serve --release     # http://127.0.0.1:8771  (?sample=sales opens a sample)

You need trunk and the wasm32-unknown-unknown target. Open uses the browser's file picker (dropping files works too) and Save downloads the workbook.

Ribbon access keys

Press and release left Alt on Windows/Linux/BSD, or press F10 on any platform, then type a sequence below one key at a time. Keytips appear on the supported Home controls and menu items. On macOS, use F10 (Fn+F10 if required by your keyboard); Option remains available for entering accented characters.

Sequence after Alt/F10 Action
H A L / H A C / H A R Align left / center / right
H V S or legacy E S Open Paste Special
H O I or legacy O C A AutoFit selected columns

In Paste Special, T/V/F/C select formats/values/formulas/comments, and E toggles Transpose. Enter applies the selected options; Escape cancels the dialog. These letters also work with Alt held on Windows/Linux/BSD.

Escape backs out one keytip level; Alt/F10 again exits keytips. Clicking, scrolling, or switching windows cancels navigation. Access keys do not start while editing text or using another dialog. This is initial support for these Home and legacy paths; other ribbon commands and full mouse-free navigation remain to be implemented. Browsers or desktop environments may reserve Alt/F10 for their own menus.

Logs

The desktop app writes its log to standard error and to gridcraft.log in the logs folder next to its settings: ~/.config/gridcraft/logs on Linux and BSD ($XDG_CONFIG_HOME/gridcraft/logs when set), ~/Library/Application Support/GridCraft/logs on macOS and %APPDATA%\GridCraft\logs on Windows. Each start moves the previous log to gridcraft.1.log and that one to gridcraft.2.log, so the log of a run that crashed survives the next start; attach them to a bug report. A log file stops growing at 16 MiB. By default GridCraft's own crates log at info and everything else at warn; RUST_LOG replaces that with env_logger-style directives, e.g. RUST_LOG=debug or RUST_LOG=warn,gridcraft_engine=debug (a trailing * matches a prefix: gridcraft*=debug). Runs with GRIDCRAFT_NO_PREFS set (no saved settings) log to standard error only.

For agents: MCP, CLI and the control channel

claude mcp add gridcraft -- gridcraft-cli mcp                 # headless MCP server
gridcraft-cli mcp --connect 7979                               # MCP bridged to a running window
gridcraft-cli eval '=XLOOKUP("b",{"a","b"},{1,2})'             # → 2
gridcraft-cli run --sample budget --cmd 'home.bold={"range":"B4:F4"}' --out budget.xlsx
gridcraft-cli cat budget.xlsx --range B4:F15                   # aligned text table
gridcraft-cli commands --search chart                          # every command and its params

The MCP server offers tools such as read_range, write_range, set_cell, evaluate_formula, format_range, insert_chart, create_table, sort_range, filter and execute_command (which reaches every one of GridCraft's commands). The desktop app's control channel adds real pointer and keyboard input, dialogs and screenshots. See docs/mcp.md, docs/cli.md and docs/control-protocol.md.

Architecture

GridCraft is an engine-first Cargo workspace with enforced layering (cargo xtask layers). The egui frontend is a separate crate, so the UI can be swapped without touching the engine.

Layer Crates
L0 core (addresses, values, errors, dates, input parsing) · numfmt (number format codes)
L1 formula (lexer, parser, printer, reference adjustment) · functions (worksheet function library)
L2 model (workbook, sheets, copy-on-write cells, styles, tables, charts…) · calc (dependency graph, evaluator, dynamic arrays) · xlsx (XLSX, CSV, plus XLSB and ODS data import)
L3 chart (toolkit-free chart layout and rendering)
L5 engine (session, commands, history, clipboard, fill, sort, filter, file I/O)
L6 ui-egui (spreadsheet UI, control channel) · mcp (MCP server)
L7 apps/gridcraft, apps/gridcraft-cli, apps/gridcraft-web
  • Contributor and agent rules (clean-room, asset policy, never-crash, quality gates): AGENTS.md
  • Bundled assets: each one is listed with its licence in ATTRIBUTION.md
  • Releases: signed macOS, Windows, Linux, BSD and web builds; see docs/releasing.md

Roadmap

GridCraft is in alpha: the core workflow works end to end, but depth, fidelity and file compatibility are still rough. It covers 89% of standard ribbon commands in our catalog (docs/parity-checklist.md) and 513 standard worksheet functions (docs/function-parity.md); this is a parity inventory, not a count of working implementations. Weighted by what spreadsheet users rely on, we estimate it is about 50% ready for real work. Next up: XLSX fidelity on real-world files, very large workbooks and multi-threaded recalc, chart depth, text in every script, and .xls import. Stage, numbers and estimates are in ROADMAP.md; the ranked work list is docs/gaps.md.

Downloads

Download GridCraft from GitHub: the latest release has every build listed below, and all releases has earlier versions and their notes. <ver> in the file names is the version number, and SHA256SUMS.txt lists a checksum for every file.

Windows

Build Installer Portable
x64 (64-bit Intel/AMD) gridcraft-<ver>-windows-x64.msi gridcraft-<ver>-windows-x64-portable.zip
arm64 (Snapdragon and other ARM PCs) gridcraft-<ver>-windows-arm64.msi gridcraft-<ver>-windows-arm64-portable.zip
x86 (32-bit) gridcraft-<ver>-windows-x86.msi gridcraft-<ver>-windows-x86-portable.zip

Installers and executables are code-signed. The MSI installer offers an optional desktop shortcut (unchecked on a new installation).

If the app doesn't open on Windows: the desktop app initializes only DirectX 12 by default. Letting wgpu also create an OpenGL instance can crash some graphics drivers (AMD's atio6axx.dll) before the window appears, so the app would flash in Task Manager and quit. WGPU_BACKEND overrides the default for troubleshooting (for example dx12 or vulkan). In PowerShell, from the folder containing the executable:

$env:WGPU_BACKEND = "vulkan"
& .\gridcraft.exe
Remove-Item Env:WGPU_BACKEND                     # restore the default for later launches

An explicit gl override can bring the driver crash back on affected systems, and vulkan can bring back a crash in some Intel UHD Graphics drivers (igvk64.dll, #120). The macOS, Linux and web backend defaults are unchanged.

If the app is slow on an older Windows PC, or DirectX 12 can't start: when DirectX 12 finds no graphics card with a driver for it, it only offers the Windows-provided software renderer, which draws every frame on the processor. In that case GridCraft uses OpenGL instead, without setting anything; if the first renderer fails to start, it tries the other one once. The log file records the choice (lines starting with graphics:). WGPU_BACKEND still overrides it (and then nothing else is tried), e.g. $env:WGPU_BACKEND = "gl" or "dx12".

DirectX 12 shaders are compiled with FXC, which is part of Windows, so no dxcompiler.dll or dxil.dll is needed, and a copy another program put on PATH can no longer stop the app at start ("Parent device is lost", #339). $env:WGPU_DX12_COMPILER = "dxc" (or "auto") selects wgpu's DXC handling again for troubleshooting.

macOS

Build File Notes
App, universal (Apple silicon + Intel) gridcraft-<ver>-macos-universal.dmg Signed and notarized
Command-line tool, universal gridcraft-cli-<ver>-macos-universal.zip Signed and notarized

Linux

Format x86_64 aarch64 (ARM64) Notes
AppImage gridcraft-<ver>-linux-x86_64.AppImage gridcraft-<ver>-linux-aarch64.AppImage Runs anywhere; updates itself with AppImageUpdate (.zsync files)
Flatpak gridcraft-<ver>-linux-x86_64.flatpak gridcraft-<ver>-linux-aarch64.flatpak Sandboxed; flatpak install --user <file>
Debian/Ubuntu gridcraft-<ver>-linux-x86_64.deb gridcraft-<ver>-linux-aarch64.deb
Fedora/RHEL/openSUSE gridcraft-<ver>-linux-x86_64.rpm gridcraft-<ver>-linux-aarch64.rpm
Tarball gridcraft-<ver>-linux-x86_64.tar.gz gridcraft-<ver>-linux-aarch64.tar.gz Unpack anywhere

FreeBSD

Build File
x86_64 gridcraft-<ver>-freebsd-x86_64.tar.gz

Web (WebAssembly)

Build File Notes
Static site gridcraft-web-<ver>.zip Runs in a modern browser; host it on any static server

The Crafting Apps

GridCraft is one of the Crafting Apps: free, open-source creative tools from the ArtCraft team, each written from scratch in Rust and each able to stand on its own.

App What it's for Code Learn more
PhotoCraft Image editing: layers, masks, type and real PSD files GitHub Website
VectorCraft Vector illustration GitHub Website
FilmCraft Video editing, color and sound GitHub Website
LightCraft Photo library and raw development GitHub Website
PdfCraft Reading, organizing and protecting PDFs GitHub Website
EffectCraft Motion graphics and visual effects GitHub Website
DesignCraft Page layout and publishing GitHub Website
FigCraft Interface design and prototyping GitHub Website
WordCraft Word processing and documents GitHub Website
SoundCraft Audio recording and editing GitHub Website
DeckCraft Presentations and slide decks GitHub Website
CADCraft Computer-aided design GitHub Website
GridCraft Spreadsheets and data GitHub Website
TextureCraft 3D texture painting GitHub Website
Craft Anything See how any software works, then build your own GitHub Website
SolidCraft Parametric 3D CAD by Tangency Labs (community app) GitHub

And ArtCraft itself, our AI image and video studio for artists who want real control.


Join the ArtCraft community on Discord

Come make things with us

Our Discord is where artists of every kind hang out: people who paint, shoot, draw, cut film, set type, and people still figuring out what they like to make. Share what you're working on, ask for help, tell us what's broken, or tell us what you wish these tools could do. Whatever your medium and however long you've been at it, you're welcome here.

discord.gg/artcraft · getartcraft.com · The Crafting Apps · GridCraft

License and credits

GridCraft is dual-licensed under MIT or Apache-2.0, at your option. Copyright (c) 2026 ArtCraft Team and the GridCraft contributors. Required notices are in NOTICE.

Bundled fonts, icons, images and other assets keep their own open licenses; each one is listed with its author, source and license in ATTRIBUTION.md.

All UI icons are drawn in code and are original; the sample workbooks and every screenshot in this README were made with GridCraft itself. GridCraft bundles no fonts: it uses the fonts installed on your system.

The ArtCraft name, wordmark and logos in docs/brand/ are trademarks of the ArtCraft Team and are not covered by this license. They may be used only unmodified, and only as part of this repository and GridCraft, under docs/brand/LICENSE-brand.txt. Forks and modified versions must remove them.


ArtCraft
Made by the ArtCraft team and community.

S
Description
No description provided
Readme
78 MiB
Languages
Rust 94.3%
RenderScript 4.6%
PowerShell 0.6%
Shell 0.4%