Pull up a chair!
Discussions is your place to get to know your peers, tackle the bigger challenges together, and have fun along the way.
- Want to see the latest updates? Follow the Highlights!
- Looking for techniques improve your MATLAB or Simulink skills? Tips & Tricks has you covered!
- Sharing the perfect math joke, pun, or meme? Look no further than Fun!
- Think there's a channel we need? Tell us more in Ideas
Updated Discussions
The "Issues" with Constant Properties
MATLABs Constant properties can be rather difficult to deal with at times. For those unfamiliar there are two distinct behaviors when accessing constant properties of a class. If a "static" pattern is used ClassName.PropName the the value, as it was assigned to the property is returned; that is to say that you will have a nargout of 1. But, rather frustratingly, if an instance of the class is used when accessing the constant property, such as ArrayOfClassName.PropName then your nargout will be equivalent to the number of elements in the array; this means that functionally the constant property accessing scheme is identical to that of the element wise properties you find on "instance" properties.
Motivation for Correcting Constant Property Behavior
This can be frustraing since constant properties are conceptually designed to tie data to a class. You could see this design pattern being useful where a super class were to define an abstract constant property, that would drive the behavior of subclasses; the subclasses define the value of the property and the super class uses it. I would like to use this design to develop a custom display "MatrixDisplay" focused mixin (like the internal matlab.mixin.internal.MatrixDisplay). The idea is that missing element labels, invalid handle element labels, and other semantic values can be configured by the subclasses, conveniently just by setting the constant properties; these properties will be used by the super class to substitute the display strings of appropriate elements. Most of the processing will happen within the super class as to enable simple, low-investment, opt-in display options for array style classes.
The issue is that you can not rely on constant property access to return the appropriate value when the instance you've been passed is empty. This also happens with excessive outputs when the instance is non-scalar, but those extra values from the CSL are just ignored, while Id imagine there is an effect on performance from generating the excess outputs (assuming theres no internal optimization for the unused outputs), this case still functions appropriately. As I enjoying exploring MATLAB, I found an internal indexing mixing class in the past that provides far greater control of do indexing; I've done a good deal of neat things with it, though at the cost of great overhead when getting implementing cool "proof of concept/showcase" examples. Today I used it to quickly implement a mix in that "fixes" constant properties such that they always return as though they were called statically from the class name, as opposed to an instance.
A Simplistic Solution
To do this I just intercepted the property indexing, checked if it was constant, and used the DefaultValue property of the metadata to return the value. This works nicely since we are required to attempt to initialize a "dummy" scalar array, or generate a function handle; both of those would likely be slower, and in the former case, may not be possible depending on the subclass implementation. It is worth noting that this method of querying the value from metadata is safe because constant properties are immutable and thus must be established as the class is loaded. Below is the small utility class I have implemented to get predictable constant variable access into classes that benefit from it. Lastly it is worth noting that I've not torture testing the rerouting of the indexing we aren't intercepting, in my limited play its behaved as expected but it may be worth looking over if you end up playing around with this and notice abnormal property assignment or reading from non-constant properties.
Sample Class Implementation
classdef(Abstract, HandleCompatible) ConstantProperty < matlab.mixin.internal.indexing.RedefinesDotProperties
%ConstantProperty Returns instance indexed constant properties as though they were statically indexed.
% This class overloads property access to check if the indexed property is constant and return it properly.
%% Property membership utility methods
methods(Access=private)
function [isConst, isProp] = isConstantProp(obj, prop, options)
%isConstantProp Determine if the input property names are constant properties of the input
arguments
obj mixin.ConstantProperty;
prop string;
options.Flatten (1, 1) logical = false;
end
% Store the cache to avoid rechecking string membership and parsing metadata
persistent class_cache
% Initialize cache for all subclasses to maintain their own caches
if(isempty(class_cache))
class_cache = configureDictionary("string", "dictionary");
end
% Gather the current class being analyzed
classname = string(class(obj));
% Check if the current class has a cache, if not make one
if(~isKey(class_cache, classname))
class_cache(classname) = configureDictionary("string", "struct");
end
% Alias the current classes cache
prop_cache = class_cache(classname);
% Check which inputs are already cached
isCached = isKey(prop_cache, prop);
% Add any values that have yet to be cached to the cache
if(any(~isCached, "all"))
% Flatten cache additions
props = row(prop(~isCached));
% Gather the meta-property data of the input object and determine if inputs are listed properties
mc_props = metaclass(obj).PropertyList;
% Determine which properties are keys
[isConst, idx] = ismember(props, string({mc_props.Name}));
idx = idx(isConst);
% Check which of the inputs are constant properties
isConst = repmat(isConst, 2, 1);
isConst(1, isConst(1, :)) = [mc_props(idx).Constant];
% Parse the results into structs for caching
cache_values = cell2struct(num2cell(isConst), ["isConst"; "isProp"]);
prop_cache(props) = row(cache_values);
% Re-sync the cache
class_cache(classname) = prop_cache;
end
% Extract results from the cache
values = prop_cache(prop);
if(options.Flatten)
% Split and reshape output data
sz = size(prop);
isConst = reshape(values.isConst, sz);
isProp = reshape(values.isProp, sz);
else
isConst = struct2cell(values);
end
end
function [isConst, isProp] = isConstantIdxOp(obj, idxOp)
%isConstantIdxOp Determines if the idxOp is referencing a constant property.
arguments
obj mixin.ConstantProperty;
idxOp (1, :) matlab.indexing.IndexingOperation;
end
import matlab.indexing.IndexingOperationType;
if(idxOp(1).Type == IndexingOperationType.Dot)
[isConst, isProp] = isConstantProp(obj, idxOp(1).Name);
else
[isConst, isProp] = deal(false);
end
end
function A = getConstantProperty(obj, idxOp)
%getConstantProperty Returns the value of a constant property using a static reference pattern.
arguments
obj mixin.ConstantProperty;
idxOp (1, :) matlab.indexing.IndexingOperation;
end
A = findobj(metaclass(obj).PropertyList, "Name", idxOp(1).Name).DefaultValue;
end
end
%% Dot indexing methods
methods(Access = protected)
function A = dotReference(obj, idxOp)
arguments(Input)
obj mixin.ConstantProperty;
idxOp (1, :) matlab.indexing.IndexingOperation;
end
arguments(Output, Repeating)
A
end
% Force at least one output
N = max(1, nargout);
% Check if the indexing operation is a property, and if that property is constant
[isConst, isProp] = isConstantIdxOp(obj, idxOp);
if(~isProp)
% Error on invalid properties
throw(MException( ...
"JB:mixin:ConstantProperty:UnrecognizedProperty", ...
"Unrecognized property '%s'.", ...
idxOp(1).Name ...
));
elseif(isConst)
% Handle forwarding indexing operations
if(isscalar(idxOp))
% Direct assignment
[A{1:N}] = getConstantProperty(obj, idxOp);
else
% First extract constant property then forward indexing operations
tmp = getConstantProperty(obj, idxOp);
[A{1:N}] = tmp.(idxOp(2:end));
end
else
% Handle forwarding indexing operations
if(isscalar(idxOp))
% Unfortunately we can't just recall obj.(idxOp) to use default/built-in so we manually extract
[A{1:N}] = obj.(idxOp.Name);
else
% Otherwise let built-in handling proceed
tmp = obj.(idxOp(1).Name);
[A{1:N}] = tmp.(idxOp(2:end));
end
end
end
function obj = dotAssign(obj, idxOp, values)
arguments(Input)
obj mixin.ConstantProperty;
idxOp (1, :) matlab.indexing.IndexingOperation;
end
arguments(Input, Repeating)
values
end
% Handle assignment based on presence of forward indexing
if(isscalar(idxOp))
% Simple broadcasted assignment
[obj.(idxOp.Name)] = deal(values{:});
else
% Initialize the intermediate values and expand the values for assignment
tmp = {obj.(idxOp(1).Name)};
[tmp.(idxOp(2:end))] = deal(values{:});
% Reassign the modified data to the output object
[obj.(idxOp(1).Name)] = deal(tmp{:});
end
end
function n = dotListLength(obj, idxOp, idxCnt)
arguments(Input)
obj mixin.ConstantProperty;
idxOp (1, :) matlab.indexing.IndexingOperation;
idxCnt (1, :) matlab.indexing.IndexingContext;
end
if(isConstantIdxOp(obj, idxOp))
if(isscalar(idxOp))
% Constant properties will also be 1
n = 1;
else
% Checking forwarded indexing operations on the scalar constant property
n = listLength(obj.(idxOp(1).Name), idxOp(2:end), idxCnt);
end
else
% Check the indexing operation normally
% n = listLength(obj, idxOp, idxCnt);
n = numel(obj);
end
end
end
end
MATLAB MCP Core Server v0.6.0 has been released onGitHub: https://github.com/matlab/matlab-mcp-core-server/releases/tag/v0.6.0
Release highlights:
- New cross-platform MCP Bundle; one-click installation in Claude Desktop
Enhancements:
- Provide structured output from check_matlab_code and additional information for MATLAB R2022b onwards
- Made project_path optional in evaluate_matlab_code tool for simpler tool calls
- Enhanced detect_matlab_toolboxes output to include product version
Bug fixes:
- Updated MCP Go SDK dependency to address CVE.
We encourage you to try this repository and provide feedback. If you encounter a technical issue or have an enhancement request, create an issue https://github.com/matlab/matlab-mcp-core-server/issues
At the present time, the following problems are known in MATLAB Answers itself:
- Symbolic output is not displaying. The work-around is to disp(char(EXPRESSION)) or pretty(EXPRESSION)
- Symbolic preferences are sometimes set to non-defaults
Missed a crowd‑favorite session feautring Marko Gecic at Infineon and Lucas Garcia at MathWorks?
This talk shows how to verify and test AI for real‑time, safety‑critical systems using an AI virtual sensor that estimates motor rotor position on an Infineon AURIX TC4x microcontroller. Built with MATLAB and Simulink, the demo covers training, verification, and real‑time control across a wide range of operating conditions.
You’ll see practical techniques to test robustness, measure sensitivity to input perturbations, and detect out‑of‑distribution behavior—critical steps for meeting standards like ISO 26262 and ISO 8800. The session also highlights how Model‑Based Design leverages AURIX TC4x features such as the PPU and CDSP to deploy AI with confidence.

