A command line tool for keeping track of what you’re doing and tracking what you’ve done.

For a summary of all commands and options, see Doing - All Commands.

What and why

doing is a basic CLI for adding and listing “what was I doing” reminders in a TaskPaper-formatted text file. It allows for multiple sections/categories and flexible output formatting.

While I’m working, I have hourly reminders to record what I’m working on, and I try to remember to punch in quick notes if I’m unexpectedly called away from a project. I can do this just by typing doing now tracking down the CG bug.

If there’s something I want to look at later but doesn’t need to be added to a task list or tracker, I can type doing later check out the pinboard bookmarks from macdrifter. When I get back to my computer — or just need a refresher after a distraction — I can type doing last to see what the last thing on my plate was. I can also type doing recent (or just doing) to get a list of the last few entries. doing today gives me everything since midnight for the current day, making it easy to see what I’ve accomplished over a sleepless night.


The current version of doing is 1.0.75.

$ [sudo] gem install doing

Only use sudo if your environment requires it. If you’re using the system Ruby on a Mac, for example, it will likely be necessary. If gem install doing fails, then run sudo gem install doing and provide your administrator password.

Run doing config to open your ~/.doingrc file in the editor defined in the $EDITOR environment variable. Set up your doing_file right away (where you want entries to be stored), and cover the rest after you’ve read the docs.

See the support section below for troubleshooting details.

The “doing” file

The file that stores all of your entries is generated the first time you add an entry (with doing now or doing later). By default, the file is created in ~/, but you can modify this in the config file.

The format of the “doing” file is TaskPaper-compatible. You can edit it by hand at any time (in TaskPaper or any text editor), but it uses a specific format for parsing, so be sure to maintain the dates and pipe characters.

Notes are anything in the list without a leading hyphen and date. They belong to the entry directly before them, and they should be indented one level beyond the parent item.

When using the now and later commands on the command line, you can start the entry with a quote and hit return, then type the note and close the quote. Anything after the first line will be turned into a TaskPaper-compatible note for the task and can be displayed in templates using %note.

Notes can be prevented from ever appearing in output with the global option --no-notes: doing --no-notes show all.

Auto tagging (adding tags listed in .doingrc under autotag and default_tags) can be skipped for an entry with the -x global option: doing -x done skipping some automatic tagging.


A basic configuration looks like this:

doing_file: /Users/username/Dropbox/doing.taskpaper
current_section: Currently
default_template: '%date: %title%note'
default_date_format: '%Y-%m-%d %H:%M'
marker_tag: flagged
marker_color: yellow
tags_color: boldcyan
default_tags: []
editor_app: TaskPaper
config_editor_app: Sublime Text
:include_notes: true
    date_format: '%F %_I:%M%P'
    section: Currently
    count: 10
    wrap_width: 0
    template: '%boldblack%date %boldgreen| %boldwhite%title%default%note'
    order: desc
    date_format: '%Y-%m-%d %H:%M'
    template: '%date | %title%note'
    wrap_width: 0
    date_format: '%_I:%M%P'
    template: '%date: %title%odnote'
    wrap_width: 0
    date_format: '%_I:%M%P on %a'
    template: '%title (at %date)%odnote'
    wrap_width: 0
    date_format: '%_I:%M%P'
    template: '%date > %title%odnote'
    wrap_width: 50
  - coding
  - design
    - thinking
    - idea

The config file is stored in ~/.doingrc, and a skeleton file is created on the first run. Just run doing on its own to create the file.

Per-folder configuration

Any options found in a .doingrc anywhere in the hierarchy between your current folder and your home folder will be appended to the base configuration, overriding or extending existing options. This allows you to put a .doingrc file into the base of a project and add specific configurations (such as default tags) when working in that project on the command line. These can be cascaded, with the closest .doingrc to your current directory taking precedence, though I’m not sure why you’d want to deal with that.

Possible uses:

  • Define custom HTML output on a per-project basis using the html_template option for custom templates. Customize time tracking reports based on project or client.
  • Define default_tags for a project so that every time you doing now from within that project directory or its subfolders, it gets tagged with that project automatically.

Any part of the configuration can be copied into these local files and modified. You only need to include the parts you want to change or add.

Doing file location

The one thing you’ll probably want to adjust is the file that the notes are stored in. That’s the doing_file key:

doing_file: /Users/username/Dropbox/nvALT2.2/?? What was I

I keep mine in my nvALT folder for quick access and syncing between machines. If desired, you can give it a .taskpaper extension to make it more recognizable to other applications. (If you do that in nvALT, make sure to add taskpaper as a recognized extension in preferences).

“Current actions” section

You can rename the section that holds your current tasks. By default, this is Currently, but if you have some other bright idea, feel free:

current_section: Currently

Default editors

The setting editor_app only applies to Mac OS X users. It’s the default application that the command doing open will open your WWID file in. Personally, I use editor_app: TaskPaper. If this is blank, it will be opened by whatever the system default is for the doing file extension (default is .md), or you can use -a app_name or -b bundle_id to override.

You can define a separate app to open the config file in when running doing config. The key for this is config_editor_app.

