ArtCraft: 14 vrije creatieve programma’s, zoals Photoshop, Premiere, Word of AutoCAD

🌐 Español · English · Português · Français · Italiano · Deutsch · Nederlands · Polski · Русский · Українська · Türkçe · Ελληνικά · العربية · فارسی · עברית · हिन्दी · বাংলা · தமிழ் · Bahasa Indonesia · Tiếng Việt · ไทย · 中文 · 日本語 · 한국어 · Kiswahili

Het verhaal: één opzeggingsboete te veel

Het verhaal dat deze weken rondgaat op fora en sociale media: ArtCraft is uit woede geboren, de maker zou „opgelicht” zijn. Achter het project staat Brandon Thomas, een software-engineer uit Atlanta (VS) met vijftien jaar ervaring, die op Reddit schreef als u/ai_art_is_art. Het woord „oplichting” komt van het publiek; hij vertelt dat Adobe hem de opzeggingskosten van zijn abonnement aanrekende.

„Ze rekenden me meerdere keren de ‘opzeggingskosten’ aan en sindsdien haat ik ze”, schreef hij op Reddit. Op Hacker News zei hij dat hij te vaak in dat „dark pattern” was getrapt: de boete als je een maandelijks betaald jaarabonnement vroegtijdig stopt. Het is geen losse klacht: in juni 2024 klaagde het Amerikaanse ministerie van Justitie Adobe aan omdat het die kosten verborg en opzeggen moeilijk maakte. Adobe stelt dat zijn voorwaarden transparant zijn.

Zijn antwoord: de programma’s opnieuw bouwen en weggeven. Met hulp van Claude, de AI van Anthropic, en de taal Rust publiceerde hij tussen eind september en begin oktober 2026 de eerste zeven apps op GitHub — het equivalent van Photoshop, Illustrator, Premiere, Lightroom, After Effects, InDesign en Acrobat — en voegde er binnen enkele weken Word, PowerPoint, Excel, AutoCAD, Pro Tools en Figma aan toe. Hij zegt dat het „clean-room”-herimplementaties zijn, gebouwd op de openbare specificaties van de bestandsformaten, zonder andermans code.

Zijn samenvatting, „software is voorbij”, ging de wereld rond: als één persoon met AI in weken kan herbouwen wat decennia kostte, krijgt betaalde software het zwaar. Er is twijfel: professor Andrés Guadamuz van de University of Sussex wijst erop dat nog niet vaststaat of dat „clean-room”-proces een toets doorstaat, en hoeveel code hij en hoeveel de AI schreef. Thomas houdt vol dat het „geen eendagsvlieg is die doodgaat”, en voorlopig geeft het bijna dagelijkse tempo van nieuwe versies hem gelijk.

ArtCraft is een opensourceproject (licentie MIT of Apache-2.0) van het team storytold dat de programma’s waarmee we dagelijks creëren vanaf nul herschrijft in Rust. Het zijn native, lichte programma’s zonder abonnement die nabootsen hoe de bekendste commerciële programma’s werken, zonder hun code te kopiëren. Ze draaien op Windows, macOS, Linux en FreeBSD, veel ook in de browser, en er verschijnen bijna elke week nieuwe versies. De genoemde merknamen zijn alleen ter oriëntatie: deze programma’s hebben niets met die merken te maken.

De programma’s, één voor één

ArtCraft Launcher v0.8.1

Begin hier. Het installeert alle andere: toont de hele catalogus, installeert elke app met één klik in de juiste versie voor je computer, controleert of het bestand niet beschadigd is en meldt updates. Eén pakket met alles bestaat niet, maar deze launcher komt het dichtst in de buurt.

PhotoCraft v0.16.0

De beeldbewerker in de geest van Photoshop: lagen, selecties, penselen, aanpassingen en retoucheren. Het is het populairste programma van het project op GitHub.

LightCraft v0.14.0

Fotobibliotheek en niet-destructieve RAW-ontwikkeling, à la Lightroom: je ordent je foto’s en past belichting, kleur en uitsnede aan zonder ooit het origineel te wijzigen.

VectorCraft v0.17.0

Vectorillustratie zoals in Illustrator: curves, vormen, lijnen en tekst die zonder kwaliteitsverlies vergroot kunnen worden. Voor logo’s, iconen en posters.

FilmCraft v0.13.0

Niet-lineaire videobewerking, vergelijkbaar met Premiere Pro: tijdlijn met meerdere sporen, knippen, kleurcorrectie en geluid.

EffectCraft v0.17.0

