Logging with Day One, geek style
I have long kept a journal–more precisely, a log–using VoodooPad with the Scratchpad scripts by Ian Beck. It’s been a great system, but after years of usage it’s started to become a bit cumbersome. VoodooPad can handle the load, but running the custom scripts is inconvenient on a document with thousands of pages. In the interest of trying new things (and fiddling away some time this evening), I decided to try switching the system over to Day One.
Day One is a gorgeous app for keeping a personal journal. I discovered it, if I recall correctly, via David Sparks. It has iOS companion apps and iCloud syncing. It also has excellent search capabilities, likes MultiMarkdown and can export my entries to plain text at any time. I like it because it’s good-looking and concise; just what I need, with no feature bloat. Plus, it’s specifically designed to do exactly what I want: keep a timestamped journal of what I’m working on, have accomplished or have just discovered in my digital travels.
Day One already has a quick entry palette in the menubar. It also has a command line interface (/usr/local/bin/dayone)1 which provides some geeky options (try dayone in Terminal) and the flexibility needed to replace my current logging system. You can create entries quickly with either method, but I wanted just a little bit more out of it. I built a quick script which allows a basic syntax for starring entries and defining dates (using natural language) inline in the entry itself. It can be used from the command line, from LaunchBar (or similar) and can be incorporated into just about any scriptable workflow.
The natural language portion of the script is built on the “Chronic” Ruby gem, so running this script as is requires that you have that installed. If you don’t have it available, just run gem install chronic to add the gem. If you run into errors doing that, try sudo gem install chronic and provide your system password. Here’s the script, complete with some explanation in the comments.
#!/usr/bin/ruby # logtodayone.rb # Brett Terpstra (http://brettterpstra.com) # Use and modify freely, attribution appreciated # # This script works with the Day One[1] command line utility # It parses an input string for an exclamation point prefix to mark starred # and/or a [date string] at the beginning to parse natural language dates # # Requirements: # Chronic ruby gem # # Example usage: # logtodayone.rb "! This is a starred entry." # logtodayone.rb "[yesterday 3pm] Something I did yesterday at 3:00PM" # logtodayone.rb "! [-2 1:30am] A starred entry about something I did two days ago" require 'rubygems' require 'chronic' # (`gem install chronic`) if ARGV.length > 0 input = ARGV.join(" ").strip else print "Log entry: " input = gets.strip end # If the input starts with an exclamation point, make it starred starred = input =~ /^!/ ? "true" : "false" # remove the bang from the input string input = input.gsub(/^!\s*/,'') # if there's a [date] specified, parse it if input =~ /^\[(.*?)\]/ datestring = $1 # if the date starts with -X, assume it means X days ago if datestring =~ /^\-(\d+)/ datestring.sub!(/\-(\d+)/,"\\1 days ago ") end # Replace a single 'y' within the date brackets with "Yesterday" for parsing datestring.sub!(/\by\b/,'yesterday') # Parse the resulting date string with Chronic d = Chronic.parse(datestring, {:context => :past, :ambiguous_time_range => 8}) d = DateTime.now if d.nil? else # if no [date] specified, make it right now d = DateTime.now end date = d.strftime("%m/%d/%Y %l:%M%p") # dayone formatted input = input.gsub(/^\[.*?\]\s*/,'') # remove [date] from input %x{echo "#{input}"|/usr/local/bin/dayone -d="#{date}" -s=#{starred} new}
Some usage tips
You can star an entry by beginning it with an exclamation point. I’m not sure how I’ll use stars yet, but I figured the option was there, so I’d add a syntax for it.
I often end up logging things after the fact but before I forget what I was doing, so it’s important for me to be able to enter an approximate date and time for the sake of organization. Date strings are entered in square brackets at the beginning (or after an exclamation point) of the entry. The natural language accepts basic strings such as “yesterday 3pm” or “noon” and converts them to Day One-compatible dates. It also accepts “-X” operators to specify a number of days ago (I’m assuming I won’t be logging entries in the future). “y” by itself will be converted to “yesterday.” A typical entry for me would look like “[y 11:45pm] working on silly scripts for logging to Day One.” An entry with no exclamation point and no date brackets is just read as a normal entry at the current time.
I’m using generic @tags–a habit carried over from my VoodooPad scratchpad–to make my entries easily searchable by topic or project. Beyond that, I’m just relying on Day One’s built-in chronological organization and full-text search.
The script is all fine and good, but it’s not much use if it’s not convenient to access. Here are a few of the ways I’m making it universally accessible in my workflow.
Bash alias
First things first, lets make it really easy to log entries from the command line. A simple alias in your ~/.bash_profile shortens things up:
alias log="~/scripts/logtodayone.rb"
Now you can make an entry with log "the thing I was just doing".
LaunchBar Action
Given that few of us are always on the command line, it would be nice to access the script easily from other utility apps. I personally use LaunchBar, but you can create similar scripts for Alfred, Quicksilver, etc. If you use LaunchBar, you can just save the three-line script below as Log to Day One.scpt in ~/Library/Application Support/LaunchBar/Actions:
on handle_string(message)
do shell script "/Users/ttscoff/scripts/logtodayone.rb \"" & message & "\""
end handle_string
Now, just pop up LaunchBar and type ldo or similar to select the action, then type space to get a text field where you can type your log entry. The script syntax applies in full, so start with an exclamation point to star the entry, and use natural language date syntax between square brackets to specify a date, if needed.
Git commit wrapper
I do something similar to this with an nvALT note, so I thought I’d try it with Day One for a while. It’s a basic bash function to copy a note from a git commit into my daily log. It just wraps git -am (commit all, message), so more complex commit commands won’t work. It covers 90% of the commits I’d actually want in my journal, though.
function cdo(){
msg=$*
path=$(pwd)
~/scripts/logtodayone.rb "@${path##*/} $msg"
git commit -am "$msg"
}
Update: I made the git wrapper significantly smarter, thanks to a little assist from @nnutter. It basically parses up your git tree for the actual repo name instead of using the directory name you’re currently in.
# experimental wrapper for git to log commits to Day One
# lots of credit to http://nnutter.com/2012/01/git-todo/
function cdo(){
msg=$*
GIT_DIR=$(git rev-parse --git-dir)
if ! (( $? )); then
GIT_DIR=$(echo "$GIT_DIR" | awk -F/ '{nlast = NF -1;print $nlast}')
if [ -z "$GIT_DIR" ]; then
path=$(pwd)
GIT_DIR=${path##*/}
fi
~/scripts/logtodayone.rb "@$GIT_DIR $msg"
fi
git commit -am "$msg"
}
So that’s my fiddling for the evening. Back to doing something more useful (like preparing for my Macworld | iWorld talk with Merlin Mann and David Sparks).
I forgot this originally, but you need to symlink the dayone CLI from the app bundle to your /usr/local/bin directory. As mentioned in the comments, more information can be found in the faq.### The script ↩

Love the script. I was using the CLI via Alfred, but this makes it super easy as an extension.
I can’t get the Starred entry to function though. Script returns an error that ’”!\” event not found’. I think the regex is fine. Too tired (and engrossed in Alcatraz) to figure it out.
Sounds like the string isn’t being quoted properly. Are you triggering from the command line or via the AppleScript? If you’re on the command line, be sure to put quotes around the argument so that the bang isn’t interpreted as a bash command:
Brett, thanks for pointing me in the right direction. I add “escape spaces” checked in the Alfred extension options. That solved it.
Ron:
How did you get it to work with Alfred? Did you just copy Brett’s script into a Script Extension? I have Silent and Action options set, and “Required Parameter” but the script does nothing.
Thomas, I was having the same issue so I tested it in the AppleScript editor. It turns out my version of Ruby is in a different location than Brett’s. I changed the shebang in his script to #!/usr/local/bin/ruby and it now works fine.
Type ‘which ruby’ in your Terminal to see what you should add there.
Tom: You should also be able to do “#!/usr/bin/env ruby”. I use env for perl & ruby in Lion.
For people who may be confused like I was, the command line program is in the app bundle. Full details are at the bottom of the FAQ: http://dayoneapp.com/faq/.
You can try
to put it on the path.
Thanks Neil, I was trying to remember exactly how I installed the CLI!
Excellent idea, Brett. I’ll end up buying LaunchBar yet; the reasons to own it keep piling up. Until I got Day One, I’d been using OhLife (after seeing it linked on http://minimalmac.com) for a while. Your post offered a tip that the dayone command-line tool was going to make it easy to import my OhLife history. I’ve posted the write-up on my tumblr if anyone’s interested in taking a look. Thanks again!
I’m wondering how you search for your @tags in Day One. I’ve also always used those to tag my files, but in Day One searching for them somehow doesn’t seem to work properly…
Yeah, the more I play with it the more I realize it seems to ignore or misinterpret any leading punctuation. I’m in touch with the devs now, so hopefully I’ll convince them to refine that part of the search…
Great, saves me the trouble of contacting them. Hope they fix it fast.
Thanks Brett. Got it working from LaunchBar which is great. One minor annoyance (since I’m not a unix/ruby geek) is that the time being grabbed in the ruby script when no time is specified is off by 5 hours.
That’s odd. It comes out right for me, but it could be a time zone offset or defaulting to UTC. You might have to use .local to get it right… I’ll play with some code later and see if I can figure that one out.
So, here’s what I’ve tracked down. I put together the following simple ruby script:
!/usr/bin/ruby
d = Time.now
date = d.strftime(“%m/%d/%Y %l:%M%p”)
puts d puts date
%x{echo “just some text” | /usr/local/bin/dayone –d=”#{date}” new}
and run it from terminal. It works fine with “just some text” showing up in Day One with the local time affixed. Thus, I don’t think the issue is in the logtodayone.rb script.
But, if I enter a message using LaunchBar and the “Log to Day One.scpt” calling logtodayone.rb, the time for the entry shows up with the UTC offset applied.
I couldn’t work with LounchBar. Maybe I missed a place logtodayone.rb file. Could you tell me where logtodayone.rb file put in? I put it in Scripts folder which I created.
[…] Brett Terpstra posted a fantastic little script to leverage Day One’s built-in CLI (command line interface, more information available here) to […]
Thank you. I got understand after read your article. I could post to One Day with LaunchBar.
Hi Brett,
I did the same thing with Launchbar last year. I posted the Applescript to handle this on the Objective Development Forums. It depends on the DayOne command line app being copied out to somewhere in your path (or hardcoding in the script) but doesn’t rely on ruby or any externals. Also, it doesn’t bother with funky tagging.
For those like me that wanted this to work with Alfred, MacStories has the scoop. You can see the script on that site at: http://www.macstories.net/tutorials/logging-with-day-one-and-alfred/
I followed this post here from the Macstories article about using this script to post from Alfred — however I can’t for the life of me get it to work. CLI symlink is in place, Chronic is installed, Ruby is installed in the correct place, the script is executable.. no luck.
same here no luck…
It’s a problem with my dayone, if I type dayone into terminal I get a permissions error. Even though permissions were even placed at 777 — if someone knows what’s wrong please let me/us know.
Fixed my problem by archiving the ‘dayone’ CL file then moving that file into the /usr/local/bin/ — no symlink. works now. Two copies of the file on my system but at least it works.
The MacStories tip works just fine, but it is too complex. Just let Alfred directly run the ruby script as a terminal extension with the plain vanilla command
/Users//scripts/logtodayone.rb {query}
[…] of the cool kids are using Day One in some really interesting ways. There’s Brett, who is using it to leave himself a bread-crumb trail of things he works on. Now there’s this great example from Stephen Hargrove on Spirit of Nine […]
I’m having trouble getting the LaunchBar Action working with rvm installed. There’s apparently a problem calling rvm’s default ruby from AppleScript. Instead, it calls the system ruby, which doesn’t have the Chronic gem.
As a workaround, I replaced “do shell script” with ‘tell application “Terminal” to do script’ — This unfortunately calls up Terminal.
Does anyone know a better solution?
There’s an all-applescript version I posted up there (linked on ObjectiveDevelopment’s forums) which doesn’t require any extra software installing. It depends on how important being able to specify dates and flag entries is to you.
Thanks, Dave. It works well!
You can install Chronic on all Ruby installs with
rvm all gem install chronic, or try using/usr/bin/env rubyin the hashbang and see if it finds the correct version of Ruby in your environment.Thanks, Brett. Unfortunately, even with the “/usr/bin/env ruby” hashbang, it still doesn’t find the rvm ruby, instead using the Ruby.framework version. I think this has something to do with how rvm sets up the environment.
rvm’s way of changing the environment also makes it difficult to install gems for that system ruby installation.
I’ve seen this problem discussed around the web, but I haven’t seen a solution anywhere.
[…] while ago I read on Brett Terpstra Logging with Day One Geek Style (Brett’s blog is great – loads of poweruser tips and scripts all the […]
[…] Terpstra has posted a number of very cool things that can be done with the OS X and iOS application DayOne. They were so compelling that I gave in […]
[…] Logging with Day One, geek style – Brett Terpstra […]
Thanks for the code. In my version, I prefer to use the branch name.
https://gist.github.com/1963105
And here is how my dayone log message looks like: SnakeAndBall @dev_swipe_ctrl : Added control determine to show/hide snake up/right/down/left buttons; Also load alternative level only when control is swipe.
[…] Tagebuch zu führen. Genauso wenig protokolliere ich Projekte im Journal-Format oder dokumentiere Job-Logbücher mit […]
For the heck of it, I ported the script to Tcl. This has the advantage of not requiring any external dependencies, and avoiding some of the RVM problems when using with LaunchBar, etc.:
https://gist.github.com/2475369