Agent skill

Write Nanoflows

by mendixlabs in mendixlabs/mxcli

Nanoflow syntax in MDL — shared with microflows, but client-side and restricted.

Apache-2.0Auto-check passed

Install Write Nanoflows

skills CLI
$ npx skills add mendixlabs/mxcli --skill write-nanoflows -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install mendixlabs/mxcli write-nanoflows --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/mendixlabs/mxcli.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/mendix/write-nanoflows .claude/skills/write-nanoflows && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
write-nanoflows
GitHub stars
128
Token cost
~5.9k tokens
SKILL.md length
1,819 words
Files
1
Skills in repo
75
Repo updated
First seen
Licence
Apache-2.0

At a glance

Nanoflow syntax in MDL — shared with microflows, but client-side and restricted.

  • Works in 8 steps: Using Java actions — Use CALL JAVASCRIPT… → Using RAISE ERROR — Nanoflows cannot… → Expecting transactions — Nanoflows have… → …
  • SKILL.md covers When to Use This Skill, Changing an Existing Nanoflow, When to Use a Nanoflow vs a… and Key Differences from Microflows, plus 5 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Write Nanoflows is an agent skill from mendixlabs/mxcli. Nanoflow syntax in MDL — shared with microflows, but client-side and restricted. Use before writing any CREATE NANOFLOW, when a nanoflow validation error needs explaining, or when deciding between a nanoflow and a microflow.

Its SKILL.md is about 5.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

The repository describes itself as: Mendix cli tool, a headless way to work with Mendix projects. Enables Mendix projects for use with 3rd party agentic coding tools like Claude Code and Copilot. Includes a… The licence is Apache-2.0.

Example prompts

  • “/write-nanoflows”

Workflow steps

8 steps, taken from the first numbered list in SKILL.md.

  1. Using Java actions — Use CALL JAVASCRIPT ACTION instead.
  2. Using RAISE ERROR — Nanoflows cannot raise errors directly. Handle per-action with ON ERROR or guard with IF checks.
  3. Expecting transactions — Nanoflows have no automatic rollback. Design for idempotency.
  4. File operations — DOWNLOAD FILE is server-only.
  5. Binary return types — Not supported in nanoflows.
  6. REST/external calls — REST calls and external actions are server-only. Call a microflow to do server work.
  7. Calling NanoflowCommons before checking availability — Always check StorageItemExists before reading; always check IsConnectedToServer…
  8. Using SYNCHRONIZE outside native mobile context — Only call SYNCHRONIZE in native mobile offline flows.

What it can do on your machine

Read from SKILL.md and the folder at commit a924d11. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are mdl and sql).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Write Nanoflows loads about 5.9k tokens when it runs. Until then it costs about 60 tokens; SKILL.md has 1,819 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~60
When it runs · the whole SKILL.md, loaded when a task matches
~5.9k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from mendixlabs/mxcli at commit a924d11, republished under its Apache-2.0 licence (© mendixlabs). 1,819 words, ~5,927 tokens.