I wanted to share something I've been thinking about to get your reactions. We all know that most MATLAB users are engineers and scientists, using MATLAB to do engineering and science. Of course, some users are professional software developers who build professional software with MATLAB - either MATLAB-based tools for engineers and scientists, or production software with MATLAB Coder, MATLAB Compiler, or MATLAB Web App Server.
I've spent years puzzling about the very large grey area in between - engineers and scientists who build useful-enough stuff in MATLAB that they want their code to work tomorrow, on somebody else's machine, or maybe for a large number of users. My colleagues and I have taken to calling them "Reluctant Developers". I say "them", but I am 1,000% a reluctant developer.
I first hit this problem while working on my Mech Eng Ph.D. in the late 90s. I built some elaborate MATLAB-based tools to run experiments and analysis in our lab. Several of us relied on them day in and day out. I don't think I was out in the real world for more than a month before my advisor pinged me because my software stopped working. And so began a career of building amazing, useful, and wildly unreliable tools for other MATLAB users.
About a decade ago I noticed that people kept trying to nudge me along - "you should really write tests", "why aren't you using source control". I ignored them. These are things software developers do, and I'm an engineer.
I think it finally clicked for me when I listened to a talk at a MATLAB Expo around 2017. An aerospace engineer gave a talk on how his team had adopted git-based workflows for developing flight control algorithms. An attendee asked "how do you have time to do engineering with all this extra time spent using software development tools like git"? The response was something to the effect of "oh, we actually have more time to do engineering. We've eliminated all of the waste from our unamanaged processes, like multiple people making similar updates or losing track of the best version of an algorithm." I still didn't adopt better practices, but at least I started to get a sense of why I might.
Fast-forward to today. I know lots of users who've picked up software dev tools like they are no big deal, but I know lots more who are still holding onto their ad-hoc workflows as long as they can. I'm on a bit of a campaign to try to change this. I'd like to help MATLAB users recognize when they have problems that are best solved by borrowing tools from our software developer friends, and then give a gentle onramp to using these tools with MATLAB.
I recently published this guide as a start:
Waddya think? Does the idea of Reluctant Developer resonate with you? If you take some time to read the guide, I'd love comments here or give suggestions by creating Issues on the guide on GitHub (there I go, sneaking in some software dev stuff ...)
k-Wave is a MATLAB community toolbox with a track record that includes over 2,500 citations on Google Scholar and over 7,500 downloads on File Exchange. It is built for the "time-domain simulation of acoustic wave fields" and was recently highlighted as a Pick of the Week.
In December, release v1.4.1 was published on GitHub including two new features led by the project's core contributors with domain experts in this field. This first release in several years also included quality and maintainability enhancements supported by a new code contributor, GitHub user stellaprins, who is a Research Software Engineer at University College London. Her contributions in 2025 spanned several software engineering aspects, including the addition of continuous integration (CI), fixing several bugs, and updating date/time handling to use datetime. The MATLAB Community Toolbox Program sponsored these contributions, and welcomes to see them now integrated into a release for k-Wave users.
I'd like to share some work from Controls Educator and long term collabortor @Dr James E. Pickering from Harper Adams University. He is currently developing a teaching architecture for control engineering (ACE-CORE) and is looking for feedback from the engineering community.
ACE-CORE is delivered through ACE-Box, a modular hardware platform (Base + Sense, Actuate). More on the hardware here: What is the ACE-Box?
The Structure
(1) Comprehend
Learners build conceptual understanding of control systems by mapping block diagrams directly to physical components and signals. The emphasis is on:
- Feedback architecture
- Sensing and actuation
- Closed-loop behaviour in practical terms
(2) Operate
Using ACE-Box (initially Base + Sense), learners run real closed-loop systems. The learners measure, actuate, and observe real phenomena such as: Noise, Delay, Saturation
Engineering requirements (settling time, overshoot, steady-state error, etc.) are introduced explicitly at this stage.
After completing core activities (e.g., low-pass filter implementation or PID tuning), the pathway branches (see the attached diagram)
(3a) Refine (Option 1) Students improve performance through structured tuning:
- PID gains
- Filter coefficients
- Performance trade-offs
The focus is optimisation against defined engineering requirements.
(3b) Refine → Engineer (Option 2)
Modelling and analytical design become more explicit at this stage, including:
- Mathematical modelling
- Transfer functions
- System identification
- Stability analysis
- Analytical controller design
Why the Branching?
The structure reflects two realities:
- Engineers who operate and refine existing control systems
- Engineers who design control systems through mathematical modelling
Your perspective would be very valuable:
- Does this progression reflect industry reality?
- Is the branching structure meaningful?
- What blind spots do you see?
Constructive critique is very welcome. Thank you!
I was reading Yann Debray's recent post on automating documentation with agentic AI and ended up spending more time than expected in the comments section. Not because of the comments themselves, but because of something small I noticed while trying to write one. There is no writing assistance of any kind before you post. You type, you submit, and whatever you wrote is live.
For a lot of people that is fine. But MATLAB Central has users from all over the world, and I have seen questions on MATLAB Answers where the technical reasoning is clearly correct but the phrasing makes it hard to follow. The person knew exactly what they meant. The platform just did not help them say it clearly.
I want to share a few ideas around this. They are not fully formed proposals but I think the direction is worth discussing, especially given how much AI tooling MathWorks has built recently.
What the platform has today
When you write a post in Discussions or an answer in MATLAB Answers, the editor gives you basic formatting options. Code blocks, some text styling, that is mostly it. The AI Chat Playground exists as a separate tool, and MATLAB Copilot landed in R2025a for the desktop. But none of that is inside the editor where people actually write community content.
Four things are missing that I think would make a real difference.
Grammar and clarity checking before you post
Not a forced rewrite. Just an optional Check My Draft button that highlights unclear sentences or anything that might trip a reader up. The user reviews it, decides what to change, then posts.
What makes this different from plugging in Grammarly is that a general-purpose tool does not know that readtable is a MATLAB function. It does not know that NaN, inf, or linspace are not errors. A MATLAB-aware checker could flag things that generic tools miss, like someone writing readTable instead of readtable in a solution post.
The llms-with-matlab package already exists on GitHub. Something like this could be built on top of it with a prompt that includes MATLAB function vocabulary as context. That is not a large lift given what is already there.
Translation support
MATLAB Central already has a Japanese-language Discussions channel. That tells you something about the community. The platform is global but most of the technical content is in English, and there is a real gap there.
Two options that would help without being intrusive:
- Write in your language, click Translate, review the English version, then post. The user is still responsible for what goes live.
- A per-post Translate button so readers can view content in a language they are more comfortable with, without changing what is stored on the platform.
A student who has the right answer to a MATLAB Answers question might not post it because they are not confident writing in English. Translation support changes that. The community gets the answer and the contributor gets the credit.
In-editor code suggestions
When someone writes a solution post they usually write the code somewhere else, test it, copy it, paste it, and format it manually. An in-editor assistant that generates a starting scaffold from a plain-text description would cut that loop down.
The key word is scaffold, not a finished answer. The label should say something like AI-generated draft, verify before posting so it is clear the person writing is still accountable. MATLAB Copilot already does something close to this inside the desktop editor. Bringing a lighter version of it into the community editor feels like a natural extension of what already exists.
A note on feasibility
These ideas are not asking for something from scratch. MathWorks already has llms-with-matlab, the MCP Core Server, and MATLAB Copilot as infrastructure. Grammar checking and translation are well-solved problems at the API level. The MATLAB-specific vocabulary awareness is the part worth investing in. None of it should be on by default. All of it should be opt-in and clearly labeled when it runs.
One more thing: diagrams in posts
Right now the only way to include a diagram in a post is to make it externally and upload an image. A lightweight drag-and-drop diagram tool inside the editor would let people show a process or structure quickly without leaving the platform. Nothing complex, just boxes and arrows. For technical explanations it is often faster to draw than to write three paragraphs.
What I am curious about
I am a Data Science student at CU Boulder and an active MATLAB user. These ideas came up while using the platform, not from a product roadmap. I do not know what is already being discussed internally at MathWorks, so it is entirely possible some of this is in progress.
Has anyone else run into the same friction points when writing on MATLAB Central? And for anyone at MathWorks who works on the community platform, is the editor something that gets investment alongside the product tools?
Happy to hear where I am wrong on the feasibility side too.
AI assisted with grammar and framing. All ideas and editorial decisions are my own.
Featuring: Dr. Arthur Clavière, Collins Aerospace
How can we be confident that a machine learning model will behave safely on data it’s never seen—especially in avionics? In this session, Dr. Arthur Clavière introduces a formal methods approach to verifying maching learning generalization. The talk highlights how formal verification can be apploied toneural networks in safety-critical avionics systems.
💬 Discussion question:
Where do you see formal verification having the biggest impact on deploying ML in safety‑critical systems—and what challenges still stand in the way?
Join the conversation below 👇
Hi,
I don't know why really. Why is there seems a difference between daily average that calculated with .csv file that has exported directly from the channel.
and calculation with the ThingSpeak Daily Average API, there is a lot of difference at the moment.
Why does this happens, and how should I fix this issue?
Attached image file is daily average that has been retrived through the API,
And attached excel file is raw data from the channel.
Thank you.