In the case of the doing now -e command, your $EDITOR environment variable will be used to complete the entry text and notes. Set it in your ~/.bash_profile or whatever is appropriate for your system:

export EDITOR="mate -w"

The only requirements are that your editor be launchable from the command line and able to “wait.” In the case of Sublime Text and TextMate, just use -w like this: export EDITOR="subl -w".


The config also contains templates for various command outputs. Include placeholders by placing a % before the keyword. The available tokens are:

  • %title: the “what was I doing” entry line
  • %date: the date based on the template’s date_format setting
  • %shortdate: a custom date formatter that removes the day/month/year from the entry if they match the current day/month/year
  • %note: Any note in the entry will be included here, a newline and tabs are automatically added.
  • %odnote: The notes with a leading tab removed (outdented note)
  • %chompnote: Notes on one line, beginning and trailing whitespace removed.
  • %section: The section/project the entry is currently in
  • %hr: a horizontal rule (-) the width of the terminal
  • %hr_under: a horizontal rule (_) the width of the terminal
  • %n: inserts a newline
  • %t: inserts a tab
  • %[color]: color can be black, red, green, blue, yellow, magenta, cyan, or white
    • you can prefix bg to affect background colors (%bgyellow)
    • prefix bold and boldbg for strong colors (%boldgreen, %boldbgblue)
    • there are some random special combo colors. Use doing colors to see the list
  • %interval: when used with the -t switch on the show command, it will display the time between a timestamp or @start(date) tag and the @done(date) tag, if it exists. Otherwise, it will remain empty.

Date formats are based on Ruby strftime formatting. You can try it out here.

My normal template for the recent command looks like this:

  date_format: '%_I:%M%P'
  template: '%date > %title%odnote'
  wrap_width: 88

And it outputs:

$ doing recent 3
 4:30am > Made my `console` script smarter...
    Checks first argument to see if it's a file, if it is, that's the log

    Else, it checks the first argument for a ".log" suffix and does a search in the user
    application logs with `find` for it.

    Otherwise, system.log.

    I also made an awesome Cope wrapper for it...
12:00pm > Working on `doing` again.
12:45pm > I think this thing (doing) is ready to document and distribute

You can get pretty clever and include line breaks and other formatting inside of double quotes. If you want multiline templates, just use \n in the template line, and after the next run it will be rewritten as proper YAML automatically.

For example, this block:

  date_format: '%_I:%M%P'
  template: "\n%hr\n%date\n > %title%odnote\n%hr_under"
  wrap_width: 100

will rewrite to:

  date_format: '%_I:%M%P'
  template: |2-

     > %title%odnote
  wrap_width: 100

and output my recent entries like this:

$ doing recent 3
 > Made my `console` script smarter...
    Checks first argument to see if it's a file, if it is, that's the log

    Else, it checks the first argument for a ".log" suffix and does a search in the user application
    logs with `find` for it.

    Otherwise, system.log.

    I also made an awesome Cope wrapper for it...

 > Working on `doing` again.

 > I think this thing (doing) is ready to document and distribute


Custom views

You can create your own “views” in the ~/.doingrc file and view them with doing view view_name. Just add a section like this:

    section: Old
    count: 5
    wrap_width: 0
    date_format: '%F %_I:%M%P'
    template: '%date | %title%note'
    order: asc
    tags: done finished cancelled
    tags_bool: ANY

You can add additional custom views. Just nest them under the views key (indented two spaces from the edge). Multiple views would look like this:

    section: Later
    count: 5
    wrap_width: 60
    date_format: '%F %_I:%M%P'
    template: '%date | %title%note'
    section: Old
    count: 5
    wrap_width: 0
    date_format: '%F %_I:%M%P'
    template: '%date | %title%note' 

The section key is the default section to pull entries from. Count and section can be overridden at runtime with the -c and -s flags. Setting section to All will combine all sections in the output.

You can add new sections with doing add_section section_name. You can also create them on the fly by using the -s section_name flag when running doing now. For example, doing now -s Misc just a random side note would create the “just a random side note” entry in a new section called “Misc,” if Misc didn’t already exist.

The tags and tags_bool keys allow you to specify tags that the view is filtered by. You can list multiple tags separated by spaces, and then use tags_bool to specify ALL, ANY, or NONE to determine how it handles the multiple tags.

The order key defines the sort order of the output. This is applied after the tasks are retrieved and cut off at the maximum number specified in count.

Regarding colors, you can use them to create very nice displays if you’re outputting to a color terminal. Example:

  date_format: '%F %_I:%M%P'
  section: Currently
  count: 10
  wrap_width: 0
  template: '%boldblack%date %boldgreen| %boldwhite%title%default%note'


You can also specify a default output format for a view. Most of the optional output formats override the template specification (html, csv, json). If the view command is used with the -o flag, it will override what’s specified in the file.


You can use the following colors in view templates. Set a foreground color with a named color:


You can also add a background color (%bg[color]) by placing one after the foreground color:


There are bold variants for both foreground and background colors

... etc.

... etc.

And a few special colors you’ll just have to try out to see (or just run doing colors):


Any time you use one of the foreground colors it will reset the bold and background settings to their default automatically. You can force a reset to default terminal colors using %default.

HTML Templates