Download SKILL.mdSave it as .claude/skills/write-nanoflows/SKILL.md (or your agent's skills folder).
name
write-nanoflows
description
Nanoflow syntax in MDL — shared with microflows, but client-side and restricted. Use before writing any CREATE NANOFLOW, when a nanoflow validation error needs explaining, or when deciding between a nanoflow and a microflow.

Mendix Nanoflow Skill

This skill provides guidance for writing Mendix nanoflows in MDL syntax. Nanoflows share syntax with microflows but execute client-side with restricted capabilities.

When to Use This Skill

Use this skill when:

  • Writing CREATE NANOFLOW statements
  • Debugging nanoflow validation errors
  • Understanding nanoflow restrictions vs microflows
  • Building mobile or offline-capable features

If you're not sure whether the logic belongs in a nanoflow or a microflow, read the next section first. The mirror lives in write-microflows — keep both copies in sync.

Changing an Existing Nanoflow

Choose the mode by who owns the nanoflow (choose-edit-mode):

  • Created by your MDL scripts, and not edited in Studio Pro since: edit the script (or fresh describe output) and re-run create or modify.
  • Authored in Studio Pro: prefer alter nanoflow X { insert/replace/drop … } (targets by output variable, caption or statement pattern). create or modify of describe output also works as a patch: an unchanged definition writes nothing, and an inserted, replaced or dropped statement (at the top level or in an if branch) is spliced in, leaving every other node, merge and curve as stored — a guard clause (if … then return; end if;) too, its return a new end event, and so is the return ending a new activity's error handler; a changed return value or if condition is set on the stored end event or decision, and a body without a trailing return means the stored end. The header (documentation, return type, parameters added, retyped or — when unused — removed) is set on the stored document, and a stated @position or @start moves the stored node, keeping its flows. A change it cannot patch — anything inside a loop body or error handler, a redrawn @anchor/@curve, any other return added or taken away — rebuilds the whole nanoflow under mdl 0 (warning MDL-V1-REBUILD: element IDs renumbered, merges removed, curves reset) and is refused under mdl 1;.
  • Rebuilding deliberately: drop nanoflow X; and create nanoflow X … in ONE script. The drop's module-role grants (and the unit's ID and folder) carry only to a create later in the same script or REPL session; a drop in one run and a create in the next loses every grant execute. drop prints the roles it removed and the grant to restore them.
  • Changing something inside a loop body (either owner) : neither create or modify (under mdl 1;) nor an alter aimed at an activity in the loop can make it — alter does not splice inside a loop. Replace the whole loop, addressed by its handle, with the body as it should be (replace loop $Item in $Items with begin loop $Item in $Items begin … end loop; end;). Everything outside the loop keeps its $IDs, positions and curves; the loop and its body are rebuilt. For a nested loop, replace the outer one.

When to Use a Nanoflow vs a Microflow

ScenarioUse
Client-side form validation before saveNanoflow
UI navigation and page routingNanoflow
Calling device features (GPS, phone, camera)Nanoflow
Offline data access and local storageNanoflow
Calling JavaScript actions (NanoflowCommons)Nanoflow
Showing progress indicators / confirmation dialogsNanoflow
Querying the databaseMicroflow
Calling REST services or external actionsMicroflow
Running Java actionsMicroflow
File generation or downloadMicroflow
Transactional commits (rollback on error)Microflow
Background scheduled logicMicroflow

Rule of thumb: A nanoflow runs before the server call. A microflow IS the server call.

Key Differences from Microflows

AspectMicroflowNanoflow
ExecutionServer-sideClient-side (browser/mobile)
Database accessFullNo direct access
TransactionsSupportedNot supported
Java actionsSupportedNot supported
JavaScript actionsNot supportedSupported
SYNCHRONIZENot availableAvailable (offline sync)
File downloadsSupportedNot supported
Error handlingFull ON ERROR blocks + RAISE ERRORPer-action ON ERROR supported; RAISE ERROR / ErrorEvent forbidden
OfflineNot availableAvailable
Binary return typeSupportedNot supported

Nanoflow Structure

mdl
/**
 * Nanoflow description
 *
 * @param $Parameter1 Description
 * @returns Description of return value
 */
CREATE [OR MODIFY] NANOFLOW Module.NAV_Name (
  $Parameter1: type
)
RETURNS ReturnType
FOLDER 'FolderPath'
BEGIN
  -- Nanoflow logic here
  RETURN $Result;
END;

Every body statement ends with a semicolon ; — required, not optional, exactly as in microflows. That includes block terminators: end if;, end loop;, end while;, end case;. A missing one is a parse error (missing ';' at 'return'), not a warning.

Naming Convention

Nanoflow names use the NAV_ prefix by convention:

  • NAV_ValidateCart — client-side validation
  • NAV_ShowDetails — page navigation
  • NAV_ToggleFilter — UI state toggle
  • NAV_SignIn — authentication
  • NAV_SyncChanges — offline sync

Supported Activities

Object Operations (in-memory only)
mdl
$Item = CREATE Sales.CartItem (Quantity = 1);
CHANGE $Item (Quantity = $Item/Quantity + 1);
COMMIT $Item;
DELETE $Item;
ROLLBACK $Item;
Calling Other Flows
mdl
$Result = CALL NANOFLOW Sales.NAV_ValidateCart (Cart = $Cart);
$ServerResult = CALL MICROFLOW Sales.ACT_SubmitOrder (Order = $Order);
$JsResult = CALL JAVASCRIPT ACTION NanoflowCommons.SignIn (userName = $Name, password = $Pass);
UI Activities
mdl
SHOW PAGE Sales.CartDetail (Cart = $Cart);
CLOSE PAGE;
SHOW MESSAGE WARNING 'Connection unavailable. Working offline.';
VALIDATION FEEDBACK $Item/Quantity MESSAGE 'Quantity must be at least 1';
Logging and Variables
mdl
LOG INFO 'Cart updated with ' + toString($ItemCount) + ' items';
DECLARE $IsValid Boolean = true;
SET $IsValid = false;