You may have come across code that looks like that in some languages:
stubFor(get(urlPathEqualTo("/quotes"))
.withHeader("Accept", equalTo("application/json"))
.withQueryParam("s", equalTo(monitoredStock))
.willReturn(aResponse())
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\\"symbol\\": \\"XYZ\\", \\"bid\\": 20.2, " + "\\"ask\\": 20.6}")))
That’s Java. Even if you can’t fully decipher it, you can get a rough idea of what it is supposed to do, build a rather complex API query.
Or you may be familiar with the following similar and frequent syntax in Python:
import seaborn as sns
sns.load_dataset('tips').sample(10, random_state=42).groupby('day').mean()
Here’s is how it works: multiple method calls are linked together in a single statement, spanning over one or several lines, usually because each method returns the same object or another object that supports further calls.
That technique is called method chaining and is popular in Object-Oriented Programming.
A few years ago, I looked for a way to write code like that in MATLAB too. And the answer is that it can be done in MATLAB as well, whevener you write your own class!
Implementing a method that can be chained is simply a matter of writing a method that returns the object itself.
In this article, I would like to show how to do it and what we can gain from such a syntax.
Example
A few years ago, I first sought how to implement that technique for a simulation launcher that had lots of parameters (far too many):
lauchSimulation(2014:2020, true, 'template', 'TmplProd', 'Priority', '+1', 'Memory', '+6000')
As you can see, that function takes 2 required inputs, and 3 named parameters (whose names aren’t even consistent, with ‘Priority’ and ‘Memory’ starting with an uppercase letter when ‘template’ doesn’t).
(The original function had many more parameters that I omit for the sake of brevity. You may also know of such functions in your own code that take a dozen parameters which you can remember the exact order.)
I thought it would be nice to replace that with:
SimulationLauncher() ...
.onYears(2014:2020) ...
.onDistributedCluster() ... % = equivalent of the previous "true"
.withTemplate('TmplProd') ...
.withPriority('+1') ...
.withReservedMemory('+6000') ...
.launch();
The first 6 lines create an object of class SimulationLauncher, calls several methods on that object to set the parameters, and lastly the method launch() is called, when all desired parameters have been set.
To make it cleared, the syntax previously shown could also be rewritten as:
launcher = SimulationLauncher();
launcher = launcher.onYears(2014:2020);
launcher = launcher.onDistributedCluster();
launcher = launcher.withTemplate('TmplProd');
launcher = launcher.withPriority('+1');
launcher = launcher.withReservedMemory('+6000');
launcher.launch();
Before we dive into how to implement that code, let’s examine the advantages and drawbacks of that syntax.
Benefits and drawbacks
Because I have extended the chained methods over several lines, it makes it easier to comment out or uncomment any one desired option, should the need arise. Furthermore, we need not bother any more with the order in which we set the parameters, whereas the usual syntax required that we memorize or check the documentation carefully for the order of the inputs.
More generally, chaining methods has the following benefits and a few drawbacks:
Benefits:
- Conciseness: Code becomes shorter and easier to write, by reducing visual noise compared to repeating the object name.
- Readability: Chained methods create a fluent, human-readable structure that makes intent clear.
- Reduced Temporary Variables: There's no need to create intermediary variables, as the methods directly operate on the object.
Drawbacks:
- Debugging Difficulty: If one method in a chain fails, it can be harder to isolate the issue. It effectively prevents setting breakpoints, inspecting intermediate values, and identifying which method failed.
- Readability Issues: Overly long and dense method chains can become hard to follow, reducing clarity.
- Side Effects: Methods that modify objects in place can lead to unintended side effects when used in long chains.
Implementation
In the SimulationLauncher class, the method lauch performs the main operation, while the other methods just serve as parameter setters. They take the object as input and return the object itself, after modifying it, so that other methods can be chained.
classdef SimulationLauncher
properties (GetAccess = private, SetAccess = private)
years_
isDistributed_ = false;
template_ = 'TestTemplate';
priority_ = '+2';
memory_ = '+5000';
end
methods
function varargout = launch(obj)
% perform whatever needs to be launched
% using the values of the properties stored in the object:
% obj.years_
% obj.template_
% etc.
end
function obj = onYears(obj, years)
assert(isnumeric(years))
obj.years_ = years;
end
function obj = onDistributedCluster(obj)
obj.isDistributed_ = true;
end
function obj = withTemplate(obj, template)
obj.template_ = template;
end
function obj = withPriority(obj, priority)
obj.priority_ = priority;
end
function obj = withMemory( obj, memory)
obj.memory_ = memory;
end
end
end
As you can see, each method can be in charge of verifying the correctness of its input, independantly. And what they do is just store the value of parameter inside the object. The class can define default values in the properties block.
You can configure different launchers from the same initial object, such as:
launcher = SimulationLauncher();
launcher = launcher.onYears(2014:2020);
launcher1 = launcher ...
.onDistributedCluster() ...
.withReservedMemory('+6000');
launcher2 = launcher ...
.withTemplate('TmplProd') ...
.withPriority('+1') ...
.withReservedMemory('+7000');
If you call the same method several times, only the last recorded value of the parameter will be taken into acount:
launcher = SimulationLauncher();
launcher = launcher ...
.withReservedMemory('+6000') ...
.onDistributedCluster() ...
.onYears(2014:2020) ...
.withReservedMemory('+7000') ...
.withReservedMemory('+8000');
% The value of "memory" will be '+8000'.
If the logic is still not clear to you, I advise you play a bit with the debugger to better understand what’s going on!
Conclusion
I love how the method chaining technique hides the minute detail that we don’t want to bother with when trying to understand what a piece of code does.
I hope this simple example has shown you how to apply it to write and organise your code in a more readable and convenient way.
Let me know if you have other questions, comments or suggestions. I may post other examples of that technique for other useful uses that I encountered in my experience.
In the sequence of previous suggestion in Meta Cody comment for the 'My Problems' page, I also suggest to add a red alert for new comments in 'My Groups' page.
Thank you in advance.
I got an email message that says all the files I've uploaded to the File Exchange will be given unique names. Are these new names being applied to my files automatically? If so, do I need to download them to get versions with the new name so that if I update them they'll have the new name instead of the name I'm using now?
Hello All,
This is my first post here so I hope its in the right place,
I have built myself a GW consisting of a RAK2245 concentrator and a Raspberry Pi, Also an Arduino end device from this link https://tum-gis-sensor-nodes.readthedocs.io/en/latest/dragino_lora_arduino_shield/README.html
Both projects work fine and connect to TTN whereby packets of data from the end device can be seen in the TTN console.
I now want to create a Webhook in TTN for Thingspeak which would hopefull allow me to see Temperature , Humidity etc in graphical form.
My question, does thingspeak support homebuilt devices or is it focused on comercially built devices ?
I have spent many hours trying to find data hosting site that is comepletely free for a few devices and not to complicated to setup as some seem to be a nightmare. Thanks for any support .
Over the past few days I noticed a minor change on the MATLAB File Exchange:
For a FEX repository, if you click the 'Files' tab you now get a file-tree–style online manager layout with an 'Open in new tab' hyperlink near the top-left. This is very useful:
If you want to share that specific page externally (e.g., on GitHub), you can simply copy that hyperlink. For .mlx files it provides a perfect preview. I'd love to hear your thoughts.
EXAMPLE:
🤗🤗🤗
I coded this app to solve the 20 or so test cases included with the Cody problem 'visually' and step-by-step. For extra fun, it can also be used to play the game... Any comments or suggestions welcome!
How can I found my license I'd and password, so please provide me my id
🚀 Unlock Smarter Control Design with AI
What if AI could help you design better controllers—faster and with confidence?
In this session, Naren Srivaths Raman and Arkadiy Turevskiy (MathWorks) show how control engineers are using MATLAB and Simulink to integrate AI into real-world control design and implementation.
You’ll see how AI is being applied to:
🧠 Advanced plant modeling using nonlinear system identification and reduced order modeling
📡 Virtual sensors and anomaly detection to estimate hard-to-measure signals
🎯 Datadriven control design, including nonlinear MPC with neural statespace models and reinforcement learning
⚡ Productivity gains with generative AI, powered by MATLAB Copilot
Giving All Your Claudes the Keys to Everything

