GitHub to OmniFocus Integration

I’m thrilled to announce that I’ve written a GitHub to OmniFocus integration.  Track your GitHub issues from OmniFocus automatically!

This Ruby script is based on my Jira to OmniFocus integration, but uses the Octokit gem to pull issues from GitHub instead of Jira.  You can find it on GitHub here:

It is simple to install, and can be run on a schedule via cron, or via a LaunchDaemon on OS X.  One notable difference from my Jira to OmniFocus integration is that this script puts the body of the GitHub issue into the Note of the OmniFocus task.  This feature may be coming as an enhancement to the Jira integration soon.

If you have any problems or enhancement requests please create a GitHub issue on the project.  Thanks!

Control Nest Thermostat From the Command Line

I have a Nest thermostat, which is a wonderful piece of technology, however that meant that I had to get my phone out of my pocket, unlock it, launch the Nest app, wait for it to connect, and then adjust the temperature.  I wondered if it was possible to control my Nest from the command line on my laptop, which I am always working in anyhow.  The answer is YES, and this is HOW:


Step 1 – Create a Nest Developer Product

Nest Developer Product ScreenYou need to create a Nest Developer account and product to get the API access you need to control your thermostat.
Create a Nest Developer account here –

Then create a Product.  Mine is called “Devons Command Line Interface”.  Make sure you grant read/write permissions for the Thermostat and Away.

Copy down the Product ID and Product Secret values.  You will need them later.  You will also need the Authorization URL in the next step so don’t close this window!


Step 2 – Get your PIN Code for your Nest Thermostat

Nest Thermostat Authorization ScreenCopy the Authorization URL shown on the right side of the Nest Developer Product Details page and paste it into a new browser window.  It should prompt you to allow your Product to connect to your personal Nest account.  Click on Continue.

It should then give you a PIN Code.  Copy this down carefully!!!



Step 3 – Get your Access Code

Now that you have a PIN Code, you need to generate an API Access Code using your PIN Code and the Product ID and Product Secret from your Nest Developer Product Details Page.

curl -X POST ""

Replace the %YOUR_*% values with the correct values for your application the Nest PIN. And replace & with &.  Then execute this in your command line.  You should get back a long access token that starts with a “c.”.  This long string is your Access Token and will be used for authorization for API calls.


Step 4 – Get Your Nest Thermostat and Structure IDs

Now that you have your Access Token you can retrieve the IDs for your Thermostat and Structure (Home) which you’ll need to setup the command line API aliases.

curl -L\?auth\=%YOUR_ACCESS_TOKEN%

This command will return a big block of JSON data.  What you are looking for in there are two values: the device_id and the structure_id.  Copy those values, you will need them soon.


Step 5 – Create the Command Line Aliases

Now you have everything you need!  I use ZSH, but this should work just the same in BASH or the shell of your choice.  I created four aliases in my .zshrc (use your .bashrc or preferred file).  Each command will need your Access Token, and either your Device ID or your Structure ID.