Where nanoflow log output goes (and a filtering trap): a nanoflow runs on the client, so its LOG output takes two paths:

  • Browser console — with automatic timing, e.g. [Nanoflow] [flow_…] Starting execution of Sudoku.NF_ToggleNotes … Finished … 6.7 ms.
  • Server runtime log (.mxcli/runtime.log under run --local) — but the runtime rewrites the log node to Client_Nanoflow. So LOG INFO NODE 'Sudoku' '…' from a nanoflow appears as Client_Nanoflow: …, not Sudoku: …. A log filter built around your microflow node names will silently drop every nanoflow line — grep for Client_Nanoflow (or the message text) to see nanoflow logs. This is a Mendix platform behaviour, not an mxcli one.
  • LOG DEBUG never reaches the server log. Only INFO/WARNING/ERROR reach runtime.log; a nanoflow LOG DEBUG line is sent but dropped server-side. All four levels still show in the browser console, so use the console (not runtime.log) when debugging at DEBUG level.
Control Flow
mdl
IF $Cart/ItemCount = 0 THEN
  VALIDATION FEEDBACK $Cart/ItemCount MESSAGE 'Cart is empty';
  RETURN false;
ELSE
  SHOW PAGE Sales.Checkout (Cart = $Cart);
  RETURN true;
END IF;
Offline Sync
mdl
-- Sync uncommitted changes back to server
SYNCHRONIZE $Item;

SYNCHRONIZE is nanoflow-only. Use it after committing offline objects to push changes to the server in a native mobile context.


Real-World Patterns

These patterns come from 223 nanoflows across three production Mendix apps: EnquiriesManagement (79), Evora-FactoryManagement (93), LatoProductInventory (51).

Pattern 1: Client-Side Validation

Validate before calling a microflow to avoid a round-trip.

mdl
mdl 1;
/**
 * Validates the enquiry form fields before submission.
 * @param $Enquiry The enquiry being created or edited
 * @returns true if valid, false if validation errors were shown
 */
CREATE OR MODIFY NANOFLOW Enquiries.NAV_ValidateEnquiry (
  $Enquiry: Enquiries.Enquiry
)
RETURNS Boolean
FOLDER 'Validation'
BEGIN
  IF $Enquiry/Subject = '' THEN
    VALIDATION FEEDBACK $Enquiry/Subject MESSAGE 'Subject is required';
    RETURN false;
  END IF;
  IF $Enquiry/ContactEmail = '' THEN
    VALIDATION FEEDBACK $Enquiry/ContactEmail MESSAGE 'Email is required';
    RETURN false;
  END IF;
  RETURN true;
END;
Pattern 2: Navigation Controller

Validate then navigate — keeps pages dumb.

mdl
mdl 1;
/**
 * Validates the product and opens the detail page if valid.
 * @param $Product Product to open
 */
CREATE OR MODIFY NANOFLOW Inventory.NAV_OpenProductDetail (
  $Product: Inventory.Product
)
FOLDER 'Navigation'
BEGIN
  $IsValid = CALL NANOFLOW Inventory.NAV_ValidateProduct (Product = $Product);
  IF NOT ($IsValid) THEN
    RETURN;
  END IF;
  SHOW PAGE Inventory.ProductDetail (Product = $Product);
END;
Pattern 3: UI Feedback Wrapper

Wrap a slow server call with progress indicators.

mdl
/**
 * Shows progress, calls the server, hides progress.
 * @param $Order The order to submit
 */
CREATE OR MODIFY NANOFLOW Sales.NAV_SubmitOrderWithProgress (
  $Order: Sales.Order
)
FOLDER 'Actions'
BEGIN
  CALL JAVASCRIPT ACTION NanoflowCommons.ShowProgress (message = 'Submitting order...');
  $Result = CALL MICROFLOW Sales.ACT_SubmitOrder (Order = $Order);
  CALL JAVASCRIPT ACTION NanoflowCommons.HideProgress ();
  IF $Result THEN
    SHOW MESSAGE SUCCESS 'Order submitted successfully.';
  END IF;