Introduction
This started as a plumbing problem. I wanted to move files between Claude’s cloud container and my Mac faster than base64 encoding allows. What I ended up building was something more interesting: a way for every Claude – Desktop, web browser, iPhone – to control my entire computing environment with natural language. MATLAB, Keynote, LaTeX, Chrome, Safari, my file system, text-to-speech. All of it, from any device, through a 200-line Python server and a free tunnel.
It isn’t quite the ideal universal remote. Web and iPhone Claude do not yet have the agentic Playwright-based web automation capabilities available to Claude desktop via MCP. A possible solution may be explored in a later post.
Background information
The background here is a series of experiments I’ve been running on giving AI desktop apps direct access to local tools. See How to set up and use AI Desktop Apps with MATLAB and MCP servers which covers the initial MCP setup, A universal agentic AI for your laptop and beyond which describes what Desktop Claude can do once you give it the keys, and Web automation with Claude, MATLAB, Chromium, and Playwright which describes a supercharged browser assistant. This post is about giving such keys to remote Claude interfaces.
Through the Model Context Protocol (MCP), Claude Desktop on my Mac can run MATLAB code, read and write files, execute shell commands, control applications via AppleScript, automate browsers with Playwright, control iPhone apps, and take screenshots. These powers have been limited to the desktop Claude app – the one running on the machine with the MCP servers. My iPhone Claude app and a Claude chat launched in a browser interface each have a Linux container somewhere in Anthropic’s cloud. The container can reach the public internet. Until now, my Mac sat behind a home router with no public IP.
An HTTP server MCP replacement
A solution is a small HTTP server on the Mac. Use ngrok (free tier) to give the Mac a public URL. Then anything with internet access – including any Claude’s cloud container – can reach the Mac via curl.
iPhone/Web Claude -> bash_tool: curl https://public-url/endpoint
-> Internet -> ngrok tunnel -> Mac localhost:8765
-> Python command server -> MATLAB / AppleScript / filesystem
The server is about 200 lines of Python using only the standard library. Two files, one terminal command to start. ngrok provides HTTPS and HTTP Basic Auth with a single command-line flag.
The complete implementation consists of three files:
claude_command_server.py (~200 lines): A Python HTTP server using http.server from the standard library. It implements BaseHTTPRequestHandler with do_GET and do_POST methods dispatching to endpoint handlers. Shell commands are executed via subprocess.run with timeout protection. File paths are validated against allowed roots using os.path.realpath to prevent directory traversal attacks.
start_claude_server.sh (~20 lines): A Bash script that starts the Python server as a background process, then starts ngrok in the foreground. A trap handler ensures both processes are killed on Ctrl+C.
iphone_matlab_watcher.m (~60 lines): MATLAB timer function that polls for command files every second.
The server exposes six GET and six POST endpoints. The GET endpoints thus far handle retrieval: /ping for health checks, /list to enumerate files in a transfer directory, /files/<n> to download a file from that directory, /read/<path> to read any file under allowed directories, and / which returns the endpoint listing itself. The POST endpoints handle execution and writing: /shell runs an allowlisted shell command, /osascript runs AppleScript, /matlab evaluates MATLAB code through a file-watcher mechanism, /screenshot captures the screen and returns a compressed JPEG, /write writes content to a file, and /upload/<n> accepts binary uploads.
File access is sandboxed by endpoint. The /read/ endpoint restricts reads to ~/Documents, ~/Downloads, and ~/Desktop and their subfolders. The /write and /upload endpoints restrict writes to ~/Documents/MATLAB and ~/Downloads. Path traversal is validated – .. sequences are rejected.
The /shell endpoint restricts commands to an explicit allowlist: open, ls, cat, head, tail, cp, mv, mkdir, touch, find, grep, wc, file, date, which, ps, screencapture, sips, convert, zip, unzip, pbcopy, pbpaste, say, mdfind, and curl. No rm, no sudo, no arbitrary execution. Content creation goes through /write.
Two endpoints have no path restrictions: /osascript and /matlab. The /osascript endpoint passes its payload to macOS’s osascript command, which executes AppleScript – Apple’s scripting language for controlling applications via inter-process Apple Events. An AppleScript can open, close, or manipulate any application, read or write any file the user account can access, and execute arbitrary shell commands via “do shell script”. The /matlab endpoint evaluates arbitrary MATLAB code in a persistent session. Both are as powerful as the user account itself. This is deliberate – these are the endpoints that make the server useful for controlling applications. The security boundary is authentication at the tunnel, not restriction at the endpoint.
The MATLAB Workaround
MATLAB on macOS doesn’t expose an AppleScript interface, and the MCP MATLAB tool uses a stdio connection available only from Desktop. So how does iPhone Claude run MATLAB?
An answer is a file-based polling mechanism. A MATLAB timer function checks a designated folder every second for new command files. The remote Claude writes a .m file via the server, MATLAB executes it, writes output to a text file, and sets a completion flag. The round trip is about 2.5 seconds including up to 1 second of polling latency. (This could be reduced by shortening the polling interval or replacing it with Java’s WatchService for near-instant file detection.)
This method provides full MATLAB access from a phone or web Claude, with your local file system available, under AI control. MATLAB Mobile and MATLAB Online do not offer agentic AI access.
Alternate approaches
I’ve used Tailscale Funnel as an alternative tunnel to manually control my MacBook from iPhone but you can’t install Tailscale inside Anthropic’s container. An alternative approach would replace both the local MCP servers and the command server with a single remote MCP server running on the Mac, exposed via ngrok and registered as a custom connector in claude.ai. This would give all three Claude interfaces native MCP tool access including Playwright or Puppeteer with comparable latency but I’ve not tried this.
Security
Exposing a command server to the internet raises questions. The security model has several layers. ngrok handles authentication – every request needs a valid password. Shell commands are restricted to an allowlist (ls, cat, cp, screencapture – no rm, no arbitrary execution). File operations are sandboxed to specific directory trees with path traversal validation. The server binds to localhost, unreachable without the tunnel. And you only run it when you need it.
The AppleScript and MATLAB endpoints are relatively unrestricted in my setup, giving Claude Desktop significant capabilities via MCP. Extending them through an authenticated tunnel is a trust decision.
Initial test results
I ran an identical three-step benchmark from each Claude interface: get a Mac timestamp via AppleScript, compute eigenvalues of a 10x10 magic square in MATLAB, and capture a screenshot. Same Mac, same server, same operations.
| Step | Desktop (MCP) | Web Claude | iPhone Claude |
|------|:------------:|:----------:|:-------------:|
| AppleScript timestamp | ~5ms | 626ms | 623ms |
| MATLAB eig(magic(10)) | 108ms | 833ms | 1,451ms |
| Screenshot capture | ~200ms | 1,172ms | 980ms |
| **Total** | **~313ms** | **2,663ms** | **3,078ms** |
The network overhead is consistent: web and iPhone both add about 620ms per call (the ngrok round trip through residential internet). Desktop MCP has no network overhead at all. The MATLAB variance between web (833ms) and iPhone (1,451ms) is mostly the file-watcher polling jitter – up to a second of random latency depending on where in the polling cycle the command arrives.
All three Claudes got the correct eigenvalues. All three controlled the Mac. The slowest total was 3 seconds for three separate operations from a phone. Desktop is 10x faster, but for “I’m on my phone and need to run something” – 3 seconds is fine.
Other tests