For commands that provide an HTML output option, you can customize the templates used for markup and CSS. The markup uses HAML, and the styles are pure CSS.

To export the default configurations for customization, use doing templates --type=[HAML|CSS]. This will output to STDOUT where you can pipe it to a file, e.g. doing templates --type=HAML > my_template.haml. You can modify the markup, the CSS, or both.

Once you have either or both of the template files, edit .doingrc and look for the html_template: section. There are two subvalues, haml: and css:. Add the path to the templates you want to use. A tilde may be substituted for your home directory, e.g. css: ~/styles/doing.css.


Keywords in your entries can trigger automatic tagging, just to make life easier. There are three tools available: default tags, whitelisting, and synonym tagging.

Default tags are tags that are applied to every entry. You probably don’t want to add these in the root configuration, but using a local .doingrc in a project directory that defines default tags for that project allows anything added from that directory to be tagged automatically. A local .doingrc in my Marked development directory might contain:

default_tags: [marked,coding]

And anything I enter while in the directory gets tagged with @marked and @coding.

A whitelist is a list of words that should be converted directly into @tags. If my whitelist contains “design” and I type doing now working on site design, that’s automatically converted to “working on site @design.”

Synonyms allow you to define keywords that will trigger their parent tag. If I have a tag called @design, I can add “typography” as a synonym. Then entering doing now working on site typography will become “working on site typography @design.”

White lists and synonyms are defined like this:

    - typography
    - layout
    - thinking
    - idea
  - brainstorming
  - coding

Note that you can include a tag with synonyms in the whitelist as well to tag it directly when used.


doing [global options] command [command options] [arguments...]

Global options:

-f, --doing_file=arg - Specify a different doing_file (default: none)
--help               - Show this message
--[no-]notes         - Output notes if included in the template (default: enabled)
--stdout             - Send results report to STDOUT instead of STDERR
--version            - Display the program version
-x, --[no-]noauto    - Exclude auto tags and default tags


help           - Shows a list of commands and global options
help [command] - Shows help for any command (`doing help now`)

Adding entries:

now, next     - Add an entry
later         - Add an item to the Later section
done, did     - Add a completed item with @done(date). No argument finishes last entry.
meanwhile     - Finish any @meanwhile tasks and optionally create a new one
again, resume - Duplicate the last entry as new entry (without @done tag)

The doing now command adds an entry to the “Currently” section by default. It accepts -s section_name to send the new entry straight to a non-default section. It also accepts --back=AMOUNT to let you specify a start date in the past using “natural language.” For example, doing now --back=25m ENTRY or doing now --back="yesterday 3:30pm" ENTRY.

You can finish the last unfinished task when starting a new one using doing now with the -f switch. It will look for the last task not marked @done and add the @done tag with the start time of the new task (either the current time or what you specified with --back).


  • doing now Working on project X — Add a new entry at the current time
  • doing now --section=Projects Working on @projectX — Add a new entry to a section titled “Projects”
  • doing now --back 30m — Add a new entry with a backdated start time, indicating you’ve been working on it for 30 minutes already
  • doing now --back 8am — Backdate a new entry to a specific time
  • doing now -f Starting the next thing — Add a new entry at the current time, and add a @done tag to the previous item with the current time as its completion date
  • doing now -f --back 30m Working on something new — Add a new entry and complete the last entry, but use a timestamp from 30 minutes ago for both.

doing done is used to add an entry that you’ve already completed. Like now, you can specify a section with -s section_name. You can also skip straight to the Archive with -a.

doing done can also backdate entries using natural language with --back 15m or --back "3/15 3pm". That will modify the starting timestamp of the entry. Used on its own, it will set the start date, and the finish date will be the current time. You can also use --took 1h20m or --took 1:20 to set the finish date based on a “natural language” time interval. If --took is used without --back, then the start date is adjusted (--took interval is subtracted) so that the completion date is the current time.

When used with doing done, --back and --took allow time intervals to be accurately counted when entering items after the fact. --took is also available for the doing finish command, but cannot be used in conjunction with --back. (In finish they both set the end date, and neither has priority. --back allows specific days/times, --took uses time intervals.)


  • doing done --back 1h The thing I just did — Add an entry for a completed task that you started an hour ago and just finished
  • doing done --back 1h --took 20m The thing I just finished — Record an entry you started an hour ago and finished 20 minutes later
  • doing done --took 20m — Finish the last task but change the finish date so that the total elapsed time is only 20 minutes (if the finish date would be in the future, start date will be adjusted accordingly)

All of these commands accept a -e argument. This opens your command line editor (as defined in the environment variable $EDITOR). Add your entry, save the temp file, and close it. The new entry is added. Anything after the first line is included as a note on the entry.

doing again (or doing resume) will duplicate the last @done entry (most recently completed) with a new start date (and without the @done tag). To resume the last entry matching specific tags, use --tag=TAG. You can specify multiple tags by separating with a comma. Multiple tags are combined with ‘AND’ by default (all tags must exist on the entry to match), but you can use --bool= to set it to ‘OR’ or ‘NOT’. By default the new entry will be added to the same section as the matching entry, but you can specify a section with --in=SECTION.