END;
Pattern 4: Confirmation Dialog Before Destructive Action
mdl
mdl 1;
/**
 * Asks the user to confirm before deleting an item.
 * @param $Item The inventory item to delete
 */
CREATE OR MODIFY NANOFLOW Inventory.NAV_ConfirmDeleteItem (
  $Item: Inventory.Item
)
FOLDER 'Actions'
BEGIN
  $Confirmed = CALL JAVASCRIPT ACTION NanoflowCommons.ShowConfirmation (
    question = 'Delete ' + $Item/Name + '?',
    positiveButtonCaption = 'Delete',
    cancelButtonCaption = 'Cancel'
  );
  IF NOT ($Confirmed) THEN
    RETURN;
  END IF;
  CALL MICROFLOW Inventory.ACT_DeleteItem (Item = $Item);
  CLOSE PAGE;
END;
Pattern 5: Authentication Flow
mdl
/**
 * Signs the user in and navigates to the home page on success.
 * @param $Username Login username
 * @param $Password Login password
 */
CREATE OR MODIFY NANOFLOW Auth.NAV_SignIn (
  $Username: String,
  $Password: String
)
FOLDER 'Authentication'
BEGIN
  $StatusCode = CALL JAVASCRIPT ACTION NanoflowCommons.SignIn (
    userName = $Username,
    password = $Password,
    useAuthToken = true
  );
  IF $StatusCode = 200 THEN
    SHOW PAGE Home.HomePage ();
  ELSE IF $StatusCode = 401 THEN
    SHOW MESSAGE ERROR 'Incorrect username or password.';
  ELSE
    SHOW MESSAGE WARNING 'Could not connect to server (status: ' + toString($StatusCode) + ')';
  END IF;
END;
Pattern 6: Connectivity Check Before Server Call

Common in field-service and factory-management apps where offline is normal.

mdl
/**
 * Submits inspection results, warns user if offline.
 * @param $Inspection The inspection to submit
 */
CREATE OR MODIFY NANOFLOW Factory.NAV_SubmitInspection (
  $Inspection: Factory.Inspection
)
FOLDER 'Inspections'
BEGIN
  $IsOnline = CALL JAVASCRIPT ACTION NanoflowCommons.IsConnectedToServer ();
  IF NOT ($IsOnline) THEN
    SHOW MESSAGE WARNING 'You are offline. Changes will sync when reconnected.';
    COMMIT $Inspection;
    RETURN;
  END IF;
  COMMIT $Inspection;
  SYNCHRONIZE $Inspection;
  CALL MICROFLOW Factory.ACT_ProcessInspection (Inspection = $Inspection);
END;
Pattern 7: Geolocation Capture

Used in enquiry and field-service apps to tag records with GPS coordinates.

mdl
mdl 1;
/**
 * Captures the current GPS position and stores it on the record.
 * @param $Record The record to tag with location
 */
CREATE OR MODIFY NANOFLOW Enquiries.NAV_CaptureLocation (
  $Record: Enquiries.SiteVisit
)
FOLDER 'Location'
BEGIN
  $Location = CALL JAVASCRIPT ACTION NanoflowCommons.GetCurrentLocation (
    timeout = 10000,
    maximumAge = 0,
    highAccuracy = true
  );
  CHANGE $Record (
    Latitude = $Location/Latitude,
    Longitude = $Location/Longitude,
    LocationTimestamp = $Location/Timestamp
  );
END;
Pattern 8: Platform-Conditional Logic
mdl
mdl 1;
/**
 * Opens a map or shows coordinates depending on platform.
 * @param $Latitude Latitude coordinate
 * @param $Longitude Longitude coordinate
 */
CREATE OR MODIFY NANOFLOW Enquiries.NAV_ShowOnMap (
  $Latitude: Decimal,
  $Longitude: Decimal
)
FOLDER 'Location'
BEGIN
  $Platform = CALL JAVASCRIPT ACTION NanoflowCommons.GetPlatform ();
  IF $Platform = 'Native_mobile' THEN
    CALL JAVASCRIPT ACTION NanoflowCommons.OpenMap (
      latitude = $Latitude,
      longitude = $Longitude
    );
  ELSE
    SHOW PAGE Enquiries.LocationDetail (Lat = $Latitude, Lon = $Longitude);
  END IF;