Motion graphics, compositing en visuele effecten in de lijn van After Effects: titels, keyframe-animatie en lagen die je combineert.

SoundCraft v0.13.1

Audiowerkstation om op te nemen, te bewerken en te mixen, geïnspireerd op Pro Tools: meerdere sporen, knippen, effecten en de eindmix.

DesignCraft v0.13.0

Opmaak en publicatie in de stijl van InDesign: tijdschriften, folders en boeken met pagina’s, kolommen, tekststijlen en afbeeldingen.

FigCraft v0.11.2

Interfaceontwerp en prototypen, zoals Figma: schermen voor apps en websites, herbruikbare componenten en schetsen die tonen hoe iets gaat werken voordat het gebouwd is.

PdfCraft v0.14.0

Voor het lezen, ordenen en beveiligen van pdf’s, in de lijn van Acrobat: openen, annoteren, pagina’s herschikken en beveiligde documenten opslaan.

WordCraft v0.11.0

Tekstverwerker vergelijkbaar met Word, voor brieven, rapporten en documenten met stijlen, tabellen en afbeeldingen.

DeckCraft v0.11.1

Presentaties en dia’s in de stijl van PowerPoint: dia’s met tekst, afbeeldingen en vormen om schermvullend te presenteren.

GridCraft v0.12.1

Spreadsheet zoals Excel: formules, gegevenstabellen, grafieken en gegevens sorteren of filteren.

CADCraft v0.13.0

Computerondersteund ontwerpen en technisch tekenen, in de lijn van AutoCAD: plattegronden met exacte maten, lagen en maatvoering.

ArtCraft v0.41.0

De app waar het project naar genoemd is, en de enige die apart staat: een studio om met kunstmatige intelligentie beelden en video te maken, bedoeld voor kunstenaars, ontwerpers en filmmakers. Voorlopig alleen voor Windows en Mac.

Bewaar ze allemaal: broncode en programmabestanden

Wie graag van alles een kopie heeft (voor het geval een project ooit verdwijnt, of om zonder internet te installeren): dit Linux-script downloadt de broncode van elk programma en alle programmabestanden van de nieuwste versie, gesorteerd in mappen per programma en per systeem (Windows, macOS, Linux, FreeBSD en web). Uitpakken en uitvoeren; het argument is de doelmap, en met PLATFORMS en EXCLUDE kies je wat je downloadt. (Het commentaar is in het Spaans.)

⬇ Script downloaden (artcraft-mirror.zip)

chmod +x artcraft-mirror.sh
./artcraft-mirror.sh ~/artcraft

PLATFORMS="windows linux" EXCLUDE='riscv64|aarch64' ./artcraft-mirror.sh ~/artcraft
  • Onderbreken mag: stopt het, start het dan opnieuw en het gaat verder waar het gebleven was.
  • Haalt alleen het nieuwe op: bij een nieuwe versie maakt het een map aan en laat de oudere met rust.
  • Controleert alles met de SHA-256-sommen die elke versie publiceert.
  • Neemt veel ruimte in: alle platforms samen zijn ongeveer 24 GB per versie; heb je er maar een paar nodig, filter dan.
Volledig script tonen
#!/usr/bin/env bash
# artcraft-mirror.sh — espejo local de las Craft Apps de ArtCraft (github.com/storytold)
#
# Estructura que genera:
#   <DEST>/<herramienta>/code/<rama>-<herramienta>-AAAAMMDD.zip   (+ .sha con el commit)
#   <DEST>/<herramienta>/release-<versión>/{windows,macos,linux,freebsd,web,otros}/...
#   <DEST>/<herramienta>/release-<versión>/SHA256SUMS.txt
#
# - Reanudable: las descargas van a *.part y continúan con Range (curl -C -).
#   Una release se da por terminada sólo cuando todo se verificó contra SHA256SUMS
#   (queda el marcador .complete). Si se corta, se vuelve a ejecutar y sigue.
# - Incremental: sólo mira la última release de cada herramienta; las carpetas
#   release-* anteriores y los zip de código de días anteriores no se tocan.
# - El código fuente se baja sólo si el commit de la rama principal cambió.
#
# Uso:
#   ./artcraft-mirror.sh [DEST]           (DEST por defecto: carpeta del script)
# Variables opcionales:
#   GITHUB_TOKEN=ghp_...                  sube el límite de la API de 60 a 5000 llamadas/h
#   PLATFORMS="windows linux macos"       sólo estas plataformas (por defecto todas)
#   EXCLUDE='riscv64|aarch64|flatpak'     regex de nombres de archivo a omitir
#   TOOLS="photocraft cadcraft"           sólo estas herramientas
#   EXTRA_TOOLS="anicraft"                añadir repos de storytold no incluidos en el catálogo
#   SKIP_CODE=1 / SKIP_RELEASES=1