doing meanwhile is a special command for creating and finishing tasks that may have other entries come before they’re complete. When you create an entry with doing meanwhile [entry text], it will automatically complete the last @meanwhile item (dated @done tag) and add the @meanwhile tag to the new item. This allows time tracking on a more general basis, and still lets you keep track of the smaller things you do while working on an overarching project. The meanwhile command accepts --back [time] and will backdate the @done tag and start date of the new task at the same time. Running meanwhile with no arguments will simply complete the last @meanwhile task.

See doing help meanwhile for more options.

Modifying entries:

finish      - Mark last X entries as @done
cancel      - Mark last X entries as @done without completion date
tag         - Tag last entry
note        - Add a note to the last entry

doing finish by itself is the same as doing done by itself. It adds @done(timestamp) to the last entry. It also accepts a numeric argument to complete X number of tasks back in history (0 affects all entries). Add -a to also archive the affected entries.

doing finish also provides an --auto flag, which you can use to set the end time of any entry to 1 minute before the start time of the next. Running a command such as doing finish --auto 10 will go through the last 10 entries and sequentially update any without a @done tag with one set to the time just before the next entry in the list.

As mentioned above, finish also accepts --back "2 hours" (sets the finish date from time now minus interval) or --took 30m (sets the finish date to time started plus interval) so you can accurately add times to completed tasks, even if you don’t do it in the moment.

Both done and finish accept an --archive switch which immediately moves the completed entries to the Archive section with a @from(Project) tag.

You can finish the last entry containing a specific tag or combination of tags using the --tag flag. Multiple tags are separated by commas. By default tags are combined with an AND boolean, meaning the entry must contain all specified tags to be considered. For example, to finish the last entry containing both “@work” and “@project1”, you would use:

doing finish --tag=work,project1

You can change the boolean using --bool=OR (last entry containing any of the specified tags) or --bool=NOT (last entry containing none of the tags).

You can also include a --no-date switch to add @done without a finish date, meaning no time is tracked for the task. doing cancel is an alias for this. Like finish, cancel accepts a count to act on the last X entries, as well as --archive and --section options. cancel also accepts the --tag and --bool flags for tag filtering.

By default doing finish works on a single entry, the last entry or the most recent entry matching a --tag or --search query. Specifying doing finish 10 would finish any unfinished entries within the last 10 entries. In the case of --tag or --search queries, the count serves as the maximum number of matches doing will act on, sorted in reverse date order (most recent first). A count of 0 will disable the limit entirely, acting on all matching entries.

Both finish and cancel accept --unfinished as an argument. This causes them to act on the last entry not already marked @done, no matter how far back it’s dated or how many @done entries come after it. You can use doing finish --unfinished X -s SECTION to finish the last X unfinished entries in SECTION.

Tagging and Autotagging

tag adds one or more tags to the last entry, or specify a count with -c X. Tags are specified as basic arguments, separated by spaces. For example:

doing tag -c 3 client cancelled

… will mark the last three entries as @client @cancelled. Add -r as a switch to remove the listed tags instead.

You can optionally define keywords for common tasks and projects in your .doingrc file. When these keywords appear in an item title, they’ll automatically be converted into @tags. The whitelist tags are exact (but case insensitive) matches.

You can also define synonyms, which will add a tag at the end based on keywords associated with it. When defining synonym keys, be sure to indent but not hyphenate the keys themselves, while hyphenating the list of synonyms at the same indent level as their key. See playing and writing in the example below for illustration. Follow standard YAML syntax.

To add autotagging, include a section like this in your ~/.doingrc file:

  - doing
  - mindmeister
  - marked
  - playing
  - working
  - writing
    - hacking
    - tweaking
    - toying
    - messing
    - blogging
    - posting
    - publishing
Tag transformation

You can include a transform section in the autotag config which contains pairs of regular expressions and replacement patterns separated by a colon. These will be used to look at existing tags in the text and generate additional tags from them. For example:

autotag: transform: - (\w+)-\d+:$1

This creates a search pattern looking for a string of word characters followed by a hyphen and one or more digits, e.g. @projecttag-12. Do not include the @ symbol in the pattern. The replacement ($1) indicates that the first matched group (in parenthesis) should be used to generate the new tag, resulting in @projecttag being added to the entry.


note lets you append a note to the last entry. You can specify a section to grab the last entry from with -s section_name. -e will open your $EDITOR for typing the note, but you can also just include it on the command line after any flags. You can also pipe a note in on STDIN (echo "fun stuff"|doing note). If you don’t use the -r switch, new notes will be appended to the existing notes, and using the -e switch will let you edit and add to an existing note. The -r switch will remove/replace a note; if there’s new note text passed when using the -r switch, it will replace any existing note. If the -r switch is used alone, any existing note will be removed.

You can also add notes at the time of entry by using the -n or --note flag with doing now, doing later, or doing done. If you pass text to any of the creation commands which has multiple lines, everything after the first line break will become the note.

If a string passed to now, later, or done has a parenthetical at the end, the parenthetical will be removed from the title and its contents added as a note. So doing now Working on @project1 (Adding some unit tests) would create an entry titled “Working on @project1” with a note “Adding some unit tests.” This is the equivalent of doing now Working on @project1 -n "Adding some unit tests".