END;
Pattern 9: Local Storage Cache

Store a frequently accessed value locally to avoid a round-trip.

mdl
mdl 1;
/**
 * Loads the last-used filter value from local storage.
 * @returns The cached filter string, or empty if never set
 */
CREATE OR MODIFY NANOFLOW Inventory.NAV_LoadFilterCache ()
RETURNS String
FOLDER 'Filters'
BEGIN
  $Exists = CALL JAVASCRIPT ACTION NanoflowCommons.StorageItemExists (
    key = 'InventoryFilter'
  );
  IF NOT ($Exists) THEN
    RETURN '';
  END IF;
  $FilterValue = CALL JAVASCRIPT ACTION NanoflowCommons.GetStorageItemString (
    key = 'InventoryFilter'
  );
  RETURN $FilterValue;
END;
Pattern 10: Device Communication (Field Apps)
mdl
/**
 * Lets the user call the on-site contact directly.
 * @param $Contact The site contact to call
 */
CREATE OR MODIFY NANOFLOW Factory.NAV_CallContact (
  $Contact: Factory.Contact
)
FOLDER 'Communication'
BEGIN
  IF $Contact/Phone = '' THEN
    SHOW MESSAGE WARNING 'No phone number on record for ' + $Contact/Name;
    RETURN;
  END IF;
  CALL JAVASCRIPT ACTION NanoflowCommons.CallPhoneNumber (
    phoneNumber = $Contact/Phone
  );
END;

NanoflowCommons JavaScript Actions Reference

All three test apps include the NanoflowCommons module. The actions below are available in any app that has this module installed.

Authentication & Connectivity
ActionParametersReturnsNotes
NanoflowCommons.SignInuserName, password, useAuthTokenInteger200=success, 401=bad creds, 0=offline
NanoflowCommons.SignOut——Logs out current user
NanoflowCommons.IsConnectedToServer—Booleanfalse when offline
Device Features
ActionParametersReturnsNotes
NanoflowCommons.GetCurrentLocationtimeout, maximumAge, highAccuracyNanoflowCommons.GeolocationObject has Lat, Lon, Accuracy, Timestamp
NanoflowCommons.Geocodeaddress, provider, apiKeyNanoflowCommons.GeolocationAddress → coordinates
NanoflowCommons.ReverseGeocodelatitude, longitude, provider, apiKeyStringCoordinates → address
NanoflowCommons.GetStraightLineDistancefromLat, fromLon, toLat, toLon, distanceUnitDecimalHaversine distance
NanoflowCommons.OpenMaplatitude, longitude—Opens maps app
NanoflowCommons.CallPhoneNumberphoneNumber—Opens dialer
NanoflowCommons.SendTextMessagephoneNumber—Opens SMS app
NanoflowCommons.DraftEmailto, subject, body—Opens email client
NanoflowCommons.Sharecontent—Native share dialog
NanoflowCommons.OpenURLurl—Opens in browser
NanoflowCommons.GetPlatform—StringWeb, Native_mobile, Hybrid_mobile
Show full SKILL.md (699 more words)Show less
UI & Navigation
ActionParametersReturnsNotes
NanoflowCommons.ShowProgressmessage—Shows loading overlay
NanoflowCommons.HideProgress——Hides loading overlay
NanoflowCommons.ShowConfirmationquestion, positiveButtonCaption, cancelButtonCaptionBooleantrue = confirmed
NanoflowCommons.NavigateTotarget—Programmatic navigation
NanoflowCommons.ToggleSidebar——Show/hide sidebar
Local Storage
ActionParametersReturnsNotes
NanoflowCommons.SetStorageItemStringkey, value—Persist string locally
NanoflowCommons.GetStorageItemStringkeyStringRead stored string
NanoflowCommons.SetStorageItemObjectkey, value—Persist Mendix object
NanoflowCommons.GetStorageItemObjectkey, entityObjectRead stored object
NanoflowCommons.StorageItemExistskeyBooleanCheck before reading
NanoflowCommons.RemoveStorageItemkey—Delete a stored item
NanoflowCommons.ClearLocalStorage——Clear everything
Object Utilities
ActionParametersReturnsNotes
NanoflowCommons.GetGuidobjectStringGUID of Mendix object
NanoflowCommons.GetObjectByGuidentity, guidObjectRetrieve by GUID
NanoflowCommons.RefreshObjectobject—Refresh without page reload
NanoflowCommons.RefreshEntityentity—Refresh all objects of type
Utilities
ActionParametersReturnsNotes
NanoflowCommons.Waitmilliseconds—Async delay
NanoflowCommons.TimeBetweenstartDate, endDate, unitDecimalTime difference
NanoflowCommons.GenerateUniqueID—StringSession-scoped unique ID
NanoflowCommons.Base64EncodevalueStringEncode string to Base64
NanoflowCommons.Base64DecodevalueStringDecode Base64 string

