Supernotes is perfect for reading the note, it handles hidden text, can read from multiple sources, can whisper or send openly. It does not set notes, however. I would suggest this script that I believe the Aaron wrote for me long ago code below) Syntax !set-gmnote any text here Will put the text " any text here " into a token's gmnote !set-cgmnote will do the same for the gmnotes on a character !set-bio will do the same for a character's bio notes. To handle multiple paragrpahs, wrap the message in double curly braces, like in a roll template: !set-gmnote {{Paragraph 1 Paragraph 2}} You can alse replace the word "set" with "add" in the macro and it will append the information to any existing note instead of replacing the entire contents. Code on('ready',function(){ 'use strict'; const cmdregex=/^(!(?:set|add)-(?:c?gmnote|bio))\s*/, formatMsg = (c)=>c.replace(cmdregex,'').replace(/(^{{\s*|\s*}}$)/gm,''); on('chat:message',function(msg){ if('api' === msg.type) { let match=msg.content.match(cmdregex); if(match && playerIsGM(msg.playerid) ){ let content = formatMsg(msg.content), who=(getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname'); if(_.has(msg,'inlinerolls')){ content = _.chain(msg.inlinerolls) .reduce(function(m,v,k){ var ti=_.reduce(v.results.rolls,function(m2,v2){ if(_.has(v2,'table')){ m2.push(_.reduce(v2.results,function(m3,v3){ m3.push(v3.tableItem.name); return m3; },[]).join(', ')); } return m2; },[]).join(', '); m['$[['+k+']]']= (ti.length && ti) || v.results.total || 0; return m; },{}) .reduce(function(m,v,k){ return m.replace(k,v); },content) .value(); } if(content.length){ let tokens = _.chain(msg.selected) .map( s => getObj('graphic',s._id)) .reject(_.isUndefined) ; switch(match[1]){ case '!set-gmnote': tokens.each( o => { o.set({ gmnotes: content }); }); break; case '!set-cgmnote': tokens.map( o => getObj('character',o.get('represents'))) .reject(_.isUndefined) .each( o => { o.set({ gmnotes: content }); }); break; case '!set-bio': tokens.map( o => getObj('character',o.get('represents'))) .reject(_.isUndefined) .each( o => { o.set({ bio: content }); }); break; case '!add-gmnote': tokens.each( o =>{ o.set({ gmnotes: `${o.get('gmnotes')}<br>\n${content}` }); }); break; case '!add-cgmnote': tokens.map( o => getObj('character',o.get('represents'))) .reject(_.isUndefined) .each( o => { o.get('gmnotes',(notes)=>{ _.defer(()=>o.set({ gmnotes: `${notes}<br>\n${content}` })); }); }); break; case '!add-bio': tokens.map( o => getObj('character',o.get('represents'))) .reject(_.isUndefined) .each( o => { o.get('bio',(notes)=>{ _.defer(()=>o.set({ bio: `${notes}<br>\n${content}` })); }); }); break; } } else { sendChat('',`/w "${who}" <div>`+ `<div>Use <code>COMMNAD Some Text</code> or <code>COMMAND {{ some multi-line text}}</code>.</div>`+ `<div><b>Commands:</b></div>`+ `<div><ul>`+ `<li><code>!set-gmnote</code> -- Replaces contents of token gmnotes.</li>`+ `<li><code>!set-cgmnote</code> -- Replaces contents of character gmnotes.</li>`+ `<li><code>!set-bio</code> -- Replaces contents of character bio.</li>`+ `<li><code>!add-gmnote</code> -- Appends to contents of token gmnotes.</li>`+ `<li><code>!add-cgmnote</code> -- Appends to contents of character gmnotes.</li>`+ `<li><code>!add-bio</code> -- Appends to contents of character bio.</li>`+ `</ul></div>` ); } } } }); });