Displaying entries:

show      - List all entries
recent    - List recent entries
today     - List entries from today
yesterday - List entries from yesterday
last      - Show the last entry
grep      - Show entries matching text or pattern

doing show on its own will list all entries in the “Currently” section. Add a section name as an argument to display that section instead. Use “all” to display all entries from all sections.

You can filter the show command by tags. Simply list them after the section name (or all). The boolean defaults to ANY, meaning any entry that contains any of the listed tags will be shown. You can use -b ALL or -b NONE to change the filtering behavior: doing show all done cancelled -b NONE will show all tasks from all sections that do not have either @done or @cancelled tags.

Use -c X to limit the displayed results. Combine it with -a newest or -a oldest to choose which chronological end it trims from. You can also set the sort order of the output with -s asc or -s desc.

The show command can also show the time spent on a task if it has a @done(date) tag with the -t option. This requires that you include a %interval token in template -> default in the config. You can also include @start(date) tags, which override the timestamp when calculating the intervals.

If you have a use for it, you can use -o csv on the show or view commands to output the results as a comma-separated CSV to STDOUT. Redirect to a file to save it: doing show all done -o csv > ~/Desktop/done.csv. You can do the same with -o json.

doing yesterday is great for stand-ups (thanks to Sean Collins for that!). Note that you can show yesterday’s activity from an alternate section by using the section name as an argument (e.g. doing yesterday archive).

doing on allows for full date ranges and filtering. doing on saturday, or doing on one month to today will give you ranges. You can use the same terms with the show command by adding the -f or --from flag. doing show @done --from "monday to friday" will give you all of your completed items for the last week (assuming it’s the weekend). There’s also doing since a simple alias for doing on PAST_DATE to now, e.g. doing since monday.

You can also show entries matching a search string with doing grep (synonym doing search). If you want to search with regular expressions or for an exact match, surround your search query with forward slashes, e.g. doing search /project name/. If you pass a search string without slashes, it’s treated as a fuzzy search string, meaning matches can be found as long as the characters in the search string are in order and with no more than three other characters between each. By default searches are across all sections, but you can limit it to one with the -s SECTION_NAME flag. Searches can be displayed with the default template, or output as HTML, CSV, or JSON.

Modifying the last entry

If you want to make a change to the last entry added, use doing last -e. The -e flag opens the last entry (including note) in your editor, and when you close your editor, your doing file will be updated with any changes you made to the entry.

You can choose the last entry in a specific section by including the -s flag, so doing last -s Later -e would edit the most recent entry in the Later section.

You can also use text search or a tag filter to get an entry earlier than the most recent one. A tag search with doing last --tag=project1 -e will edit the last entry tagged @project1. Multiple tags can be combined with commas, and you can use --bool to specify whether the search is AND (matches all tags given), OR (matches any tag given), or NOT (matches none of the tags).

You can edit the last entry that matches a search string with --search=QUERY. QUERY can either be a raw string, or you can surround it with slashes to search by regex (doing last --search="/project./" -e). If the string is raw text, fuzzy matching will be used, so the characters must be in order but can be separated by up to three other characters.

Both --tag and --search can be constrained to a single section with -s SECTION.


view     - Display a user-created view
views    - List available custom views

Display any of the custom views you make in ~/.doingrc with the view command. Use doing views to get a list of available views. Any time a section or view is specified on the command line, fuzzy matching will be used to find the closest match. Thus, lat will match Later, etc..


sections    - List sections
choose      - Select a section to display from a menu
add_section - Add a new section to the "doing" file


archive  - Move entries between sections
open     - Open the "doing" file in an editor (OS X)
config   - Edit the default configuration


    -k, --keep=arg - Count to keep (ignored if archiving by tag) (default: 5)
    -t, --to=arg   - Move entries to (default: Archive)
    -b, --bool=arg - Tag boolean (default: AND)

The archive command will move entries from one section (default: Currently) to another section (default: Archive).

doing archive on its own will move all but the most recent 5 entries from currently into the archive.

doing archive other_section will archive from other_section to Archive.

doing archive other_section -t alternate will move from other_section to alternate. You can use the -k flag on any of these to change the number of items to leave behind. To move everything, use -k 0.

You can also use tags to archive. You define the section first, and anything following it is treated as tags. If your first argument starts with @, it will assume all sections and assume any following arguments are tags.

By default, tag archiving uses an AND boolean, meaning all the tags listed must exist on the entry for it to be moved. You can change this behavior with -b OR or -b NONE (ALL and ANY also work).

Example: Archive all Currently items for @client that are marked @done

doing archive @client @done

Doing can currently only import tasks from reports. If you want to sync up your Doing file with Timing’s tracking:

  1. Open Timing and go to Reports
  2. Set the date span you want to import into doing
  3. Group by Project, Then by None
  4. Include Tasks with Title, (not as subgroup), Timespan, and Notes
  5. Uncheck App Usage
  6. Set File Format to JSON and Duration format to “XX:YY:ZZ”
  7. Include short entries if desired
  8. Export the report to a new file

