I wrote a simple script to use the GMnotes to track spell slots on tokens (rather than character sheets).  !TokR <label> // Displays current label and associated value.  !TokR <label>+ // Increases value associated with label and displays new value.  !TokR <label>- // Decreases value associated with label and displays new value.  sample list of labels and values:  spell0: 4 spell1: 4 spell2: 2 spell3: 1 potions: 2  Other labels and variables can be used, keeping to the same format (label: value).  on("ready",function(){     on("chat:message",function(msg){         if(msg.type=="api" && msg.content.match(/^!tokR/) && playerIsGM(msg.playerid)){             var reg = /^!tokR ([-a-zA-Z0-9 _]*)([+-])$/ig;             var cmd = reg.exec(msg.content);             var selected = msg.selected;             if (selected===undefined){                 sendChat("tokR","Please select a character.");                 return;             }             var tok = getObj("graphic",selected[0]._id);             var gmnote = tok.get("gmnotes");             var decodedText = decodeURIComponent(gmnote);             if (!cmd) {                 reg = /^!tokR ([-a-zA-Z0-9 _]*)$/ig;                 cmd = reg.exec(msg.content);                 var label = cmd[1];                 var regexstr = label + ": [\\d]\+";                 const labelRegex = new RegExp(regexstr,'ig');                 var match = decodedText.match(labelRegex);                 if (!cmd) {                     sendChat("tokR","Please enter !tokR <label>, !tokR <label>+, or !tokR <label>-")                     return;                 } else {                     if (match){                     sendChat("tokR",match[0]);                     return;                     } else {                         sendChat("tokR","No label found!");                         return;                     }                     return;                 }             } else {                 var label = cmd[1];                 var regexstr = label + ": [\\d]\+";                 const labelRegex = new RegExp(regexstr,'ig');                 var match = decodedText.match(labelRegex);                 let value = match[0];                 value = value.split(' ')[1];                 var args=cmd[2];                 if (args == '+') {                     sendChat("tokR", "Value of " + label + ": " + value);                     value++;                     sendChat ("tokR", "Updated to " + value);                     var valuestr = label + ": " + value;                     text = decodedText.replace(labelRegex,valuestr);                     tok.set("gmnotes",text);                     return;                 } else if (args == '-') {                     sendChat("tokR", "Value of " + label + ": " + value);                     value--;                     sendChat ("tokR", "Updated to " + value);                     var valuestr = label + ": " + value;                     text = decodedText.replace(labelRegex,valuestr);                     tok.set("gmnotes",text);                     return;                 } else {                     sendChat("tokR","Please enter !tokR <label>, !tokR <label>+, or !tokR <label>-")                     return;                                      }                                                                }                                                                              }     }); });  Theoretically, this shouldn't interfere with other API scripts that use the GMnotes. It uses .replace() to update the targeted text, though I have not tested this API Script with any other Script. I also have not tested this with a lot of other characters. It has to decode the unicode from the GMnotes, but no problems arise with basic characters or colons.