Automating my work diary with AI
As someone who is always looking for the next challenge, I don’t usually bother keeping track of completed tasks. Still, it’s very useful to be able to look back and see what I have achieved in the past.
Because of this, it was always hard for me to remember what I did in the previous quarter when preparing my performance review. I started wondering how I could automate this task and took the opportunity to experiment with AI tools.
My first idea was to focus on a specific solution, get some daily stats (commits, PRs, comments, etc.) from GitHub, as for a developer it is something very representative of the work done in a day.
The next step was to use an AI model to generate a summary of the day based on these stats, so I can have a concise and clear description of what I did in a human-readable format.
And the last step was to store these summaries in a structured way, I decided to use https://obsidian.md/ as it is a great tool for note taking and knowledge management, and it allows me to easily organize and search my work diary.
This this simple idea in mind, I write a definition document with the requirements and the steps to follow, and used GitHub Copilot to create a plan, and execute it.
The result, in 2-3 iterations with the agent, was a simple CLI tool that runs daily, fetches the GitHub stats, generates the summary using an AI model, and stores the summary in a repo which contains my Obsidian vault.
I could validate the results and they were amazing, as example this real output for a day:
# Work Diary - 2026-01-15
## Summary
Today I primarily focused on improving the developer experience around dialog management within the `factorialco/f0` repository. I created a new `useDialog` hook designed to simplify the process of opening and managing dialogs, reducing the amount of boilerplate code required.
Pull request #3242 introduces this new hook, showcasing a more streamlined approach compared to the previous method. The goal is to provide a smoother and more intuitive way for developers to integrate dialogs into the application. This work aims to improve code maintainability and reduce the potential for errors related to dialog state management.
Going further
I understood the potential of these tools, so I rethought the architecture to make it more flexible and extensible. I found that:
- not only GitHub stats are useful; other sources like Slack, email, and Jira can also be valuable
- the output format doesn’t always need to be Markdown
- sometimes I might want to send the summary to different places like email or Slack instead of (or in addition to) a file
With this in mind I redesigned the architecture around a plugin‑based system that follows a 3 + 1 step process:
-
Input (plugins): collect data from different sources (GitHub, Slack, email, Jira, etc.) and provide a prompt to the AI model to summarize that data.
-
AI summarizer (core): takes the data from the input plugins and generates a summary using an AI model.
-
Formatter (plugin): combines all the plugin summaries and formats them into different representations (Markdown, HTML, plain text, etc.).
-
Output (plugins): take the formatter output and store, print, or send the summary to different destinations.
This way I can easily add new input sources, change the AI model, add new formatters or output destinations without changing the core logic of the application.
Example workflow
A workflow similar to the one in the first iteration looks like this:
ai:
provider: google
model: gemini-2.5-flash
apiKey: env:GOOGLE_API_KEY
inputs:
- plugin: github
config:
token: env:GH_READ_TOKEN
username: env:GH_USERNAME
- plugin: email
config:
provider: gmail
host: imap.gmail.com
port: 993
secure: true
user: env:IMAP_USER
password: env:IMAP_PASSWORD
mailbox: "[Gmail]/Todos" # pulls everything
sentMailbox: "[Gmail]/Enviados" # typical Gmail sent folder
maxMessages: 200
formatter:
plugin: markdown
outputs:
- plugin: console
- plugin: file
config:
path: '~/workdiary-{date}.md'
mode: merge # Don't be worried if the file exists, just append the new summary or update the previous one as it wraps the content with markers
Note the use of
env:to get the API keys and other sensitive data from environment variables, so they are not stored in plain text in the workflow file. When the tool runs, it replaces these placeholders with the actual values from the environment.
Then run the tool to generate the work diary:
$ work-diary --workflow ./workflow.yaml
Show me the code!
I thought this tool could be useful for other people, so I released it as open source: https://github.com/sergiocarracedo/work-diary. If you want to run it on your machine you can follow the instructions in SETUP.md.
The project is still in early stages, but if you want to contribute with new plugins, features, etc. you are welcome!
Running it as a scheduled task
To be truly valuable, this tool needs to run every day. There are many ways to achieve that, but I decided to use GitHub Actions because it is easy to set up and maintain. The repository includes a reusable GitHub Action (sergiocarracedo/work-diary@v1.1.0) that you can use in your own repo to run the tool daily.
This is the workflow I use in my repo to run the tool at the end of each day and commit the changes to the Obsidian repo:
# .github/workflows/work-diary.yml
name: Work Diary
on:
schedule:
- cron: "30 23 * * *"
workflow_dispatch:
inputs:
date:
description: "Target date (YYYY-MM-DD, UTC). Defaults to today."
required: false
type: string
jobs:
diary:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run Work Diary
uses: sergiocarracedo/work-diary@v1.1.0
env:
AI_PROVIDER: 'google'
AI_MODEL: 'gemini-2.5-flash'
AI_APIKEY: ${{ secrets.GEMINI_API_KEY }}
GH_READ_TOKEN: ${{ secrets.GH_READ_TOKEN }}
GH_USERNAME: ${{ secrets.GH_USERNAME }}
with:
config: |
ai:
provider: env:AI_PROVIDER
model: env:AI_MODEL
apiKey: env:AI_APIKEY
inputs:
- plugin: github
config:
token: env:GH_READ_TOKEN
username: env:GH_USERNAME
formatter:
plugin: markdown
outputs:
- plugin: console
- plugin: file
config:
path: "Daily Notes/{date}.md"
mode: merge
- name: Commit and push diary changes
env:
GIT_AUTHOR_NAME: github-actions[bot]
GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
GIT_COMMITTER_NAME: github-actions[bot]
GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
run: |
git status --porcelain
if git status --porcelain | grep .; then
git config user.name "$GIT_AUTHOR_NAME"
git config user.email "$GIT_AUTHOR_EMAIL"
git add .
git commit -m "chore: update work diary"
git push
else
echo "No changes to commit."
fi
This workflow runs every day at 23
UTC, and you can adjust the cron expression to fit your needs. It checks out the repository, runs the work-diary tool with the specified configuration, and then commits and pushes any changes to the repository.Conclusion
Automating my work diary with AI has been a great experience. It has saved me time and effort and allowed me to focus on more important tasks. It also gives me a better overview of my work, and I’m pretty sure it will help me a lot in the future when I need to prepare my performance reviews. 😉😉
If you are interested in other input sources, formatters or output plugins, feel free to open an issue or a PR in the work-diary. Providing feedback and suggestions is always welcome!
Disclaimer
No AI models were harmed during the making of this tool, well I stressed them a little bit 😂
Sergio Carracedo