Now you can run doing import --type timing -s SECTION PATH, where SECTION is the name of the section you want to import the entries to (defauts to Currently), and PATH is the path to the JSON file. You can also add a tag (or tags) to all entries, or a custom prefix.

(--type timing is the only option right now, so it doesn’t need to be included)

# Import entries to Projects section and add @timing to all new entries
doing import -s Projects --tag=timing "~/Desktop/All Activities.json"

# Import to default section (Currently) and prefix entries with '[Imported]'
doing import --prefix="[Imported]" "~/Desktop/All Activities.json"

Interactive Usage

If you have fzf installed (, you can use doing select to get a menu of all your items (or items in a given section) which can be searched with fuzzy matching. The menu allows multiple selections to be acted on directly.

To use the menu, type a search string or use the arrow keys to navigate up and down. Press tab on an entry you’d like to perform an action on. A marker will show up on the left indicating the entry is selected. Repeat the process and select as many entries as needed. When you hit Return, the selection will be passed back to doing. Use Control-A to select all visible entries.

Doing can perform several functions with this menu. Not all of doing’s features are available, but the core functionality you’d need is there, plus you can open the selected entries on one page in your text editor, make changes to them, and when you save and close the entries are updated accordingly. This allows editing of everything from timestamps to tags to notes.

Run doing help select for a list of options:

-a, --archive         - Archive selected items
-c, --cancel          - Cancel selected items (add @done without timestamp)
-d, --delete          - Delete selected items
-e, --editor          - Edit selected item(s)
-f, --finish          - Add @done with current time to selected item(s)
--flag                - Add flag to selected item(s)
-m, --move=SECTION    - Move selected items to section (default: none)
-s, --section=SECTION - Select from a specific section (default: none)
-t, --tag=TAG         - Tag selected entries (default: none)

For example, doing select -d -a would present the menu, and then mark selected entries as @done (with timestamp) and move them to the Archive section.

Multiple actions can be performed at once by combining options. You can also combine the --editor switch with any other options. Other actions will be performed first, then the entries — with any modifications performed — will be presented in the editor for tweaking.

Note: when using the --editor flag to open selections in your text editor, entries will be separated by --- lines. These must remain in place for doing to track the changes. You can do anything you want to the entries, modify dates, change text, add notes, etc., as long as you leave the dividers in place. You can even delete an entry entirely, leaving the dividers around the missing line and the entry will be removed from your doing file when you save and exit the editor.


Shell completion

Bash: See the file doing.completion.bash in the git repository for full bash completion. Thanks to fcrespo82 for getting it started.

Zsh: See the file doing.completion.zsh in the git repository for zsh completion. Courtesy of Gabe Anzelini.

Fish: See the file in the git repository for Fish completion. This is the least complete of all of the completions, but it will autocomplete the first level of subcommands, and your custom sections and views for the doing show and doing view commands.


The LaunchBar action requires that doing be available in /usr/local/bin/doing. If it’s not (because you’re using RVM or similar), you’ll need to symlink it there. Running the action with Return will show the latest 9 items from Currently, along with any time intervals recorded, and includes a submenu of Timers for each tag.

Pressing Spacebar and typing allows you to add a new entry to currently. You an also trigger a custom show command by typing “show [section/tag]” and hitting return. Include any command line flags at the end of the string, and if you add text in parenthesis, it will be processed as a note on the entry.

Point of interest, the LaunchBar Action makes use of the -o json flag for outputting JSON to the action’s script for parsing.

Doing for LaunchBar v2.2

A LaunchBar action for use with doing

Published 02/07/20.

Updated 07/01/21. Changelog

DonateMore info…

Evan Lovely has created an Alfred workflow as well.


Errors after “Successfully installed…”

If you get errors in the terminal immediately after a message like:

Successfully installed doing-x.x.x
2 gems installed

…it may just be documentation related. If running doing works, you can ignore them. If not, try running the install command again with --no-document:

$ gem install --no-document doing

Command not found

If running doing after a successful install gives you a “command not found” error, then your gem path isn’t in your $PATH, meaning the system can’t find it. To locate the gem and link it into your path, you can try this:

cd $GEM_PATH/bin
ln -s doing /usr/local/bin/

Then try running doing and see if it works.

Encoding errors

Ruby is rife with encoding inconsistencies across platforms and versions. Feel free to file issues (see below).


As a free project, doing isn’t heavily supported, but you can get support from myself and other users on GitHub. If you run into a replicatable bug in your environment, please post an issue and include your platform, OS version, and the result of ruby -v, along with a copy/paste of the error message. To get a more verbose error message, try running GLI_DEBUG=true doing [...] for a full trace.

Please try not to email me directly about GitHub projects.

Developer notes

Feel free to poke around, I’ll try to add more comments in the future (and retroactively).



  • Refine editing multiple selections (doing select)


  • Add –tag and –search flags to tag command to tag all entries matching search terms
  • Add since command, which is the same as doing on tuesday to now but doing since tuesday just feels more intuitive.


  • Fix for timeline output


  • Add doing select to show menu of all tasks, searchable with fuzzy matching and the ability to perform certain tasks on multiple selections.


  • Fix for template command not working at all


  • Fix for doing done --took 30m setting the wrong @done timestamp when completing previous item


  • Add --unfinished option to finish and cancel commands


  • Fix error in doing show --sort argument parsing


  • Gem packaging error


  • Fix for some long flags being interpreted as arrays instead of strings
  • More flexible boolean specification, can be: all, and, any, or, not, or none
  • Fix for archive command not removing original entries from archived section


  • Prevent duplicates/overlapping entries when importing


  • Initial import feature for reports


  • README updates
  • If doing done --took=X results in completion date greater than current time, use current time as completion date and backdate the entry’s timestamp to fit


  • Fix: doing done with --took= and without --back= should set end time to start date plus --took value


  • Add –search filter to doing archive



  • Default value for doing again --bool was ALL, should be AND



  • Improvements to doing again --tag= functionality



  • Finish previous task if doing again and not already completed



  • Unit tests



  • Tag command tests


  • Doing not reading per-directory .doingrc configs



  • Added config_editor_app setting to config so you can have
  • A parenthetical at the end of an entry title becomes an attached
  • --editor flag for doing last to edit last entry
  • --tag= flag to filter doing last by tag
  • --search= to filter doing last by text/regex search
  • --search= for doing finish, finish last X entries matching search
  • Add tags_color as a primary config key to highlight @tags in displayed entries


  • Clean up command line help
  • –editor improvements for all commands that use it


  • Doing finish –took throwing error
  • Doing tag –remove was adding tags if they didn’t exist
  • Creating a meanwhile task with a note resulted in an error



  • Bugfix for finish --tag=TAG



  • --tag and --bool filtering for again/resume, cancel
  • --in flag for again/resume to specify to which section the new
  • Finish command accepts --tag= flag, finishing last entry
  • doing cancel to end X tasks without completion date (alias for


  • Add –no-color option to view command
  • Add –tag to show for compatibility


  • Error running finish without –tag flag
  • –archive flag on finish, done, and cancel causing error



  • Finish command accepts --tag= flag, finishing last entry
  • doing cancel to end X tasks without completion date (alias for


  • –archive flag on finish, done, and cancel causing error


  • Fix for missing date on @done tags


  • Fix confirmation dialog for doing tag -a -c 0 (autotag all)


  • Remove check for file existence before attempting to run run_after script
  • Don’t autotag entries restarted with again/resume
  • Add short flags (-b) for --back on all commands that support it


  • Code cleanup


  • Only execute run_after script if changes are written


  • Remove unneccessary console logging


  • Add again command to repeat last entry without @done tag
  • Add run_after configuration option to execute external script after any change


  • Fix note indentation in doing file


  • Fix for repeated backreferences in tag transform


  • Add --tag_sort to all subcommands with --totals option


  • Tag transforms
  • Option to sort tags by name in –totals


  • Gem dependency updates


  • Fix for array comparison error


  • Bugfixes


  • Global option -x to skip autotags and default_tags from global/local .doingrc
  • Remove extra spaces when creating entry


  • More graceful writing of default config (~/.doingrc) on first run
  • Repaired testing setup. Needs moar tests.


  • Add --at flag for doing done, e.g. doing done --at=1:35pm --took=15m A new task I already finished
  • Allow decimal quantities when using natural language for hours or days, e.g. --took=2.5h
  • Add did as a synonym for done subcommand


  • Smarter method of getting user $HOME
  • Improved avoiding duplicate tags when autotagging
  • Improved autotag reporting


  • doing note operates on whatever is most recent, not just the last note in Currently
  • doing tag with no count specified operates on most recent entry in any section, not just Currently
  • doing tag with a count greater than 1 requires a section to be specified
  • Improved results reporting for doing tag
  • When removing tag do a whole-word match to avoid removing part of a longer tag


  • Apply default_tags after autotagging to avoid tags triggering tags
  • Set doing recent to default to All sections instead of Currently
  • Fix error in time reporting
  • improved y/n prompt for TTY


  • Fix handling of “local” config files, allowing per-project configurations
  • Allow cascading of local config files
  • Allow doing today and yesterday to specify a section


  • Add legitimate regex search capabilities
  • Synonyms for grep (search) and now (next)
  • CSS fix


  • Rewrite HTML export templates with responsive layout and typography
  • Ability to customize the HTML output using HAML and CSS
  • New command doing templates to export default templates for HAML and CSS
  • New config options under html_template for haml and css


  • For doing note -e include the entry title so you know what you’re adding a note to
  • For any other command that allows -e include a comment noting that anything after the first line creates a note
  • Ignore # comments when parsing editor results
  • Add a .md extension to the temp file passed to the editor so you can take advantage of any syntax highlighting and other features in your editor


  • Fix undefined method [] for nil class error in doing view
  • Loosened up the template color resetting a bit more


  • Add --stdout global option to send reporting to STDOUT instead of STDERR (for use with LaunchBar et al)


  • Fixes overzealous color resetting


  • CLI/text totals block was outputting when HTML output was selected
  • Have all template colors reset bold and background automatically when called


Catching up on the changelog. Kind of. A lot has happened, mostly fixes.

  • Fish completion
  • views and sections subcommands have -c option to output single column
  • Fix html title when tag_bool is NONE
  • Fix @from tagging missing closing paren
  • Fix tag coloring


  • Fix gsub error in doing meanwhile


  • JSON output option to view commands
  • Added autotagging to tag command
  • date filtering, improved date language
  • added doing on command
  • let view templates define output format (csv, json, html, template)
    • add %chompnote template variable (item note with newlines and extra whitespace stripped)


  • fix for -v option
  • Slightly fuzzier searching in the grep command
  • cleaner exits, only_timed key for view configs
  • making the note command append new notes better, and load existing notes in the editor if -e is called
  • handle multiple tag input in show tag filter
  • Global tag operations, better reporting


  • Improved HTML output
  • --only_timed option for view/show commands that only outputs items with elapsed timers (interval between start and done dates)
  • add seconds for timed items in CSV output, run --only_timed before chopping off --count #
  • fix for 1.8.7 Dir.home issue
  • version bump
  • don’t show tag totals with zero times
  • zsh completion for doing
  • HTML styling
  • --only_timed option
  • added zsh completion file to
  • add zsh completion file


  • done command: making --took modify start time if --back isn’t specified
  • Cleaned up time totals, improved HTML output
  • fixes for --back and --took parsing
  • Adding more complete terminal reporting to archive command


  • Skipped ahead in the version numbering. Because I don’t care.
  • Added a note command and --note flags for entry creation commands


  • --totals, --[no-]times, --output [csv,html] options for yesterday command.
  • Add tests for Darwin to hide OS X-only features on other systems
  • -f flag to now command for finishing last task when starting a new one (Looks back for the last unfinished task in the list)
  • --took option for done and finish for specifying intervals from the start date for the completion date
  • Basic command line reporting
  • --auto flag for finish and done that will automatically set the completion time to 1 minute before the next start time in the list. You can use it retroactively to add times to sequential todos.
  • doing grep for searching by text or regex


  • Default to showing times #26, show totals even if no tags exist #27, fix indentation #29
  • Add section label to archived tasks automatically, excepting Currently section
  • Today outputs and backdate for finish
  • HTML styling and fix for 1.8.7 haml errors
  • Look, HTML output! (--output html)
  • Also, --output csv
  • let doing archive function on all sections
  • option to exclude date from @done,
  • output newlines in sections and views
  • Flagging (doing mark)
  • fix for view/section guess error
  • Adding tag filtering to archive command (doing archive \@done)
  • doing yesterday
  • doing done -r to remove last doing tag (optionally from -s Section)
  • Add -f flag to specify alternate doing file
  • meanwhile command


  • CSV output for show command (--csv)
  • HTML output for show command (--output html)
  • fuzzy searching for all commands that specify a view.
    • In the terminal, you’ll see “Assume you meant XXX” to show what match it found, but this is output to STDERR (and won’t show up if you’re redirecting the output or using it in GeekTool, etc.)
  • tags_color in view config to highlight tags at the end of the lines. Can be set to any of the %colors.
  • Basic time tracking.
    • -t on show and view will turn on time calculations
    • Intervals between timestamps and dated @done tags are calculated for each line, if the tag exists.
    • You must include a %interval token in the appropriate template for it to show
    • @start(date) tags can optionally be used to override the timestamp in the calculation
    • Any other tags in the line have that line’s total added to them
    • Totals for tags can be displayed at the end of output with --totals


  • doing done without argument tags last entry done
    • -a archives them
  • doing finish or doing finish X marks last X entries done
    • -a archives them
  • doing tag tag1 [tag2] tags last entry or -c X entries
    • doing tag -r tag1 [tag2] removes said tag(s)
  • custom views additions
    • custom views can include tags and tags_bool
      • tags is a space-separated list of tags to filter the results by
      • tags_bool defines AND (all tags must exist), OR (any tag exists), or NONE (none of the tags exist)
    • order key (asc or desc) defines output sort order by date
    • section key can be set to All to combine sections
  • doing show updates
    • accepts all as a section
    • arguments following section name are tags to filter by
      • -b sets boolean (AND, OR, NONE) or (ALL, ANY, NONE) (default OR/ANY)
    • use -c X to limit results
    • use -s to set sort order (asc or desc)
    • use -a to set age (newest or oldest)
  • fuzzy section guessing when specified section isn’t found
  • fuzzy view guessing for doing view command


  • colors in templated output
  • open command
    • opens in the default app for file type
    • -a APPNAME (doing open -a TaskPaper)
    • -b bundle_id (doing open -b com.sublimetext.3)
  • -e switch for now, later and done commands
    • save a tmp file and open it in an editor
    • allows multi-line entries, anything after first line is considered a note
    • assumed when no input is provided (doing now)
  • doing views shows all available custom views
  • doing view without a view name will let you choose a view from a menu
  • doing archive fixed so that -k X works to keep X number of entries in the section


  • colors in templated output
  • open command
    • opens in the default app for file type
    • -a APPNAME (doing open -a TaskPaper)
    • -b bundle_id (doing open -b com.sublimetext.3)
  • -e switch for now, later, and done commands
    • save a tmp file and open it in an editor
    • allows multi-line entries, anything after first line is considered a note
    • assumed when no input is provided (doing now)

Speaking of doing…

Related Projects