Ctrl K
ComunidadGuías…

justfile

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Default recipe (runs when just is called without arguments)
default:
    @just --list

# Read nightly toolchain from rust-toolchain.toml (single source of truth).
nightly_toolchain := `grep '^channel' rust-toolchain.toml | sed 's/.*"\(.*\)"/\1/'`

# Format Rust code
format:
    cargo +{{nightly_toolchain}} fmt --all

# Check if code is formatted
format-check:
    cargo +{{nightly_toolchain}} fmt --all -- --check

# Run the full live provider integration workflow locally (sources .envrc when present).
provider-e2e-weekly:
    ./scripts/run-provider-integration-weekly.sh

# Run only the scenario-driven provider E2E serialization checks.
provider-e2e-scenarios:
    ./scripts/run-provider-e2e-daily.sh

# Compatibility alias for the old daily recipe name.
provider-e2e-daily: provider-e2e-scenarios

# Verify Cargo.lock is in sync with workspace manifests.
lockfile-check:
    cargo fetch --locked

# Lint Rust code using clippy (OS-aware: macOS excludes CUDA features)
lint: lockfile-check
    #!/usr/bin/env bash
    set -euo pipefail
    if [ "$(uname -s)" = "Darwin" ]; then
        cargo +{{nightly_toolchain}} clippy -Z unstable-options --workspace --all-targets --exclude moltis-providers --exclude moltis-gateway --exclude moltis-matrix --timings -- -D warnings
        cargo +{{nightly_toolchain}} clippy -Z unstable-options -p moltis-providers --all-targets --features local-llm-metal --timings -- -D warnings
        cargo +{{nightly_toolchain}} clippy -Z unstable-options -p moltis-gateway --all-targets --features local-llm-metal --timings -- -D warnings
    else
        cargo +{{nightly_toolchain}} clippy -Z unstable-options --workspace --all-features --all-targets --timings -- -D warnings
    fi

# Build Tailwind CSS for the web UI.
build-css:
    cd crates/web/ui && ./build.sh

# Build Vite frontend JS (TS/TSX -> dist/).
build-frontend:
    cd crates/web/ui && npm run build

# Build the service worker (sw.ts -> sw.js).
build-sw:
    cd crates/web/ui && npm run build:sw

# Build all web assets (Vite JS + Tailwind CSS + service worker).
build-web-assets:
    ./scripts/build-web-assets.sh

# Ad-hoc codesign debug binaries (macOS only, requires MACOS_CODESIGN_IDENTITY).
# Signs the main binary and all test binaries in target/debug/deps/ so Little
# Snitch doesn't prompt on every rebuild during local dev.
[private]
codesign-debug:
    #!/usr/bin/env bash
    [ "$(uname -s)" = "Darwin" ] || exit 0
    [ -n "${MACOS_CODESIGN_IDENTITY:-}" ] || exit 0
    id="${MACOS_CODESIGN_IDENTIFIER:-org.moltis.dev}"
    sign() { codesign --force --sign "$MACOS_CODESIGN_IDENTITY" --identifier "$id" "$1" 2>/dev/null || true; }
    # Main binary
    if [ -f target/debug/moltis ]; then sign target/debug/moltis; fi
    # Test binaries (Mach-O executables, skip .d/.fingerprint/dylib)
    for bin in target/debug/deps/moltis*; do
        if [ -f "$bin" ] && [ -x "$bin" ] && [[ "$bin" != *.d ]]; then sign "$bin"; fi
    done

# Build the project
build: build-web-assets
    cargo build
    just codesign-debug

# Build in release mode
build-release:
    ./scripts/cargo-build-moltis.sh --release

# Build embedded WASM guest tools and pre-compile to .cwasm for AOT loading.
wasm-tools:
    cargo build --target wasm32-wasip2 -p moltis-wasm-calc -p moltis-wasm-web-fetch -p moltis-wasm-web-search --release
    cargo run -p moltis-wasm-precompile --release

# Build just the release WASM artifacts expected by embedded-wasm builds.
build-wasm-artifacts: wasm-tools
    @echo "Built target/wasm32-wasip2/release/{moltis_wasm_calc,moltis_wasm_web_fetch,moltis_wasm_web_search}.{wasm,cwasm}"

# Build release after ensuring embedded WASM artifacts are present.
build-release-with-wasm: build-wasm-artifacts
    ./scripts/cargo-build-moltis.sh --release

# Run local dev server with workspace-local config/data dirs.
dev-server:
    cargo build --bin moltis
    just codesign-debug
    MOLTIS_SLACK_API_BASE_URL_ALLOWLIST=localhost,127.0.0.1 MOLTIS_CONFIG_DIR=.moltis/config MOLTIS_DATA_DIR=.moltis/ cargo run --bin moltis

# Build Debian package for the current architecture
deb: build-release build-wasm-artifacts
    bash ./scripts/stage-wasm-package-assets.sh target/release
    cargo deb -p moltis --no-build

# Build Debian package for amd64
deb-amd64: build-wasm-artifacts
    ./scripts/cargo-build-moltis.sh --release --target x86_64-unknown-linux-gnu
    bash ./scripts/stage-wasm-package-assets.sh target/x86_64-unknown-linux-gnu/release
    cargo deb -p moltis --no-build --target x86_64-unknown-linux-gnu

# Build Debian package for arm64
deb-arm64: build-wasm-artifacts
    ./scripts/cargo-build-moltis.sh --release --target aarch64-unknown-linux-gnu
    bash ./scripts/stage-wasm-package-assets.sh target/aarch64-unknown-linux-gnu/release
    cargo deb -p moltis --no-build --target aarch64-unknown-linux-gnu

# Build Debian packages for all architectures
deb-all: deb-amd64 deb-arm64

# Build Arch package for the current architecture
arch-pkg: build-release
    #!/usr/bin/env bash
    set -euo pipefail
    VERSION="${MOLTIS_VERSION:-$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')}"
    ARCH=$(uname -m)
    PKG_DIR="target/arch-pkg"
    rm -rf "$PKG_DIR"
    mkdir -p "$PKG_DIR/usr/bin"
    cp target/release/moltis "$PKG_DIR/usr/bin/moltis"
    chmod 755 "$PKG_DIR/usr/bin/moltis"
    cat > "$PKG_DIR/.PKGINFO" <<PKGINFO
    pkgname = moltis
    pkgver = ${VERSION}-1
    pkgdesc = Personal AI gateway inspired by OpenClaw
    url = https://www.moltis.org/
    arch = ${ARCH}
    license = MIT
    PKGINFO
    cd "$PKG_DIR"
    fakeroot -- tar --zstd -cf "../../moltis-${VERSION}-1-${ARCH}.pkg.tar.zst" .PKGINFO usr/
    echo "Built moltis-${VERSION}-1-${ARCH}.pkg.tar.zst"

# Build Arch package for x86_64
arch-pkg-x86_64:
    #!/usr/bin/env bash
    set -euo pipefail
    ./scripts/cargo-build-moltis.sh --release --target x86_64-unknown-linux-gnu
    VERSION="${MOLTIS_VERSION:-$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')}"
    PKG_DIR="target/arch-pkg-x86_64"
    rm -rf "$PKG_DIR"
    mkdir -p "$PKG_DIR/usr/bin"
    cp target/x86_64-unknown-linux-gnu/release/moltis "$PKG_DIR/usr/bin/moltis"
    chmod 755 "$PKG_DIR/usr/bin/moltis"
    cat > "$PKG_DIR/.PKGINFO" <<PKGINFO
    pkgname = moltis
    pkgver = ${VERSION}-1
    pkgdesc = Personal AI gateway inspired by OpenClaw
    url = https://www.moltis.org/
    arch = x86_64
    license = MIT
    PKGINFO
    cd "$PKG_DIR"
    fakeroot -- tar --zstd -cf "../../moltis-${VERSION}-1-x86_64.pkg.tar.zst" .PKGINFO usr/
    echo "Built moltis-${VERSION}-1-x86_64.pkg.tar.zst"

# Build Arch package for aarch64
arch-pkg-aarch64:
    #!/usr/bin/env bash
    set -euo pipefail
    ./scripts/cargo-build-moltis.sh --release --target aarch64-unknown-linux-gnu
    VERSION="${MOLTIS_VERSION:-$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')}"
    PKG_DIR="target/arch-pkg-aarch64"
    rm -rf "$PKG_DIR"
    mkdir -p "$PKG_DIR/usr/bin"
    cp target/aarch64-unknown-linux-gnu/release/moltis "$PKG_DIR/usr/bin/moltis"
    chmod 755 "$PKG_DIR/usr/bin/moltis"
    cat > "$PKG_DIR/.PKGINFO" <<PKGINFO
    pkgname = moltis
    pkgver = ${VERSION}-1
    pkgdesc = Personal AI gateway inspired by OpenClaw
    url = https://www.moltis.org/
    arch = aarch64
    license = MIT
    PKGINFO
    cd "$PKG_DIR"
    fakeroot -- tar --zstd -cf "../../moltis-${VERSION}-1-aarch64.pkg.tar.zst" .PKGINFO usr/
    echo "Built moltis-${VERSION}-1-aarch64.pkg.tar.zst"