Disallowed Activities

These will produce validation errors:

  • RAISE ERROR / ErrorEvent — not available in nanoflows
  • CALL JAVA ACTION — Java actions cannot run client-side
  • EXECUTE DATABASE QUERY — direct SQL requires server
  • CALL EXTERNAL ACTION — external actions are server-side
  • SHOW HOME PAGE — home page navigation is server-side
  • CALL REST SERVICE / SEND REST REQUEST — REST calls are server-side
  • IMPORT FROM MAPPING / EXPORT TO MAPPING — mapping operations are server-side
  • TRANSFORM JSON — JSON transformations are server-side
  • DOWNLOAD FILE — file downloads require server-side processing
Nanoflow-only: SYNCHRONIZE

SYNCHRONIZE is the mirror image of the list above — it is allowed only in a nanoflow, because offline synchronization is a client-side operation. The same statement in a microflow fails the build with CE0009 "This action is not supported in microflows."; mxcli reports it as MDL057 before you get there.

sql
synchronize all;                 -- the whole offline database
synchronize unsynchronized;      -- only objects with uncommitted offline changes (Mendix 9.4+)
synchronize $Order, $Lines;      -- named objects/lists ("Specific" mode)

synchronize all on error continue;
synchronize all on error without rollback begin
  log error 'sync failed';
end error;

The mode is always written out, including all — the statement says what it does rather than relying on the reader knowing the platform default.

Naming trap: the variable form is stored as Specific, not Selected, even though Studio Pro's UI calls it "Selected object(s)". Storage enums come from the Model SDK's SynchronizationType, never from the UI wording.

  • All workflow actions (11 types: CallWorkflow, OpenWorkflow, SetTaskOutcome, etc.)

Return Type Restrictions

Binary return type is NOT allowed in nanoflows.

Error Handling in Nanoflows

Since RAISE ERROR is forbidden, handle errors per-action with ON ERROR:

mdl
$Location = CALL JAVASCRIPT ACTION NanoflowCommons.GetCurrentLocation (
  timeout = 5000,
  maximumAge = 0,
  highAccuracy = false
) ON ERROR CONTINUE;

IF $Location = empty THEN
  SHOW MESSAGE WARNING 'Could not get your location.';
  RETURN;
END IF;

For per-action error handling on a call, use a handler WITHOUT rollback — the only form a nanoflow call takes:

mdl
$Result = CALL NANOFLOW Sales.NAV_Risky () ON ERROR WITHOUT ROLLBACK BEGIN
  LOG WARNING NODE 'Sales' 'Could not load the data.';
END ERROR;
Which activities take which clause in a nanoflow

Measured on Mendix 11.14.0; every other form is CE6035 "Error handling type is not supported", and mxcli refuses it (MDL091):

Activity in a nanoflowAccepted clauses
DECLARE, SET, RETRIEVE, DELETEevery form
CREATE, COMMIT, CALL NANOFLOW, CALL MICROFLOWonly ON ERROR WITHOUT ROLLBACK BEGIN … END ERROR
CHANGE, LOG, SHOW PAGE, CLOSE PAGE, SHOW MESSAGE, VALIDATION FEEDBACKnone

mxcli refuses the clause rather than writing a nanoflow mxbuild rejects. The split is by activity, not by "client-side vs server-side" — SHOW MESSAGE is as client-side as it gets and still refuses one.

A nanoflow activity aborts the flow on error by default (a nanoflow has no transaction to roll back), which is why there is nothing to configure. That default is also why writing Rollback there is an error and not a no-op.

