CLI for Morgen calendar and task management — optimised for LLM consumption
Project description
guten-morgen
A CLI for Morgen calendar and task management, designed for both humans and LLM agents.
All commands emit structured JSON, making it easy to pipe into scripts, jq, or feed directly to AI coding assistants like Claude Code.
Features
- Unified task view — see tasks from Morgen, Linear, and Notion in one place
- Calendar groups — filter events by work/personal/family with a single flag
- Time-blocking — schedule tasks as calendar events with
tasks schedule - Tag lifecycle — model task stages (Active, Waiting-On, Someday) with tags
- LLM-friendly output —
--json,--response-format concise,--jq,--fieldsfor token-efficient responses - Smart caching — TTL-based cache with
cache clearandcache stats
Installation
Requires Python 3.10+.
# Run without installing (uv)
uvx guten-morgen --help
# Install globally (uv — recommended)
uv tool install guten-morgen
# Install globally (pipx)
pipx install guten-morgen
# Install into current environment (pip)
pip install guten-morgen
# From source (development)
git clone https://github.com/tenfourty/guten-morgen.git
cd guten-morgen
uv sync --all-extras
uv run pre-commit install
All methods expose both gm (short) and guten-morgen (long) commands.
Setup
-
Get an API key from Morgen Platform (Settings > API Keys)
-
Create config (choose one):
# Interactive setup (recommended) gm init # Or manually: project-local config cp config.toml.example guten-morgen.toml # Edit guten-morgen.toml and add your api_key
Config discovery:
$GM_CONFIG→guten-morgen.toml(walks up from CWD) →~/.config/guten-morgen/config.toml -
Verify it works:
gm accounts gm today --json
Quick Start
# What's coming up?
gm next --json --response-format concise
# Full daily overview
gm today --json
# List overdue tasks across all sources
gm tasks list --status open --overdue --json --group-by-source
# Create and time-block a task
gm tasks create --title "Write design doc" --due 2026-02-20 --duration 90
gm tasks schedule <task-id> --start 2026-02-20T10:00:00
# Filter by tag
gm tasks list --tag "Active" --status open --json
Run gm usage for the full command reference.
Calendar Groups
Groups let you filter events by context. Configure in guten-morgen.toml:
default_group = "work"
active_only = true
[groups.work]
accounts = ["you@company.com:google"]
calendars = ["Work Calendar"]
[groups.personal]
accounts = ["you@personal.com:fastmail"]
calendars = ["Personal"]
Use --group personal to switch context, or --group all to see everything.
Global Options
| Option | Description |
|---|---|
--format table|json|jsonl|csv |
Output format (default: table) |
--json |
Shortcut for --format json |
--fields <list> |
Select specific fields |
--jq <expr> |
jq filtering on output |
--response-format concise |
~1/3 the tokens (great for LLMs) |
--short-ids |
Truncate IDs to 12 chars |
--group NAME |
Filter by calendar group |
--no-cache |
Bypass cache |
Development
# Install dev dependencies
uv sync --all-extras
uv run pre-commit install
# Run tests
uv run pytest -x -q --cov
# Type checking
uv run mypy src/
# Lint
uv run ruff check .
Pre-commit hooks enforce ruff, mypy, bandit, pytest (90% coverage minimum), and ggshield secret scanning. To use ggshield, create a free account and set GITGUARDIAN_API_KEY.
Architecture
src/guten_morgen/
cli.py Click commands — boundary layer (model -> dict)
client.py MorgenClient — typed API wrapper (Pydantic models)
models.py Pydantic v2 models
output.py Render pipeline (table/json/jsonl/csv + fields + jq)
errors.py Exception hierarchy -> structured JSON on stderr
config.py XDG config discovery + API settings
time_utils.py Date range helpers
cache.py TTL-based request cache
groups.py Calendar group filtering from guten-morgen.toml
retry.py Rate-limit retry with dual-mode countdown
The boundary rule: client.py returns Pydantic models, cli.py converts with model_dump(), output.py only sees dicts.
Claude Code Integration
This project includes a CLAUDE.md with conventions and a .claude/ directory with hooks and skills for use with Claude Code. These are optional — the CLI works without them.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file guten_morgen-0.6.1.tar.gz.
File metadata
- Download URL: guten_morgen-0.6.1.tar.gz
- Upload date:
- Size: 183.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a509ae16ca894eb2e31e847cf701675dfc40fab9c15e40ecc4c354ac02c93e29
|
|
| MD5 |
2853095884c8af68db8297679dd1891d
|
|
| BLAKE2b-256 |
9ed411b5b920655536e592abfce476569e33b7a280c38a9f301d8f822c6769de
|
Provenance
The following attestation bundles were made for guten_morgen-0.6.1.tar.gz:
Publisher:
release.yml on tenfourty/guten-morgen
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guten_morgen-0.6.1.tar.gz -
Subject digest:
a509ae16ca894eb2e31e847cf701675dfc40fab9c15e40ecc4c354ac02c93e29 - Sigstore transparency entry: 982764424
- Sigstore integration time:
-
Permalink:
tenfourty/guten-morgen@1001751b5f36e045465a44d0c16c47069b80605c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/tenfourty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1001751b5f36e045465a44d0c16c47069b80605c -
Trigger Event:
push
-
Statement type:
File details
Details for the file guten_morgen-0.6.1-py3-none-any.whl.
File metadata
- Download URL: guten_morgen-0.6.1-py3-none-any.whl
- Upload date:
- Size: 39.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db5389b186abac342ad6ed2b2e0092bff4543707a61445baba87dade131b1a39
|
|
| MD5 |
44f032f14b6e326968a7c8df22a5c37c
|
|
| BLAKE2b-256 |
7dddd8985ab38b019eabea1db207cf1ee60c9317b383845733c6afc0c5b71d15
|
Provenance
The following attestation bundles were made for guten_morgen-0.6.1-py3-none-any.whl:
Publisher:
release.yml on tenfourty/guten-morgen
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guten_morgen-0.6.1-py3-none-any.whl -
Subject digest:
db5389b186abac342ad6ed2b2e0092bff4543707a61445baba87dade131b1a39 - Sigstore transparency entry: 982764429
- Sigstore integration time:
-
Permalink:
tenfourty/guten-morgen@1001751b5f36e045465a44d0c16c47069b80605c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/tenfourty
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1001751b5f36e045465a44d0c16c47069b80605c -
Trigger Event:
push
-
Statement type: