Jekyll2021-03-10T15:11:36+01:00https://stevenvanbael.com/Steven Van BaelThe open calendar, task and note space is a mess2021-03-10T11:00:00+01:002021-03-10T11:00:00+01:00https://stevenvanbael.com/open-calendar-task-space-is-a-mess<p>The last few weeks I’ve been looking into the open calendar, tasks and notes space with the goal of finding or building a privacy-conscious and still practical system.
This post is an exploration of the available technology in that space, its problems and how to solve them.</p>
<p>For context: I use Windows, MacOS and Linux on my computers on a daily basis, my daily driver phone is an iPhone. I don’t care much for collaboration with other people using these tools, my focus is to keep control over my personal data and build a workflow that works well for my day to day work.</p>
<h2 id="what-i-want">What I want</h2>
<p>When I set out on my journey I had the following goals in mind:</p>
<ul>
<li>I control the source of truth for all calendars, tasks and notes data by means of a self-hosted solution.</li>
<li>I can view and edit the data on all my machines (MacOS, Windows, Linux, iOS, Android) <em>in a consistent manner</em>.</li>
<li>Use standard protocols (CalDAV/iCalendar for calendars and tasks, WebDAV for notes).</li>
<li>Preference for FOSS software but not a hard requirement: for example it’s OK to use a proprietary app like the iOS Calendar app if it supports pulling
data from my datastore and is consistent with other clients.</li>
<li>Easy to work with multiple calendar and task sets so I can logically group data by project and still have a combined view available.</li>
<li>For tasks specifically I would like to have subtask support so I can divide a large task into multiple subtasks and track completion of the whole.</li>
<li>Ideally I want to be able to hook into task lifecycle events so I can execute my own logic when tasks are created or finished.</li>
<li>Notes in markdown format</li>
</ul>
<p>My ideal solution would be an open source CalDAV/WebDAV server storing data, and a cross-platform client that works on all desktop/mobile platforms. I can live with a different desktop and mobile app but I do not want to have 3 different desktop GUIs.</p>
<h2 id="what-i-found">What I found</h2>
<p>CalDAV and iCalendar are the established standard protocols for synchronizing calendars and tasks but these protocols have some issues:</p>
<ul>
<li>They are very old and have accrued quite a bit of legacy</li>
<li>There is a lack of libraries implementing these protocols, there are libraries for languages like PHP, Java and C but these implementations are typically unmaintained and because of the nature of these languages they are not very suitable for the modern cross-platform world.</li>
<li>Because of the lack of libraries in modern languages there are no fully cross-platform clients</li>
<li>Things like subtasks are not originally in the RFC, there is support for related references in iCalendar objects but clients use wildly different implementations
of this so getting consistent subtask behavior across clients is a challenge.</li>
</ul>
<p>It’s not all bad, CalDAV has good support for synchronizing resources and limiting sync to only objects that have changed by using etags metadata and sync tokens.</p>
<p>WebDAV is a good standard for synchronizing files and since most note apps are just markdown editors with sync capabilities notes are not as problematic. Hence I will mainly focus the rest of this post on calendars and tasks.</p>
<h2 id="selfhosted-source-of-truth-storage">Selfhosted Source of Truth Storage</h2>
<p>The goal here is to have a selfhosted storage backend that exposes the data using CalDAV, iCalendar and WebDAV protocols.
These are the solutions I tried:</p>
<h3 id="owncloudnextcloud">Owncloud/Nextcloud</h3>
<p>Owncloud and its fork Nextcloud are self-hosted solutions for file sync and collaboration. It can be used as CalDAV+WebDAV storage and has a Web GUI for interacting with the data.</p>
<p>Pros:</p>
<ul>
<li>Open Source</li>
<li>Supports CalDAV/iCalendar protocols</li>
<li>Supports WebDAV protocol for file and note sync</li>
<li>Supports multiple calendar and task sets</li>
<li>Easy to deploy as a docker image</li>
<li>Includes authentication</li>
<li>Includes web GUI client for tasks with support for subtasks</li>
</ul>
<p>Cons:</p>
<ul>
<li>Written in old PHP and there is work underway to do a complete rewrite in Golang</li>
<li>Its GUI subtask implementation is not recognized by some other clients</li>
</ul>
<h3 id="radicale">Radicale</h3>
<p>Radicale is a Python project that implements CalDAV storage for calendars and tasks.</p>
<p>Pros:</p>
<ul>
<li>Open Source</li>
<li>Easy to deploy as a docker image</li>
<li>Simple configuration</li>
<li>Supports multiple calendar and task sets</li>
<li>No GUI, just storage</li>
</ul>
<p>Cons:</p>
<ul>
<li>No WebDAV support, needs a separate server</li>
<li>Does not handle authentication by default, needs to be handled by the reverse proxy</li>
</ul>
<h3 id="sabre">Sabre</h3>
<p>SabreDAV is a CalDAV server written in PHP</p>
<p>Pros:</p>
<ul>
<li>Open source</li>
<li>Support CalDAV/iCalendar protocols</li>
<li>Supports multiple calendars and task sets</li>
<li>Includes authentication</li>
<li>Extensive setup documentation and guides</li>
<li>No GUI, just storage</li>
</ul>
<p>Cons:</p>
<ul>
<li>Written in old PHP, according to the homepage it requires PHP 5.4</li>
<li>No WebDAV support, needs a separate server</li>
</ul>
<h3 id="other-backends">Other backends</h3>
<p>There are other projects like Chandler/Cosmo but those are in an even worse state than the ones I mentioned above.</p>
<p>Google Calendar can be used as a CalDAV backend but that means the source of truth is not under my control so that’s a non starter.</p>
<p>For my purposes, an installation of Owncloud or Radicale + an external WebDav server seems to fit best.</p>
<h2 id="clients">Clients</h2>
<p>After setting up local evaluation versions of Owncloud and Radicale, I then tested a number of clients on different platforms to see how they interact.</p>
<h3 id="web-owncloud-gui">Web: Owncloud GUI</h3>
<p>The Web GUI that comes with Owncloud</p>
<p>Pros:</p>
<ul>
<li>Open Source</li>
<li>Good for basic calendar and task management</li>
<li>Simple CRUD operations</li>
<li>Supports subtasks</li>
<li>Web-based so it works on all platforms</li>
</ul>
<p>Cons:</p>
<ul>
<li>No support for additional views or filters</li>
<li>Not very mobile optimized</li>
<li>Just like the rest of Owncloud, written in PHP, and a rewrite in Golang is underway</li>
</ul>
<h3 id="linux-korganizer">Linux: KOrganizer</h3>
<p>A QT-based Linux app, part of the KDE productivity suite.</p>
<p>Pros:</p>
<ul>
<li>Open Source</li>
<li>Syncs well with both Owncloud and Radicale</li>
<li>Supports multiple calendar and task sets and allows view filtering and custom views</li>
<li>Very customizable in terms of colors, views and workflow</li>
<li>Fast and does not consume much resources</li>
<li>Recognizes subtasks created in the Owncloud Web GUI and has good subtask support</li>
</ul>
<p>Cons:</p>
<ul>
<li>Even though it is QT-based and open source, it relies on KDE and is therefore not suitable for running on MacOS or Windows</li>
<li>No mobile equivalent</li>
<li>Has trouble with subtasks created by other clients like 2Do</li>
</ul>
<h3 id="windows-essentialpim">Windows: EssentialPIM</h3>
<p>Pros:</p>
<ul>
<li>it’s the only non-web client I got working on Windows</li>
</ul>
<p>Cons:</p>
<ul>
<li>Not open source</li>
<li>Needs a Pro subscription to enable CalDAV sync</li>
<li>Every calendar and task set needs to be synchronized separately</li>
<li>No way to filter views on a calendar or task set</li>
<li>Windows only</li>
</ul>
<h3 id="ios--macos-2do">iOS & MacOS: 2DO</h3>
<p>I only tried the iOS version of this app, I assume the MacOS version works in a similar way.</p>
<p>Pros:</p>
<ul>
<li>Nice and fast GUI</li>
<li>Supports multiple calendar and task sets</li>
<li>Supports view filtering per calendar or task set</li>
<li>Same app for MacOS, iOS and Android</li>
</ul>
<p>Cons:</p>
<ul>
<li>It uses its own implementation for subtasks which is not recognized by most of the other clients</li>
<li>Does not recognize subtasks from KOrganizer or Owncloud</li>
<li>No equivalent on Linux or Windows</li>
</ul>
<h3 id="ios--macos-native-calendar-and-reminder-apps">iOS & MacOS: Native Calendar and Reminder apps</h3>
<p>The native calendar/reminder app on iOS supports pulling data from CalDAV but I could not get it to work with my local test instances of Owncloud and Radicale.</p>
<h3 id="cross-platform-notes-joplin">Cross platform notes: Joplin</h3>
<p>Joplin is an open source note taking app that has apps on all platforms and syncs over WebDAV.</p>
<p>Pros:</p>
<ul>
<li>Open Source</li>
<li>Supports WebDAV protocol</li>
<li>Works on all desktop and mobile platforms</li>
<li>Notes in Markdown</li>
<li>Supports vim keybindings</li>
</ul>
<p>Cons:</p>
<ul>
<li>I don’t have anything negative to say about Joplin yet, only the fact that its desktop apps are electron-based which is not great for resource usage. But then again that is the reason why they can deliver a consistent experience on all platforms.</li>
</ul>
<h3 id="other-cross-platform-solutions">Other Cross platform solutions</h3>
<p>I could not find any calendar/task clients that are available on all 3 desktop and 2 mobile platforms. Or even one that just works the same on all 3 desktop platforms.</p>
<p>There are apps that work well on all platforms, for example Todoist, but typically they don’t support open protocols like CalDAV and using them means having all data locked up in their silo.</p>
<h3 id="others">Others</h3>
<p>These are just the apps I was able to test quickly, there might be others but most of them have a non-starter property.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The open calendar, task and notes space is very fragmented due to old protocols, wildly varying implementations and a lack of cross-platform support libraries. It’s a challenge to find a combination of storage server and clients that work well together on all platforms.
To this day I did not succeed in finding a combination that satisfies all my requirements, aside from notes using WebDAV+Joplin.</p>
<p>So for now, I will probably start by setting up WebDAV+Joplin for notes, and keep using Google Calendar and Todoist for calendars and tasks until I figure out a complete solution.</p>
<h2 id="how-to-fix-this-in-the-future">How to fix this in the future</h2>
<p>Although the CalDAV and iCalendar protocols have their downsides, I think they are still the way to go for the foreseeable future and we should not discard them or try to replace them with something else.</p>
<p>We as a developer community can improve the situation by directing some community effort into the writing and maintenance of modern portable libraries for these protocols.</p>
<p>I myself intend to start working on a set of Rust libraries that implement these protocols (and optionally sync+localstorage behavior), combined with some FFI language wrappers so they can be easily used from cross-platform toolkits (JS for Electron, Dart for Flutter, Rust for native come to mind)</p>Steven Van Baelsteven@quantus.ioThe last few weeks I’ve been looking into the open calendar, tasks and notes space with the goal of finding or building a privacy-conscious and still practical system. This post is an exploration of the available technology in that space, its problems and how to solve them.Profiling zsh startup time2018-08-17T12:00:00+02:002018-08-17T12:00:00+02:00https://stevenvanbael.com/profiling-zsh-startup<p>I am a heavy <code class="highlighter-rouge">tmux</code> and <code class="highlighter-rouge">zsh</code> user and today I noticed that starting a new tmux pane started getting slow. Sometimes it took more than 1 second for my shell in the new pane to become interactive.
The only thing a new pane is doing is starting up <code class="highlighter-rouge">zsh</code>, so zsh initialization was the likely culprit.</p>
<h2 id="measuring-initial-startup-time">Measuring initial startup time</h2>
<p>As with any optimization, before we start making changes we want to measure the current performance. The following command shows us how long it takes for zsh to startup and become interactive.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span><span class="nb">time </span>zsh -i -c <span class="nb">exit
</span>zsh -i -c <span class="nb">exit </span>0.67s user 0.06s system 86% cpu 0.842 total
</code></pre>
</div>
<h2 id="enabling-profiling">Enabling profiling</h2>
<p>Zsh has a builtin profiler to profile startup time usage. It is called <code class="highlighter-rouge">zprof</code> and can be enabled by adding <code class="highlighter-rouge">zmodload zsh/zprof</code> to the top and <code class="highlighter-rouge">zprof</code> to the bottom of your <code class="highlighter-rouge">~/.zshrc</code>.</p>
<p>Now when we start up zsh, it will start profiling, execute the rest of <code class="highlighter-rouge">~/.zshrc</code> and print out the results:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>zsh
num calls <span class="nb">time </span>self name
-----------------------------------------------------------------------------------
1<span class="o">)</span> 1 305.98 305.98 50.52% 305.95 305.95 50.51% nvm_die_on_prefix
2<span class="o">)</span> 1 463.42 463.42 76.51% 82.96 82.96 13.70% nvm
3<span class="o">)</span> 1 79.69 79.69 13.16% 79.53 79.53 13.13% __kubectl_bash_source
4<span class="o">)</span> 1 74.43 74.43 12.29% 74.43 74.43 12.29% nvm_ensure_version_installed
5<span class="o">)</span> 3 30.63 10.21 5.06% 30.63 10.21 5.06% compaudit
6<span class="o">)</span> 1 12.47 12.47 2.06% 12.32 12.32 2.03% __kops_bash_source
7<span class="o">)</span> 1 20.58 20.58 3.40% 7.16 7.16 1.18% compinit
8<span class="o">)</span> 2 3.33 1.66 0.55% 3.33 1.66 0.55% env_default
9<span class="o">)</span> 2 3.24 1.62 0.53% 3.24 1.62 0.53% grep-flag-available
10<span class="o">)</span> 1 465.72 465.72 76.89% 2.30 2.30 0.38% nvm_auto
11<span class="o">)</span> 1 1.31 1.31 0.22% 1.31 1.31 0.22% colors
12<span class="o">)</span> 18 1.03 0.06 0.17% 1.03 0.06 0.17% compdef
13<span class="o">)</span> 1 0.73 0.73 0.12% 0.73 0.73 0.12% nvm_supports_source_options
14<span class="o">)</span> 1 0.27 0.27 0.04% 0.27 0.27 0.04% is-at-least
15<span class="o">)</span> 2 0.31 0.16 0.05% 0.16 0.08 0.03% <span class="nb">complete
</span>16<span class="o">)</span> 4 0.11 0.03 0.02% 0.11 0.03 0.02% is_plugin
17<span class="o">)</span> 3 0.11 0.04 0.02% 0.11 0.04 0.02% nvm_has
18<span class="o">)</span> 1 0.06 0.06 0.01% 0.06 0.06 0.01% start_tmux
19<span class="o">)</span> 2 0.05 0.03 0.01% 0.05 0.03 0.01% bashcompinit
20<span class="o">)</span> 1 466.49 466.49 77.02% 0.04 0.04 0.01% nvm_process_parameters
...
</code></pre>
</div>
<p>These results show that almost 90% of startup time is taken by <code class="highlighter-rouge">nvm</code> (the Nodejs version manager) and bash completion initialization for <code class="highlighter-rouge">kubectl</code> and <code class="highlighter-rouge">kops</code> (2 kubernetes tools).</p>
<p>I commented out the <code class="highlighter-rouge">nvm</code> initialization as I don’t use Node anymore. I moved the Kubernetes bash completion initialization inside a <code class="highlighter-rouge">kube()</code> function that was already there for configuration my kubernetes credentials. This way the bash completions only load lazily when I configure my shell for a specific kubernetes cluster.</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="k">function </span>kube<span class="o">()</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">[</span> <span class="nv">$commands</span><span class="o">[</span>kubectl] <span class="o">]</span>; <span class="k">then
</span><span class="nb">source</span> <<span class="o">(</span>kubectl completion zsh<span class="o">)</span>
<span class="k">fi
if</span> <span class="o">[</span> <span class="nv">$commands</span><span class="o">[</span>kops] <span class="o">]</span>; <span class="k">then
</span><span class="nb">source</span> <<span class="o">(</span>kops completion --shell zsh<span class="o">)</span>
<span class="k">fi</span>
<span class="c"># omitted kubectl configuration code</span>
<span class="o">}</span>
</code></pre>
</div>
<h2 id="measuring-results-again">Measuring results again</h2>
<p>After making the changes I ran zsh with the profiler again:</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span>zsh
num calls <span class="nb">time </span>self name
-----------------------------------------------------------------------------------
1<span class="o">)</span> 3 22.71 7.57 60.31% 22.71 7.57 60.31% compaudit
2<span class="o">)</span> 1 17.40 17.40 46.20% 6.85 6.85 18.20% compinit
3<span class="o">)</span> 2 3.14 1.57 8.34% 3.14 1.57 8.34% grep-flag-available
4<span class="o">)</span> 2 2.73 1.36 7.24% 2.73 1.36 7.24% env_default
5<span class="o">)</span> 1 0.96 0.96 2.55% 0.96 0.96 2.55% colors
6<span class="o">)</span> 16 0.89 0.06 2.37% 0.89 0.06 2.37% compdef
7<span class="o">)</span> 1 0.22 0.22 0.58% 0.22 0.22 0.58% is-at-least
8<span class="o">)</span> 4 0.08 0.02 0.22% 0.08 0.02 0.22% is_plugin
9<span class="o">)</span> 1 0.07 0.07 0.19% 0.07 0.07 0.19% start_tmux
</code></pre>
</div>
<p>And with profiling disabled to measure the result of our optimizations</p>
<div class="language-bash highlighter-rouge"><pre class="highlight"><code><span class="gp">$ </span><span class="nb">time </span>zsh -i -c <span class="nb">exit
</span>zsh -i -c <span class="nb">exit </span>0.04s user 0.03s system 70% cpu 0.108 total
</code></pre>
</div>
<p>Now it starts up in 108ms instead of 842ms which is a noticeable improvement when opening new tmux panes.</p>
<p>The largest offenders now seem to be <code class="highlighter-rouge">compaudit</code> and <code class="highlighter-rouge">compinit</code> which need 22ms and 17ms to complete. I did a Google search to find solutions for improving these but I could not find anything that was worth the effort. For now +- 100ms startup time for Zsh is <code class="highlighter-rouge">good enough</code> and I’m going to call it a day.</p>Steven Van Baelsteven@quantus.ioI am a heavy tmux and zsh user and today I noticed that starting a new tmux pane started getting slow. Sometimes it took more than 1 second for my shell in the new pane to become interactive. The only thing a new pane is doing is starting up zsh, so zsh initialization was the likely culprit.Back to basics: A minimalist website2018-07-09T12:00:00+02:002018-07-09T12:00:00+02:00https://stevenvanbael.com/back-to-basics<p>This week I’ve come across some articles (links at the end) that made me pull the trigger on executing an idea
I’ve been thinking about for a very long time: Rework my personal website to be as minimalist as it can be.</p>
<p>I have been dipping my toes into the minimalist lifestyle for a few years now but I have not yet fully committed to it
in my digital life. This is about to change.</p>
<h2 id="what-is-a-website-and-what-is-its-purpose">What is a website and what is its purpose?</h2>
<p>One of the core principles in the minimalism movement is to get rid of useless clutter and focus on the essentials.</p>
<p>Before we can apply this principle onto a website, we need to know what
the essential pieces of a website are. And in order to know that, we first need to define what a website is.</p>
<p>I like to use the following description:</p>
<blockquote>
<p>A website is a body of content created or compiled by its owner to be consumed by its visitor.</p>
</blockquote>
<p><em>Content</em> is the keyword here and consuming it is the only reason why people are visiting.
Anything else is just a <em>distraction</em> (advertisements, design elements, animations), or worse, an invasion of their privacy (user tracking).</p>
<h2 id="so-what-did-i-do">So what did I do?</h2>
<p>I opened up the jekyll project folder for this blog and started deleting everything that was not essential:</p>
<ul>
<li>all CSS stylesheets including the Bootstrap framework</li>
<li>all JS scripts including Bootstrap and JQuery</li>
<li>all user tracking code including Google Analytics</li>
</ul>
<h2 id="what-is-left">What is left?</h2>
<p><em>Content</em>.</p>
<p>That’s it. <em>Just content</em>.</p>
<p>And a tiny bit of inline CSS to limit the page width and wrap long lines to make the whole thing readable.</p>
<p>The endresult: A performant website that works in all browsers (even the funky text-only ones like <a href="http://lynx.invisible-island.net/">Lynx</a>) and focuses on the essential element: the content.</p>
<h2 id="but-what-about-the-analytics">But what about the analytics?</h2>
<p>This is a subject matter for another post but the short bullet version comes down to this:</p>
<ul>
<li>I don’t need to know how many visitors I have</li>
<li>I don’t need to know where they come from or what devices they use</li>
<li>I don’t need to violate their privacy by sending their data to a third party (Google)</li>
<li>If for some unknown reason I really do need to know visitor numbers I can <em>grep/awk</em> the <em>nginx</em> logs for a ballpark figure.</li>
</ul>
<h2 id="the-articles-that-inspired-me">The articles that inspired me</h2>
<ul>
<li><a href="https://brutalist-web.design/">Guidelines for Brutalist Web Design</a></li>
<li><a href="https://mortoray.com/2018/07/09/i-dont-know-how-to-create-a-website/">I don’t know how to create a website</a></li>
<li><a href="https://stallman.org/netflix.html">Reasons not to use Netflix</a></li>
</ul>
<p>If you’re interested in minimalism check out</p>
<ul>
<li><a href="https://www.theminimalists.com/start/">An intro to the minimalist lifestyle</a></li>
</ul>Steven Van Baelsteven@quantus.ioThis week I’ve come across some articles (links at the end) that made me pull the trigger on executing an idea I’ve been thinking about for a very long time: Rework my personal website to be as minimalist as it can be.Read about the software you use2016-03-17T13:45:01+01:002016-03-17T13:45:01+01:00https://stevenvanbael.com/read-about-the-software-you-use<p>Yesterday I was sharing my screen in a Skype call when we were debugging a broken Jenkins build. During the call my colleague noticed that I was opening the console output of a running build by clicking on the build number in the Build Executor Status sidebar, waiting for the page to load and then clicking on the Console Output. He told me that by clicking the circle next to the build number would take me straight to the last position of the Console Output screen.</p>
<p>In the past 5 years I have used Jenkins almost every day of my professional life and I thought I knew it well. I was the go-to Jenkins guy in some of the companies I worked for and here I was learning a trivial new thing that effectively halves the time it takes for me to perform a common task. A task that I have done thousands of times before.</p>
<p>I realised that in the case of Jenkins I have violated my own rule about software:</p>
<blockquote>
<p>my rule of thumb: If you use a (software) tool more than 1 hour a day: read at least one book on it.</p>
</blockquote>
<p>I strongly believe that if you learn a new tool only by using it, you will eventually start using it in wrong or sub-optimal ways. As demonstrated by my Jenkins anecdote above. Because the way I was performing one task worked, I did not stop to think if there was a better, more efficient way to do it.</p>
<p>Simply reading a book or manual on the topic will expose you to more features and alternative ways for doing things. I noticed 3 main benefits from reading more about software:</p>
<h2 id="you-will-become-a-more-efficient-programmer">You will become a more efficient programmer</h2>
<p>In early 2015 after months of pain in my wrist and fingers I started the transition from emacs to Vim as my main editor. For months I was googling for answers every time I wanted to perform an action I had not done before. After 10 months of googling and improving my Vim chops I thought I was doing well… and then I picked up a copy of <a href="http://shop.oreilly.com/product/9780596529833.do">Learning the vi and Vim editors</a> by O’reilly and was proven wrong.</p>
<p>In 5 hours I learned about the origin of the editor, its roots in the ex editor, ex commands, the use of regular expressions in almost every command.</p>
<p>Those 5 hours I spent reading the book have already saved me countless hours of tedious text editing work. Because the book has a few in depth topics about regular expression syntax, not only my Vim skills but also my command line skills improved.</p>
<h2 id="you-will-discover-new-uses-for-software">You will discover new uses for software</h2>
<p>A few years ago when I was learning Emacs I read an old emacs manual from 1997 written by RMS himself. Aside from countless keyboard shortcuts and features that improved my editing efficiency it also thought me the core philosophy of Emacs: a text buffer as the universal interface.</p>
<p>After reading this book it became clear to me that Emacs is not just a text editor but a tool for interacting with software through a text interface. After that I started using emacs for taking notes, IRC chat, email and as an HTTP client.</p>
<h2 id="your-team-will-share-the-benefits">Your team will share the benefits</h2>
<p>When I was learning Git 6 years ago I read Scott Chacon’s book <a href="https://progit.org/">Pro Git</a>. I finished it in a couple of hours, spread out over two evenings and – as with the Vim book – the result was amazing.</p>
<p>After reading this book I had a thorough understanding of how Git worked, why it worked like that and I was able to apply this knowledge to any Git problem I have encountered since then. Almost overnight I went from <em>the guy asking basic git questions to the guy everyone turns to for git questions</em>.</p>
<h2 id="start-learning-about-your-tools">Start learning about your tools</h2>
<p>I want you to take a look at your own programming habits and identify a tool you use at least one hour each day and you don’t know that much about. This could be your text editor, version control software, build tool, CI server, programming language or something else. Then go out and find a learning resource that will teach you everything there is to know about it. This can be a book, a manual, the documentation or even the source code.</p>
<p>I guarantee that the time you invest in reading will pay of huge.</p>Steven Van Baelsteven@quantus.ioYesterday I was sharing my screen in a Skype call when we were debugging a broken Jenkins build. During the call my colleague noticed that I was opening the console output of a running build by clicking on the build number in the Build Executor Status sidebar, waiting for the page to load and then clicking on the Console Output. He told me that by clicking the circle next to the build number would take me straight to the last position of the Console Output screen.