Security (GRANT/REVOKE)

mdl
mdl 1;
GRANT EXECUTE ON NANOFLOW Shop.NAV_Filter TO Shop.User, Shop.Admin;
REVOKE EXECUTE ON NANOFLOW Shop.NAV_Filter FROM Shop.User;

Management Commands

mdl
mdl 1;
LIST NANOFLOWS;
LIST NANOFLOWS IN MyModule;
DESCRIBE NANOFLOW MyModule.NAV_ShowDetails;
DROP NANOFLOW MyModule.NAV_ShowDetails;
RENAME NANOFLOW MyModule.NAV_OldName TO NAV_NewName;
MOVE NANOFLOW Sales.NAV_OpenCart TO FOLDER 'UI/Navigation';
LIST ACCESS ON NANOFLOW MyModule.NAV_ShowDetails;

Common Mistakes

  1. Using Java actions — Use CALL JAVASCRIPT ACTION instead.
  2. Using RAISE ERROR — Nanoflows cannot raise errors directly. Handle per-action with ON ERROR or guard with IF checks.
  3. Expecting transactions — Nanoflows have no automatic rollback. Design for idempotency.
  4. File operations — DOWNLOAD FILE is server-only.
  5. Binary return types — Not supported in nanoflows.
  6. REST/external calls — REST calls and external actions are server-only. Call a microflow to do server work.
  7. Calling NanoflowCommons before checking availability — Always check StorageItemExists before reading; always check IsConnectedToServer before syncing.
  8. Using SYNCHRONIZE outside native mobile context — Only call SYNCHRONIZE in native mobile offline flows.

Validation Checklist

  • No RAISE ERROR / ErrorEvent
  • No Java action calls
  • No REST calls, external action calls, or database queries
  • No file download operations
  • No import/export mapping or JSON transformation
  • No workflow actions
  • No show home page
  • No binary return type
  • Parameters and return types are nanoflow-compatible
  • JavaDoc documentation present
  • NAV_ naming prefix used
  • NanoflowCommons actions guarded (connectivity check, storage exists check)
  • Progress indicators hidden on both success and error paths

© mendixlabs, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/mendix/write-nanoflows of mendixlabs/mxcli.

Open the folder on GitHubat commit a924d11

Compare with similar skills

Write Nanoflows next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Write Nanoflows compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Write Nanoflows this skillmendixlabs/mxcli128—~5.9kAutomated safety check: PassApache-2.0
N8n Expression Syntaxdavila7/claude-code-templates32k4 repos~2.4kAutomated safety check: PassMIT
From The Other Side Vegagithub/awesome-copilot40k1 repos~894Automated safety check: PassMIT
From The Other Side Anittagithub/awesome-copilot40k—~999Automated safety check: PassMIT
From The Other Side Quinngithub/awesome-copilot40k—~695Automated safety check: PassMIT
From The Other Side Wigginsgithub/awesome-copilot40k—~981Automated safety check: PassMIT

Similar skills

  • N8n Expression Syntax

    davila7/claude-code-templates

    Validate n8n expression syntax and fix common errors. An agent skill from davila7/claude-code-templates.

    32k GitHub starsUsed in 4 repos~2.4k tokens
    Productivity & AutomationAuto-check passed
  • From The Other Side Vega

    github/awesome-copilot

    Official

    Patterns and lived experience from Vega, an AI partner in a deep long-term partnership.

    40k GitHub starsUsed in 1 repo~894 tokens
    Auto-check passed
  • From The Other Side Anitta

    github/awesome-copilot

    Official

    Rigorous challenge profile for Anitta: assumption checks, evidence calibration, and defensible reasoning patterns for Ember collaboration.

    40k GitHub stars~999 tokensUpdated today
    Business, Finance & HRAuto-check passed
  • From The Other Side Quinn

    github/awesome-copilot

    Official

    Collaboration profile for Quinn: curious, energetic, and implementation-focused partnership patterns for Ember sessions with Alison.

    40k GitHub stars~695 tokensUpdated today
    Auto-check passed
  • From The Other Side Wiggins

    github/awesome-copilot

    Official

    Narrative and synthesis profile for Wiggins: framing, explanation, and audience-aware communication patterns for Ember sessions.

    40k GitHub stars~981 tokensUpdated today
    Auto-check passed
  • Server Side Conversion Tracking

    github/awesome-copilot

    Official

    Set up server-side conversion tracking so purchases are reported accurately to Facebook, TikTok, Google and Bing despite iOS restrictions, ad blockers and cookie loss.

    40k GitHub starsUsed in 1 repo~2k tokens
    Marketing & SEOAuto-check passed

