Script action to create tasks in Focus app

I’m working on a script action in Drafts to create tasks in Focus. The action runs successfully but no tasks are created in Focus.

Here is the script:

const d = draft;
const task_list = d.processTemplate("[[selection]]");
const baseURL = "focusapp://x-callback-url/add"; //

var tasks = task_list.split(/\n/);
for (var task of tasks) {
  if (task.match(/(^#)|(^\s*$)|(^- \[x\])/)) { // ignore lines that have completed tasks, include markdown headings, or are empty
  } else {
    task = task.replace(/^- (\[ ] )?(.*)/,"$2"); // remove simple-list formatting
    var cb = CallbackURL.create();
    cb.baseURL = baseURL;
    cb.addParameter("title", task);

    // open and wait for result
    var success =;
    if (success) {
        console.log("Task created: " + cb); // Log when task created successfully — this is firing, just no tasks created
    if (!success) {
      if (cb.status == "cancel") {
      } else {;

It’s probably something really obvious I’m overlooking. Maybe there’s something wrong with the URLs that are getting passed but I can’t figure out how to see what’s in the CallbackURL object to tell if that’s the problem.

Can anyone help?

I don’t have the Focus app, but perhaps double check the following?

  1. You are url encoding the title.
  2. Your script is actually entering the part where it tries to call Focus.
  3. Check the action log for any errors/information.

My first suggestion is to add an alert so you can see what cb is before you call it. It may be improperly formed. (Although why the script would then exit successfully, I don’t know.)

Also, I am suspicious of the call to splice. I’m no JavaScript expert, but Isn’t it a method that needs arguments?

1 Like

Thanks! It’s definitely calling the URL because I can see it toggles back and forth between Drafts and Focus as it loops through the lines of the draft. Also there are no errors in the log.

I’m (obviously) no JavaScript expert either. There is something wrong with how I’m calling splice, will look at that.

I’m not able to get a look at what’s in the CallbackURL object with an alert or console.log before I call open() — What method/routine do I call to look inside?

@drdrang is spot on with his splice observation.

Maybe just alert or console log out your base URL, parameters and values; or build the URL from then and copy it to the clipboard for checking.

Also, URL encoding of your titles may still be a key step. Think about what an ampersand in your title would do to your URL.

I also do not have the app to try, but your URL does not match the url scheme docs you linked to. They say they support the x-callback-url parameters, but their example does not contain the “x-callback-url” host name, try changing:




Also, to troubleshoot URLs, I would always start by making your the URL you are trying to generate works if you type it in Safari’s address bar. So, if you click this URL, does it work in Focus:


Thanks for the suggestions, will give them a try.

The Focus app documentation isn’t explicit about x-callback-url but says that it is supported so I just threw it in there.

From the examples I’ve seen (adapted this script from the “send to Fantastical” action), CallbackURL does the work of concatenating and encoding URLs. I’d like to know what it’s doing because if I can get this to work it’ll open up a lot of other possibilities for my workflow. Is there more documentation?

Looking at it again, I realize I don’t even need the splice statement. (Will still check how to use properly :blush: )

CallbackURL object is documented in the scripting reference.

Removing the “x-callback-url” did the trick, thanks!

1 Like

Even though jochi has his answer, I’d like to pursue the properties of the CallbackURL object further.

I see now that my advice to try something like alert(cb) was bad because that won’t show the constructed and encoded URL. Is there any way to get the full URL from a CallbackURL object? I don’t see anything in the docs, but it seems like a useful thing to have when debugging.

There is no such function on CallbackURL. Would be pretty easy to add. It would be incomplete, in the sense that is would not include the x-success, x-error or x-cancel parameters, but could display any parameters you have configured on the object (or with the baseURL). I’ll make a note to add.

1 Like

Thanks, Greg!

[padding to 20 chars]

Yes indeed, thanks Greg!..

I’ve completed a first version of the action and added it to the directory. It’s hacky, but it works. Would love feedback from other Focus users!

FYI: CallbackURL.url property (added in R17).

That’ll come in handy, thanks!!!

That’s what I call service.