set -uo pipefail

OWNER=storytold
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
DEST=${1:-$SCRIPT_DIR}
PLATFORMS=${PLATFORMS:-"windows macos linux freebsd web otros"}
EXCLUDE=${EXCLUDE:-}
TODAY=$(date +%Y%m%d)

# Catálogo de respaldo por si no se puede leer el del launcher
FALLBACK_TOOLS="photocraft vectorcraft filmcraft lightcraft pdfcraft effectcraft designcraft
figcraft wordcraft soundcraft deckcraft cadcraft gridcraft"
# Fuera del catálogo del launcher pero con releases propias
ALWAYS_TOOLS="craft-launcher artcraft"

for bin in curl jq git sha256sum flock; do
    command -v "$bin" >/dev/null || { echo "Falta '$bin'" >&2; exit 1; }
done

mkdir -p "$DEST"
exec 9>"$DEST/.artcraft-mirror.lock"
flock -n 9 || { echo "Ya hay otra ejecución en curso en $DEST" >&2; exit 1; }

log()  { printf '[%s] %s\n' "$(date +%H:%M:%S)" "$*"; }
warn() { printf '[%s] AVISO: %s\n' "$(date +%H:%M:%S)" "$*" >&2; }

api() {
    local auth=()
    [[ -n ${GITHUB_TOKEN:-} ]] && auth=(-H "Authorization: Bearer $GITHUB_TOKEN")
    curl -fsSL --retry 3 -H "Accept: application/vnd.github+json" "${auth[@]}" \
        "https://api.github.com/$1"
}

# Descarga: $1 url, $2 destino final, $3 tamaño esperado.
# Con tamaño conocido continúa el .part (Range); sin él (zip de código, generado
# al vuelo y sin Range) empieza de cero.
fetch() {
    local url=$1 out=$2 size=${3:-} part="$2.part" have resume=()
    mkdir -p "$(dirname "$out")"
    if [[ -n $size && -f $part ]]; then
        have=$(stat -c %s "$part")
        if (( have == size )); then mv -f "$part" "$out"; return 0; fi
        if (( have > size )); then rm -f "$part"; fi
        resume=(-C -)
    else
        rm -f "$part"
    fi
    curl -fL --retry 5 --retry-delay 5 --retry-all-errors "${resume[@]}" \
        --progress-bar -o "$part" "$url" || return 1
    mv -f "$part" "$out"
}

platform_of() {
    case $1 in
        SHA256SUMS*)                              echo . ;;
        *windows*|*.msi|*.exe)                    echo windows ;;
        *macos*|*.dmg|*.app.tar.gz|*universal*)   echo macos ;;
        *freebsd*)                                echo freebsd ;;
        *linux*|*.AppImage*|*.deb|*.rpm|*.flatpak) echo linux ;;
        *-web-*)                                  echo web ;;
        *)                                        echo otros ;;
    esac
}

wanted() {
    local name=$1 plat=$2
    [[ $plat == . ]] && return 0
    [[ " $PLATFORMS " == *" $plat "* ]] || return 1
    [[ -n $EXCLUDE && $name =~ $EXCLUDE ]] && return 1
    return 0
}

tool_list() {
    if [[ -n ${TOOLS:-} ]]; then echo $TOOLS; return; fi
    local cat
    cat=$(curl -fsSL "https://raw.githubusercontent.com/$OWNER/craft-launcher/main/crates/core/src/catalog.rs" 2>/dev/null \
          | grep -oE "\"$OWNER/[a-z0-9-]+\"" | tr -d '"' | cut -d/ -f2 | grep -v '^craft-launcher$' | sort -u)
    [[ -z $cat ]] && { warn "no pude leer el catálogo del launcher; uso la lista interna"; cat=$FALLBACK_TOOLS; }
    echo $cat $ALWAYS_TOOLS ${EXTRA_TOOLS:-} | tr ' ' '\n' | awk 'NF && !seen[$0]++'
}