nestset() {
curl -L -X PUT "" -H "Content-Type: application/json" -d "$1"

nestget() {
curl -L\?auth\=%YOUR_ACCESS_TOKEN%

nestaway() {
curl -L -X PUT "" -H "Content-Type: application/json" -d '"away"'

nesthome() {
curl -L -X PUT "" -H "Content-Type: application/json" -d '"home"'


Step 6 – Control Your Nest Thermostat From the Command Line!

Now that you’ve defined those aliases you are ready to use them!

nestget returns the current target temperature your Nest is set to:

[devon:~]$ nestget

nestset takes a single argument which is the new target temperature in Fahrenheit:
[devon:~]$ nestset 72

nestaway sets your Nest into Away mode:
[devon:~]$ nestaway

nesthome sets your Nest into Home mode:
[devon:~]$ nesthome




Translation into Portuguese for

Updated JIRA to Omnifocus Integration

Updates to my JIRA Omnifocus Integration

I have made some long over-due updates to the Jira OmniFocus integration I wrote a year ago.  Sean Kane provided a great pull request earlier this year where he’d made some massive improvements to the packaging and installation of the tool.  I just fixed a couple minor bugs, added support for syncing the Due Date of a Jira ticket to an OmniFocus task.  I also found a very inefficient scan of existing OmniFocus tasks, which I was able to improve.  For me this led to the script going from taking ~50 seconds, to now completing in about 2 seconds.  Not bad for modifying one line!


Where to get it

Find the latest Jira Omnifocus Integration code and install instructions here:

Please log any issues you find at GitHub issues and I will try to provide more timely support and enhancements as I am able.



Remote Work

While Spark::red has offices, we are primarily a distributed team, and as we continue to grow more and more of our team will be geographically separated from one another.  So the topic of remote working and distributed teams is an important one for us, and one I’m personally invested in.  I feel that there are significant advantages to both working in an office (collaboration, communication, culture, and more) and working remotely (freedom, focus, no commute, and more), so I do both.  I work from the Spark::red office outside of Boston 3-4 days a week (unless I’m traveling) and work from home 1-2 days a week.  As you may have read in several previous blog posts, I am also experimenting with one month or longer remote working situations.

Why Remote Work?

There are several reasons that Spark::red embraces the remote working approach.  It’s both something that we want to do, as well as something that we have to do.

For employees near a Spark::red office, being able to work from home as well can be a great perk. You can balance the pain your commute with the benefits of being in the office.  You can stay home if the plumber is coming by.  You can work from Boston if you have an appointment in town and don’t want to get stuck in rush hour.  You can visit your family in another state and still work as needed.  So it’s a benefit that many of our employees appreciate and take advantage of to differing degrees.

The type of person that we want to hire as we continue to grow is rare.  Our focus is ATG Oracle Commerce, which is a very small niche, so it’s difficult to find people with the right experience and skill set to join our team.  As a small company performing important work for large clients, it’s also imperative that any team members are amazing.  I know there’s a strong backlash against terms like “rockstar”, “ninja”, “A level”, etc… but there’s always going to be a wide spectrum of talent, experience, motivation, and effectiveness.  Spark::red can’t afford anyone who isn’t a GREAT team member, both from a effectiveness standpoint, but also from a cultural fit.  Find a person who fits is hard, and it’s impossible to find everyone we need from a single city.   We need to be able to hire the right people, regardless of their physical location.

Our clients’ sites are 24x7x365 operations.  They need to be supported, monitoring, maintenance, and improved at all hours.  Our clients are spread coast-to-coast in the United States, as well as multiple other continents.  Our global client base is growing, and is likely to be one of our largest growth areas in the coming years.  As such we need to be able to provide support, and not just emergency support, over a wider range of the day.  Deployments, support tickets, and alerts can happen from the early morning to the late night.  The more geographically diverse the Spark::red team is, the more of this can be accomplished by people working normal hours.  When you’re up until 4 AM helping a client with a deployment, you can’t be at your best the next day.  If that deployment can be done by someone 8 or more hours behind you on the globe, then it’s easier to provide better service.

The following three points drive home the fact that embracing and supporting a geographically diverse team is important for Spark::red’s growth and success, both from a team member happiness and from a client satisfaction standpoint.

The Struggles

Having a remote team comes with a unique set of potential difficulties, both hard and soft.  It’s worth doing, but you need to be mindful of the risks and have plans, tools, and processes in place to address them.

The “hard” issues are technical, procedural, or quantifiable and range from things like “how do you handle it when someone has a problem with their laptop and they live thousands of miles away from the nearest office?” to “how does the team communicate effectively?”  How are tasks managed, progress tracked, support and mentorship given, how do you make sure people know what’s going on in the company around them without overloading them with a river of distracting updates and information they don’t actually need?

The “soft” issues are more around corporate culture, interpersonal relationships and communication, maintaing and evolving the company ethos and soul.  They are hard to measure and harder to solve.  Also, everyone is different.  Everyone works differently, and is motivated by different things.  So don’t expect everyone to want to work remotely, or for it be effective for them, or for a given set of tools/ideas/processes to work equally well for everyone.

How Spark::red is Working

Spark::red has two main offices in Redmond, WA and Chelmsford, MA, employees who split their time between an office and working from home, as well as employees who live thousands of miles away from the nearest office.  Our tools and processes are certainly a work in progress and by no means are the end-all-be-all approach you should adopt, but there’s some good stuff going on here.

We use Campfire for group chat.  We have several standing rooms, for internal teams, for clients, for random chat, and also create rooms on demand for projects or topics as needed.  The chatroom provides a good way for large numbers of people to interact, but it can be as interrupt driven as you let it be.  You can check the rooms each time a new message is posted, or only look when the chime means your name was mentioned, or just glance over when you’re not in the middle of something.  Or you can just sign-out for a while, and when you get back into Campfire you can scroll back through and see what you missed.  We use Flint as a Campfire client instead of using the web app.  We can also use it on our phones and iPads so if we’re  not at our computer and need to ask something, or check in on something, it’s easy.

After an amazing presentation by the Streaming Eagles from GitHub at the FutureStack 13 conference last month, we’ve started using video chat for one-on-one discussions and some small group chats as well.  We’ve played with several different tools for video (google hangouts, FaceTime, and currently are using Skype.  I hate the Skype application, but it’s video quality and reliability under sub-par network conditions have really made it work for us.  The video chat gives you a much more natural conversation style, and makes it clear that on the other end is a real person, with real feelings, and a real life, and I think it makes people less likely to be snarky or miscommunicate.  This is still an experiment in progress, but so far I think it’s good.

We use Jira for task tracking.  It makes it easy to hand off a task to another person or another team, providing the full history of the task and current status.  We use Confluence for a wiki.  We use DropBox for sharing files.  We’re starting to use Evernote as well for collaboration and notes.

While we don’t do development (agile or not) we are doing a daily scrum call with the entire company.  We quickly go through what we’ve done, what we’re working on today, any blocking issues, if we need help from anyone, etc…  It’s 15 minutes well spent and gives everyone a good idea of what’s going on, let’s people ask for help, and gets everyone “together” virtually.  As our team grows internationally it may become harder to involve the entire team at any given timeslot.

We do some inter-office travel and office visits.  Getting people to meet, talk, work, and hangout in person provides huge benefits in their long term working relationship and communication effectiveness.  We’ve done a company all-hands summit, and that’s something I’d like to make an annual event, although it’s tougher to do now that we have more clients and more daily support need.  This is something I’d like to figure out better.

We have a lot to learn still, and I don’t think we’re doing things as well as we could be, but we’re connately trying to improve how we work and how we work remotely.

Go Forth and Work!

I think most companies would benefit from allowing, encouraging, and empowering their employees and team to work remotely.  The big cons are pretty easily solvable and the pros are significant.  I would love to hear what you’ve found works or doesn’t work around working remotely.  I’m constantly looking to improve what we’re doing and try new things.

Jira to OmniFocus Integration

At Spark::red we use Jira extensively for internal projects and tasks, for alerts and issues, and for handling client support requests.  It’s a great tool.  I also use OmniFocus for other types of tasks: personal, errands, write an email to so-and-so, create a proposal, etc…  What that’s left me with is two separate to-do lists, that I have to check separately, which is a pain.

I finally started looking at possible integrations between the two tools, and I found several scripts that sync Jira tasks into OmniFocus.  Unfortunately every single one I tried didn’t work.  Either my version of Jira was too new (5.1.5), or my OmniFocus is too new (1.10.5), or my Ruby is too new, or various Ruby Gems wouldn’t install correctly, or the integration required massive additional library/software installation.

So while I was stuck in the San Francisco airport a few nights ago waiting for a very delayed flight home, I hacked up a simple Ruby script that does what I need it to do. I’ve never written anything in Ruby before, so it’s probably terribly written, but it works!  I have it running every 10 minutes as a cron job on my laptop.

What it does is two things:

It pulls back all unresolved Jira tickets that are assigned to you and if it hasn’t already created a OmniFocus task for that ticket, it creates a new one.  The title of the task is the Jira ticket number followed by the summary from the ticket.  The note part of the OmniFocus task is just the URL to the Jira ticket so you can easily go right to it.  I chose not to pull over the full description, or comment history into the task notes as it’s usually more than I want to see in OmniFocus.

It also checks all the OmniFocus tasks that look like they are related to Jira tickets, and checks to see if the matching ticket has been resolved.  If so, it marks the task as complete.

Very simple.  The Ruby code is straight forward and it should be easy to modify to do other things to meet your specific needs.

You will need to install a few gems

gem install rb-appscript json

You’ll need to edit the configuration values at the top of the script (please note this current version does not hide/encrypt your password), and then save it somewhere.  I have mine in /Users/devon/bin/ but you can put it anywhere.  Then you can add a cron entry to run it every 5 minutes or 10 minutes or whatever you need (it will take a minute or so to run so don’t make it run too often).

You can use crontab -e to edit your user crontab and create an entry like this:

*/10 * * * * /Users/devon/bin/jiraomnifocus.rb

That should be it!  If it doesn’t work, try adding some puts debug statements and running it manually.  I can’t offer any support, as I don’t know Ruby that well and just magically cobbled this together:)