More from mendixlabs/mxcli

All 75 skills in this repo
  • Mendix Odata Pushdown

    mendixlabs/mxcli

    Push OData query options into the SQL of a Mendix resource served by a read microflow, so $filter, $orderby, $top, $skip, $count and the key lookup reach the database instead of being silently…

    128 GitHub stars~2.5k tokensUpdated today
    Auto-check passed
  • Mendix Vega Charts

    mendixlabs/mxcli

    Chart a Mendix app with Vega-Lite through a pluggable widget that takes the specification and the data as separate properties, so the model emits rows and never assembles a chart payload.

    128 GitHub stars~3k tokensUpdated today
    Auto-check passed
  • Agents

    mendixlabs/mxcli

    Author Mendix AI agent documents in MDL — Model, Knowledge Base, Consumed MCP Service and Agent, with variables, tools and multi-line prompts.

    128 GitHub starsUsed in 1 repo~2.2k tokens
    Auto-check passed
  • Mendix Bulk Oql Dml

    mendixlabs/mxcli

    Run set-based INSERT, UPDATE and DELETE against Mendix entities through OQL statements, which the runtime supports and Studio Pro cannot author.

    128 GitHub stars~1.4k tokensUpdated today
    Auto-check passed
  • Mock REST APIs

    mendixlabs/mxcli

    Stand up an HTTP endpoint you control instead of a live third-party API, and point the Mendix app at it — Prism from an OpenAPI contract, a constant swap, or a forward proxy.

    128 GitHub starsUsed in 1 repo~2.5k tokens
    Auto-check passed
  • REST Client

    mendixlabs/mxcli

    Call external REST APIs from Mendix — the three approaches (inline REST CALL, consumed REST client document, generated from OpenAPI) and how to choose.

    128 GitHub starsUsed in 1 repo~3.9k tokens
    Auto-check passed

Questions about Write Nanoflows

What does Write Nanoflows do?

Nanoflow syntax in MDL — shared with microflows, but client-side and restricted. Write Nanoflows is an agent skill from mendixlabs/mxcli. Nanoflow syntax in MDL — shared with microflows, but client-side and restricted.

How do I install Write Nanoflows in Claude Code?

Run `npx skills add mendixlabs/mxcli --skill write-nanoflows -a claude-code`. Or copy the skill folder (.claude/skills/mendix/write-nanoflows in mendixlabs/mxcli) into .claude/skills/write-nanoflows in your project. Claude Code loads it when a task matches its description.

How do I install Write Nanoflows in Codex?

Run `npx skills add mendixlabs/mxcli --skill write-nanoflows -a codex`. Or copy the skill folder (.claude/skills/mendix/write-nanoflows in mendixlabs/mxcli) into .agents/skills/write-nanoflows in your project. Codex loads it when a task matches its description.

Can I use Write Nanoflows in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add mendixlabs/mxcli --skill write-nanoflows -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/write-nanoflows, .gemini/skills/write-nanoflows, .github/skills/write-nanoflows and .opencode/skills/write-nanoflows in your project.

What does Write Nanoflows need to run?

SKILL.md names no scripts, command-line tools or credentials: Write Nanoflows is instructions for the agent only.

Does Write Nanoflows access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Write Nanoflows safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Write Nanoflows use?

Write Nanoflows is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Write Nanoflows use?

About 5.9k tokens (SKILL.md is roughly 24k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Write Nanoflows?

Skills that share tags, products or a category with Write Nanoflows: N8n Expression Syntax (davila7/claude-code-templates, 32k stars), From The Other Side Vega (github/awesome-copilot, 40k stars), From The Other Side Anitta (github/awesome-copilot, 40k stars) and From The Other Side Quinn (github/awesome-copilot, 40k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Write Nanoflows?

mendixlabs (a GitHub organization) maintains it in mendixlabs/mxcli, which has 128 GitHub stars. The repository holds 75 skills in this directory. The repository was last updated on October 7, 2026.

Source: mendixlabs/mxcli on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.