mirror_code() {
    local tool=$1 dir="$DEST/$1/code" head branch sha last
    head=$(git ls-remote --symref "https://github.com/$OWNER/$tool" HEAD 2>/dev/null) \
        || { warn "$tool: no pude consultar el repositorio"; return 1; }
    branch=$(awk '/^ref:/ {sub("refs/heads/","",$2); print $2}' <<<"$head")
    sha=$(awk '$2=="HEAD" && $1!="ref:" {print $1}' <<<"$head")
    mkdir -p "$dir"

    last=$(ls -1 "$dir"/*.zip.sha 2>/dev/null | sort | tail -1)
    if [[ -n $last && $(<"$last") == "$sha" ]]; then
        log "$tool: código al día ($branch@${sha:0:8})"
        return 0
    fi
    local zip="$dir/$branch-$tool-$TODAY.zip"
    log "$tool: bajando código $branch@${sha:0:8} → $(basename "$zip")"
    # El zip por commit garantiza que el archivo corresponde al sha anotado
    fetch "https://github.com/$OWNER/$tool/archive/$sha.zip" "$zip" || { warn "$tool: falló el zip"; return 1; }
    echo "$sha" > "$zip.sha"
}

verify() { # $1 archivo, $2 SHA256SUMS → 0 ok / 1 mal / 2 sin suma publicada
    local file=$1 sums=$2 expected
    [[ -f $sums ]] || return 2
    expected=$(awk -v n="$(basename "$file")" '{f=$2; sub(/^\*/,"",f)} f==n {print $1}' "$sums")
    [[ -z $expected ]] && return 2
    [[ $(sha256sum "$file" | cut -d' ' -f1) == "$expected" ]]
}

mirror_release() {
    local tool=$1 json tag ver rdir
    json=$(api "repos/$OWNER/$tool/releases/latest") || { warn "$tool: sin releases o límite de API alcanzado"; return 1; }
    tag=$(jq -r .tag_name <<<"$json")
    ver=${tag#"$tool"-}; ver=${ver#v}
    rdir="$DEST/$tool/release-$ver"

    if [[ -f $rdir/.complete && $(<"$rdir/.complete") == "$PLATFORMS|$EXCLUDE" ]]; then
        log "$tool: release $ver ya completa"
        return 0
    fi
    log "$tool: release $ver"
    mkdir -p "$rdir"
    jq -c '{tag_name, name, published_at, html_url, body}' <<<"$json" > "$rdir/release.json"

    local ok=1 name url size plat out sums="$rdir/SHA256SUMS.txt"
    # SHA256SUMS primero para poder verificar el resto
    while IFS=$'\t' read -r name url size; do
        plat=$(platform_of "$name")
        wanted "$name" "$plat" || continue
        if [[ $plat == . ]]; then out="$rdir/$name"; else out="$rdir/$plat/$name"; fi

        if [[ -f $out ]]; then
            verify "$out" "$sums"; case $? in
                0) continue ;;
                2) [[ $(stat -c %s "$out") == "$size" ]] && continue ;;
            esac
            warn "$tool: $name no coincide, se vuelve a bajar"; rm -f "$out"
        fi
        log "  ↓ ${out#"$rdir"/} ($((size / 1048576)) MiB)"
        if ! fetch "$url" "$out" "$size"; then warn "  falló $name"; ok=0; continue; fi
        verify "$out" "$sums"; case $? in
            1) warn "  checksum INCORRECTO: $name (se borra)"; rm -f "$out"; ok=0 ;;
            2) [[ $name != SHA256SUMS* ]] && [[ $(stat -c %s "$out") != "$size" ]] && { warn "  tamaño incorrecto: $name"; rm -f "$out"; ok=0; } ;;
        esac
    done < <(jq -r '.assets | sort_by(.name | startswith("SHA256SUMS") | not)[]
                    | [.name, .browser_download_url, .size] | @tsv' <<<"$json")

    if (( ok )); then echo "$PLATFORMS|$EXCLUDE" > "$rdir/.complete"; log "$tool: release $ver completa ✔"
    else warn "$tool: release $ver incompleta; vuelve a ejecutar el script para continuar"; return 1; fi
}

fail=0
for tool in $(tool_list); do
    echo "──────── $tool"
    [[ -z ${SKIP_CODE:-} ]]     && { mirror_code "$tool"    || fail=1; }
    [[ -z ${SKIP_RELEASES:-} ]] && { mirror_release "$tool" || fail=1; }
done

(( fail )) && { warn "Hubo errores; ejecuta de nuevo para reintentar lo pendiente."; exit 1; }
log "Todo al día en $DEST"

Het zijn heel jonge programma’s, bijna allemaal als vroege alfa gemarkeerd: ze beloven veel, maar vervangen professionele programma’s voor serieus werk nog niet. Probeer ze, bewaar kopieën van je bestanden en meld fouten op hun GitHub.

Bronnen