# Build Arch packages for all architectures
arch-pkg-all: arch-pkg-x86_64 arch-pkg-aarch64

# Build RPM package for the current architecture
rpm: build-release
    cargo generate-rpm -p crates/cli

# Build RPM package for x86_64
rpm-x86_64:
    ./scripts/cargo-build-moltis.sh --release --target x86_64-unknown-linux-gnu
    cargo generate-rpm -p crates/cli --target x86_64-unknown-linux-gnu

# Build RPM package for aarch64
rpm-aarch64:
    ./scripts/cargo-build-moltis.sh --release --target aarch64-unknown-linux-gnu
    cargo generate-rpm -p crates/cli --target aarch64-unknown-linux-gnu

# Build RPM packages for all architectures
rpm-all: rpm-x86_64 rpm-aarch64

# Build AppImage for the current architecture
appimage: build-release
    #!/usr/bin/env bash
    set -euo pipefail
    VERSION="${MOLTIS_VERSION:-$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')}"
    ARCH=$(uname -m)
    APP_DIR="target/moltis.AppDir"
    rm -rf "$APP_DIR"
    mkdir -p "$APP_DIR/usr/bin"
    cp target/release/moltis "$APP_DIR/usr/bin/moltis"
    chmod 755 "$APP_DIR/usr/bin/moltis"
    cat > "$APP_DIR/moltis.desktop" <<DESKTOP
    [Desktop Entry]
    Type=Application
    Name=Moltis
    Exec=moltis
    Icon=moltis
    Categories=Network;
    Terminal=true
    DESKTOP
    cat > "$APP_DIR/moltis.svg" <<SVG
    <svg xmlns="http://www.w3.org/2000/svg" width="256" height="256"><rect width="256" height="256" fill="#333"/><text x="128" y="140" font-size="120" text-anchor="middle" fill="white">M</text></svg>
    SVG
    ln -sf moltis.svg "$APP_DIR/.DirIcon"
    cat > "$APP_DIR/AppRun" <<'APPRUN'
    #!/bin/sh
    SELF=$(readlink -f "$0")
    HERE=${SELF%/*}
    exec "$HERE/usr/bin/moltis" "$@"
    APPRUN
    chmod +x "$APP_DIR/AppRun"
    if [ ! -f target/appimagetool ]; then
        wget -q "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${ARCH}.AppImage" -O target/appimagetool
        chmod +x target/appimagetool
    fi
    ARCH=${ARCH} target/appimagetool --appimage-extract-and-run "$APP_DIR" "moltis-${VERSION}-${ARCH}.AppImage"
    echo "Built moltis-${VERSION}-${ARCH}.AppImage"

# Build Snap package
snap:
    snapcraft

# Build Flatpak
flatpak:
    cd flatpak && flatpak-builder --repo=repo --force-clean builddir org.moltbot.Moltis.yml

# Run all CI checks (format, lint, build, test)
ci: format-check lint i18n-check build-web-assets build test

# Compile once, then run Rust tests and E2E tests in parallel.
# Uses the same nightly toolchain as clippy/local-validate so the build cache
# is shared — no double-compilation.
build-test: build-web-assets
    #!/usr/bin/env bash
    set -euo pipefail
    echo "==> Building all workspace targets (bins + tests)..."
    if [ "$(uname -s)" = "Darwin" ]; then
        cargo +{{nightly_toolchain}} build --workspace --all-targets
    else
        cargo +{{nightly_toolchain}} build --workspace --all-features --all-targets
    fi
    just codesign-debug
    echo "==> Build complete. Running Rust tests and E2E tests in parallel..."

    RUST_LOG="$(mktemp)"
    E2E_LOG="$(mktemp)"
    trap 'rm -f "${RUST_LOG}" "${E2E_LOG}"' EXIT

    if [ "$(uname -s)" = "Darwin" ]; then
        cargo +{{nightly_toolchain}} nextest run --workspace > "${RUST_LOG}" 2>&1 &
    else
        cargo +{{nightly_toolchain}} nextest run --workspace --all-features > "${RUST_LOG}" 2>&1 &
    fi
    TEST_PID=$!

    (cd crates/web/ui && npm run e2e) > "${E2E_LOG}" 2>&1 &
    E2E_PID=$!

    TEST_EXIT=0; E2E_EXIT=0
    wait "${TEST_PID}" || TEST_EXIT=$?
    wait "${E2E_PID}" || E2E_EXIT=$?

    if [ "${TEST_EXIT}" -ne 0 ]; then
        echo "==> Rust tests FAILED (exit ${TEST_EXIT}):"
        cat "${RUST_LOG}"
    else
        echo "==> Rust tests PASSED"
    fi

    if [ "${E2E_EXIT}" -ne 0 ]; then
        echo "==> E2E tests FAILED (exit ${E2E_EXIT}):"
        cat "${E2E_LOG}"
    else
        echo "==> E2E tests PASSED"
    fi

    exit $(( TEST_EXIT > 0 ? TEST_EXIT : E2E_EXIT ))

# Run the same Rust preflight gates used before release packaging.
release-preflight: lint
    cargo +{{nightly_toolchain}} fmt --all -- --check

# Sync repo-root install.sh into website/install.sh for Cloudflare deployment.
sync-website-install:
    ./scripts/sync-website-install.sh

# Ensure repo-root install.sh and website/install.sh are identical.
check-website-install-sync:
    ./scripts/check-website-install-sync.sh

# Dispatch release workflow from GitHub Actions (normal mode).
release-workflow ref='main':
    gh workflow run release.yml --ref {{ref}} -f dry_run=false

# Dispatch release workflow from GitHub Actions (dry-run mode).
release-workflow-dry ref='main':
    gh workflow run release.yml --ref {{ref}} -f dry_run=true

# Dispatch both release workflow modes for the same ref (dry-run then normal).
release-workflow-both ref='main':
    gh workflow run release.yml --ref {{ref}} -f dry_run=true
    gh workflow run release.yml --ref {{ref}} -f dry_run=false

# Regenerate CHANGELOG.md from git history and tags.
changelog:
    git-cliff --config cliff.toml --output CHANGELOG.md

# Preview unreleased changelog entries from commits since the last tag.
changelog-unreleased:
    git-cliff --config cliff.toml --unreleased

# Generate release entries for unreleased commits under the provided version.
changelog-release version:
    git-cliff --config cliff.toml --unreleased --tag "{{version}}" --strip all

# Commit all changes, push branch, create/update PR, and run local validation.
# All args are optional; defaults are auto-generated from branch + changed files.
ship commit_message='' pr_title='' pr_body='':
    ./scripts/ship-pr.sh {{ quote(commit_message) }} {{ quote(pr_title) }} {{ quote(pr_body) }}

# Run local validation with the full Rust and Playwright test suites.
local-validate-full pr_number='':
    #!/usr/bin/env bash
    set -euo pipefail
    args=()
    if [[ -n {{ quote(pr_number) }} ]]; then
        args+=({{ quote(pr_number) }})
    fi
    # `"${args[@]+...}"` is required: bash 3.2 (the default /bin/bash on macOS)
    # treats a plain `"${args[@]}"` on an empty array as an unbound variable
    # under `set -u`. The array is empty in the supported no-PR local-only mode.
    LOCAL_VALIDATE_TEST_CMD="just test" \
    LOCAL_VALIDATE_E2E_CMD="cd crates/web/ui && npm run e2e:install && npm run e2e" \
        ./scripts/local-validate.sh "${args[@]+"${args[@]}"}"

# Run all tests (nightly to share build cache with clippy/lint, OS-aware).
# On macOS: single nextest run using default features (includes Metal, not CUDA).
# On Linux: --all-features (includes CUDA).
# Builds first so codesign can run before test execution (prevents Little Snitch prompts).
test:
    #!/usr/bin/env bash
    set -euo pipefail
    if [ "$(uname -s)" = "Darwin" ]; then
        cargo +{{nightly_toolchain}} build --workspace --all-targets
        just codesign-debug
        cargo +{{nightly_toolchain}} nextest run --workspace
    else
        cargo +{{nightly_toolchain}} nextest run --workspace --all-features
    fi

# Run contract test suites (channel, provider, memory, tools)
contract-tests:
    cargo test -p moltis-channels contract
    cargo test -p moltis-providers contract
    cargo test -p moltis-memory contract
    cargo test -p moltis-tools contract

# Verify locale key parity across frontend i18n bundles.
i18n-check:
    ./scripts/i18n-check.sh

# Install browser tooling for gateway web UI e2e tests.
ui-e2e-install:
    cd crates/web/ui && npm install && npm run e2e:install

# Run gateway web UI e2e tests (Playwright).
ui-e2e:
    cargo +{{nightly_toolchain}} build --bin moltis
    just codesign-debug
    cd crates/web/ui && npm run e2e

# Run gateway web UI e2e tests with headed browser.
ui-e2e-headed:
    cargo +{{nightly_toolchain}} build --bin moltis
    just codesign-debug
    cd crates/web/ui && npm run e2e:headed

# Build all Linux packages (deb + rpm + arch + appimage) for all architectures
packages-all: deb-all rpm-all arch-pkg-all

# Build the native gpui desktop client (apps/desktop, its own workspace).
desktop-build:
    cd apps/desktop && cargo build

# Run the desktop client's tests.
desktop-test:
    cd apps/desktop && cargo test

# Lint the desktop client (all feature combinations it ships with).
desktop-lint:
    cd apps/desktop && cargo clippy --all-targets --features mockup -- -D warnings
    cd apps/desktop && cargo clippy --all-targets --no-default-features -- -D warnings

# Run the desktop client.
desktop-run:
    cd apps/desktop && cargo run

# Show UI variants from FILE side by side (the gpui-mockup agent skill).
# Without FILE it shows the built-in demo (apps/desktop/src/mockup/demo.rs).
desktop-mockup file="" feedback="" capture="":
    #!/usr/bin/env bash
    set -euo pipefail
    absolute() { case "$1" in ""|/*) printf '%s' "$1" ;; *) printf '%s/%s' {{quote(invocation_directory())}} "$1" ;; esac; }
    file="$(absolute {{quote(file)}})"
    feedback="$(absolute {{quote(feedback)}})"
    capture="$(absolute {{quote(capture)}})"
    cd apps/desktop
    MOLTIS_MOCKUP_FILE="$file" cargo build --locked --features mockup
    args=(--mockup)
    if [ -n "$feedback" ]; then args+=(--feedback "$feedback"); fi
    if [ -n "$capture" ]; then args+=(--capture "$capture"); fi
    exec target/debug/moltis-desktop "${args[@]}"

# Package "Moltis Desktop.app" (macOS) with the moltis daemon inside.
desktop-package-macos:
    ./scripts/package-desktop-macos.sh

# Package the Moltis Desktop AppImage (Linux) with the moltis daemon inside.
desktop-package-linux:
    ./scripts/package-desktop-linux.sh

# Build "Moltis Desktop.app" with the moltis daemon inside (release) and open it.
desktop-open-macos: desktop-package-macos
    open "apps/desktop/target/bundle/Moltis Desktop.app"

# Build Rust static library and generated C header for the macOS app.
swift-build-rust:
    ./scripts/build-swift-bridge.sh

# Generate Xcode project from YAML spec in apps/macos.
swift-generate:
    ./scripts/generate-swift-project.sh

# Lint macOS app sources with SwiftLint.
swift-lint:
    ./scripts/lint-swift.sh

# Build Swift macOS app.
swift-build: swift-build-rust swift-generate
    ./scripts/build-swift.sh

# Run Swift app unit tests.
swift-test: swift-build-rust swift-generate
    ./scripts/test-swift.sh

# Build and launch the Swift macOS app locally.
swift-run: swift-build-rust swift-generate
    ./scripts/run-swift.sh

# Open generated project in Xcode.
swift-open: swift-build-rust swift-generate
    open apps/macos/Moltis.xcodeproj

# Generate iOS app Xcode project.
ios-generate:
    ./scripts/generate-ios-project.sh

# Generate Apollo GraphQL types for iOS.
ios-graphql:
    cargo run -p moltis-schema-export -- apps/ios/GraphQL/Schema/schema.graphqls
    ./scripts/generate-ios-graphql.sh

# Build iOS app (generic iOS destination, no signing).
ios-build: ios-generate ios-graphql
    ./scripts/generate-ios-project.sh
    xcodebuild -project apps/ios/Moltis.xcodeproj -scheme Moltis -configuration Debug -destination "generic/platform=iOS" CODE_SIGNING_ALLOWED=NO build

# Lint iOS app sources with SwiftLint.
ios-lint:
    cd apps/ios && swiftlint

# Open iOS project in Xcode (regenerates GraphQL types and project first).
ios-open: ios-generate ios-graphql
    ./scripts/generate-ios-project.sh
    open apps/ios/Moltis.xcodeproj

# Build the APNS push relay.
courier-build:
    cargo build -p moltis-courier --release

# Cross-compile courier for linux/x86_64.
courier-cross:
    cargo build -p moltis-courier --release --target x86_64-unknown-linux-gnu

# Deploy courier to remote server(s) via Ansible.
courier-deploy:
    cd apps/courier/deploy && ansible-playbook playbook.yml

# Run the APNS push relay (dev).
courier-run *ARGS:
    cargo run -p moltis-courier -- {{ARGS}}

# Serve the website locally with SSR partial injection (default 127.0.0.1:4000).
website-dev:
    node website/scripts/build-changelog.mjs
    node website/scripts/dev-server.mjs