Skip to main content

'Evernoting' from the command line

5 min read

Older Article

This article was published 13 years ago. Some information may be outdated or no longer applicable.

I won’t argue whether Evernote is good or useless. For a long time I didn’t get the hype. Then I found a genuine use for it: a single place to dump all my scripts and code snippets that had been scattered across random text files on my laptop.

I was writing some Puppet scripts inside a virtual machine and I wanted to save them to Evernote directly from the terminal. No copy-pasting. Just a simple command line interface that lets me push an entry straight into my notes.

I found the official Evernote PHP-SDK and an example that made the whole thing much easier. I extended it and made it (shall we say) “command line compatible”. The example script uses EDAM (no, not the Dutch cheese): Evernote Data Access Management, a protocol for exchanging data with the Evernote service. Under the hood, EDAM runs on Thrift, a binary communication protocol originally developed by Facebook and now hosted by the Apache Software Foundation. Thrift allows the definition and creation of services for a large number of languages.

Before we go any further, grab an Authorisation Token from either https://sandbox.evernote.com/api/DeveloperToken.action or https://www.evernote.com/api/DeveloperToken.action (depending on whether you want to save notes to a sandbox environment or your real notebook). If you’ve already got a token, keep it handy. We’ll need it shortly.

The script (which I’ve intuitively named ‘note.php’) has two run modes: ‘cli’ and ‘file’. The ‘cli’ mode sends whatever you type in the command line to Evernote. The ‘file’ mode reads the entire contents of a file and saves it as a note. Both modes accept standard HTML tags, so you can use to highlight something if you like.

The script takes 3 arguments:

--mode: either '_cli_' or '_file_'

--subject: the title of the note

--text: the text **or** file content to save as a note.
php note.php cli "Test Note" "This is a test note. It accepts **HTML** tags as well."
php note.php file "Another test" /path/to/your-file.log

And here’s the command to execute from your command line: Which results in the following note created in the Evernote web interface:

The first section of the code is similar to the original example provided by Evernote. The only difference is a help function I’ve added that describes the script’s functionality. Let’s look at what it actually does.

use EDAM\Types\Data, EDAM\Types\Note;
use EDAM\Error\EDAMUserException, EDAM\Error\EDAMErrorCode;
use Evernote\Client;

require_once 'autoload.php';
require_once 'Evernote/Client.php';
require_once 'packages/Errors/Errors_types.php';
require_once 'packages/Types/Types_types.php';
require_once 'packages/Limits/Limits_constants.php';

function help() {
echo "\nThis is a command line PHP script with the following options:
    Usage:
    " . basename(__FILE__) . " cli|file title \"text\"|\"/path/to/file\"
    title: Title of note
    cli: to be followed by \"text\", e.g:
      " . basename(__FILE__) . " cli \"Note title\" \"Add to note\"
    file: must be followed by a path, e.g.:
      " . basename(__FILE__) . " file \"Another title\" \"/home/user/notes.txt\"

    Both the cli and file options accept HTML tags as parameters, e.g.:
      " . basename(__FILE__) . " cli \"My Title\" \"I can accept **HTML tags**\"\n
";
}

The real work happens in a custom function. The highlighted line is where you drop in your developer access token. Once authentication is done, we create a new Client object and a new Note object, set the required parameters (title, content, bearing in mind that Evernote uses their own markup language, ENML), and call createNote() to save:

<?php
function addNote($title, $content) {
    $authToken = "";
    $client = new Client(array('token' => $authToken));

    $noteStore = $client->getNoteStore();
    $note = new Note();
    $note->title = $title;
    // The content of an Evernote note is represented using Evernote Markup Language
    // (ENML). The full ENML specification can be found in the Evernote API Overview
    // at http://dev.evernote.com/documentation/cloud/chapters/ENML.php
    $note->content =
        '<?xml version="1.0" encoding="UTF-8"?>' .
        '<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">' .
        '<en-note>' . nl2br($content) . '<br/></en-note>';

    // When note titles are user-generated, it's important to validate them
    $len = strlen($note->title);
    $min = $GLOBALS['EDAM_Limits_Limits_CONSTANTS']['EDAM_NOTE_TITLE_LEN_MIN'];
    $max = $GLOBALS['EDAM_Limits_Limits_CONSTANTS']['EDAM_NOTE_TITLE_LEN_MAX'];
    $pattern = '#' . $GLOBALS['EDAM_Limits_Limits_CONSTANTS']['EDAM_NOTE_TITLE_REGEX'] . '#'; // Add PCRE delimiters
    if ($len < $min || $len > $max || !preg_match($pattern, $note->title)) {
        print "\nInvalid note title: " . $note->title . '\n\n';
        exit(1);
    }
    $createdNote = $noteStore->createNote($note);

    print "Successfully created a new note:  " .  $note->title . " (GUID: " . $createdNote->guid . ")\n";
}
?>

I’ve also added some error checking and logic to prevent anyone with clumsy fingers from accidentally saving a file path as the note text instead of reading the file:

<?php
if ($argc != 4 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) {
    help();
    exit();
} else {
    $mode = isset($argv[1]) ? $argv[1] : undef;
    $title = isset($argv[2]) ? $argv[2] : undef;
    $content = isset($argv[3]) ? $argv[3] : undef;

    if (!isset($mode) || !isset($title) || !isset($title)) {
        help();
    }

    if ($mode == "cli") {
        addNote($title, $content);
    }
    elseif ($mode == "file") {
        //parse file
        if (!file_exists($content)) {
            echo "The file defined cannot be found - make sure you entered the right file (" . $content . ") and that you're using the right parameter ('file').";
            help();
            exit();
        } else {
            $content = file_get_contents($content);
            addnote($title, $content);
        }
    }
    else {
        help();
        exit();
    }
}
?>

That’s it. If you want to try this out, you’ll need all the Evernote libraries. Feel free to grab my code (including all the required files) from GitHub. Happy Evernoting!