MATLAB: Computations (determinants, eigenvalues), 3D figure generation, image compression. The complete pipeline – compute on Mac, transfer figure to cloud, process with Python, send back – runs in under 5 seconds. This was previously impossible; there was no reasonable mechanism to move a binary file from the container to the Mac.
Keynote: Built multi-slide presentations via AppleScript, screenshotted the results.
TeXShop: Wrote a .tex file containing ten fundamental physics equations (Maxwell through the path integral), opened it in TeXShop, typeset via AppleScript, captured the rendered PDF. Publication-quality typesetting from a phone. I don’t know who needs this at 11 PM on a Sunday, but apparently I do.
Safari: Launched URLs on the Mac from 2,000 miles away. Or 6 feet. The internet doesn’t care.
Finder: Directory listings, file operations, the usual filesystem work.
Text-to-speech: Mac spoke “Hello from iPhone” and “Web Claude is alive” on command. Silly but satisfying proof of concept.
File Transfer: The Original Problem, Solved
Remember, this started because I wanted faster file transfers for desktop Claude. Compare:
| Method | 1 MB file | 5 MB file | Limit |
|--------|-----------|-----------|-------|
| Old (base64 in context) | painful | impossible | ~5 KB |
| Command server upload | 455ms | ~3.6s | tested to 5 MB+ |
| Command server download | 1,404ms | ~7s | tested to 5 MB+ |
The improvement is the difference between “doesn’t work” and “works in seconds.”
Cross-Device Memory
A nice bonus: iPhone and web Claudes can search Desktop conversations using the same memory tools. Context established in a Desktop session – including the server password – can be retrieved from a phone conversation. You do have to ask explicitly (“search my past conversations for the command server”) or insert information into the persistent context using settings rather than assuming Claude will look on its own.
Web Claudes
The most surprising result was web Claude. I expected it to work – same container infrastructure, same bash_tool, same curl. But “expected to work” and “just worked, first try, no special setup” are different things. I opened claude.ai in a browser, gave it the server URL and password, and it immediately ran MATLAB, took screenshots, and made my Mac speak. No configuration, no troubleshooting, no “the endpoint format is wrong” iterations. If you’re logged into claude.ai and the server is running, you have full Mac access from any browser on any device.
What This Means
MCP gave Desktop Claude the keys to my Mac. A 200-line server and a free tunnel duplicated those keys for every other Claude I use. Three interfaces, one Mac, all the same applications, all controlled in natural language.
Additional information
An appendix gives Claude’s detailed description of communications. Codes and instructions are available at the MATLAB File Exchange: Giving All Your Claudes the Keys to Everything.
Acknowledgments and disclaimer
The problem of file transfer was identified by the author. Claude suggested and implemented the method, and the author suggested the generalization to accommodate remote Claudes. This submission was created with Claude assistance. The author has no financial interest in Anthropic or MathWorks.
—————
Appendix: Architecture Comparison
Path A: Desktop Claude with a Local MCP Server
When you type a message in the Desktop Claude app, the Electron app sends it to Anthropic’s API over HTTPS. The LLM processes the message and decides it needs a tool – say, browser_navigate from Playwright. It returns a tool_use block with the tool name and arguments. That block comes back to the Desktop app over the same HTTPS connection.
Here is where the local MCP path kicks in. At startup, the Desktop app read claude_desktop_config.json, found each MCP server entry, and spawned it as a child process on your Mac. It performed a JSON-RPC initialize handshake with each one, then called tools/list to get the tool catalog – names, descriptions, parameter schemas. All those tools were merged and sent to Anthropic with your message, so the LLM knows what’s available.
When the tool_use block arrives, the Desktop app looks up which child process owns that tool and writes a JSON-RPC message to that process’s stdin. The MCP server (Playwright, MATLAB, whatever) reads the request, does the work locally, and writes the result back to stdout as JSON-RPC. The Desktop app reads the result, sends it back to Anthropic’s API, the LLM generates the final text response, and you see it.
The Desktop app is really just a process manager and JSON-RPC router. The config file is a registry of servers to spawn. You can plug in as many as you want – each is an independent child process advertising its own tools. The Desktop app doesn’t care what they do internally. The MCP execution itself adds almost no latency because it’s entirely local, process-to-process on your Mac. The time you perceive is dominated by the two HTTPS round-trips to Anthropic, which all three Claude interfaces share equally.
Path B: iPhone Claude with the Command Server
When you type a message in the Claude iOS app, the app sends it to Anthropic’s API over HTTPS, same as Desktop. The LLM processes the message. It sees bash_tool in its available tools – provided by Anthropic’s container infrastructure, not by any MCP server. It decides it needs to run a curl command and returns a tool_use block for bash_tool.
Here, the path diverges completely from Desktop. There is no iPhone app involvement in tool execution. Anthropic routes the tool_use to a Linux container running in Anthropic’s cloud, assigned to your conversation. This container is the “computer” that iPhone Claude has access to. The container runs the curl command – a real Linux process in Anthropic’s data center.
The curl request goes out over the internet to ngrok’s servers. ngrok forwards it through its persistent tunnel to the claude_command_server.py process running on localhost on your Mac. The command server authenticates the request (basic auth), then executes the requested operation – in this case, running an AppleScript via subprocess.run(['osascript', ...]). macOS receives the Apple Events, launches the target application, and does the work.
The result flows back the same way: osascript returns output to the command server, which packages it as JSON and sends the HTTP response back through the ngrok tunnel, through ngrok’s servers, back to the container’s curl process. bash_tool captures the output. The container sends the tool result back to Anthropic’s API. The LLM generates the text response, and the iPhone app displays it.
The iPhone app is a thin chat client. It never touches tool execution – it only sends and receives chat messages. The container does the curl work, and the command server bridges from Anthropic’s cloud to your Mac. The LLM has to know to use curl with the right URL, credentials, and JSON format. There is no tool discovery, no protocol handshake, no automatic routing. The knowledge of how to reach your Mac is carried entirely in the LLM’s context.
—————
Duncan Carlsmith, Department of Physics, University of Wisconsin-Madison. duncan.carlsmith@wisc.edu
I used Claude Code along with MATLAB's MCP server to develop this animation that morphs between the MATLAB membrane and a 3D heart. Details at Coding a MATLAB Valentine animation with agentic AI » The MATLAB Blog - MATLAB & Simulink
Show me what you can do!
If you share code, may I suggest putting it in a GitHib repo and posting the link here rather than posting the code directly in the forum? When we tried a similar exercise on Vibe-coded Christmas trees, we posted the code directly to a single discussion thread and quickly brought the forum software to its knees.

About Discussions
Discussions is a user-focused forum for the conversations that happen outside of any particular product or project.
Get to know your peers while sharing all the tricks you've learned, ideas you've had, or even your latest vacation photos. Discussions is where MATLAB users connect!
Get to know your peers while sharing all the tricks you've learned, ideas you've had, or even your latest vacation photos. Discussions is where MATLAB users connect!
More Community Areas
MATLAB Answers
Ask & Answer questions about MATLAB & Simulink!
File Exchange
Download or contribute user-submitted code!
Cody
Solve problem groups, learn MATLAB & earn badges!
Blogs
Get the inside view on MATLAB and Simulink!
AI Chat Playground
Use AI to generate initial draft MATLAB code, and answer questions!



