PersonalD is a local Linux daemon for planning, focus, reminders, browser activity, and lightweight time awareness.
It was built for a busy work-and-study workflow: keep the schedule close, show what is next, send timely reminders, watch for focus drift, and stay useful without locking the user out of their own machine.
- YAML-based weekly schedule, one-off events, deadlines, and study targets
- Desktop notifications with optional attention sound
- Gentle focus sessions with drift reminders
- Hyprland active-window activity tracking
- Local browser bridge for active tab context
- Daily plan generation and editing
- Local calendar import from
.icsfiles - Daily and weekly activity reports
- JSON status output for bars, widgets, and shells
- Optional Quickshell integration
PersonalD is not a strict blocker. It does not force pages open, lock apps, or prevent you from closing anything. It is designed to nudge, remind, and reflect your day back to you.
PersonalD is early, usable, and evolving. The core CLI, daemon, schedule reminders, focus sessions, browser bridge, reports, and local storage are working, but the project is still pre-1.0.
Contributors are welcome. Good starting points are documentation, tests, config validation, desktop compatibility, browser bridge improvements, and small CLI quality-of-life fixes.
- Linux
- Python 3.11+
notify-sendfor desktop notificationshyprctlfor Hyprland activity tracking and environment actionspaplay,pw-play,aplay,ffplay,mpv, orcanberra-gtk-playfor notification sounds
Hyprland is recommended for the activity and environment features. Schedule, reminders, planning, browser bridge, calendar import, and reports can still work without Quickshell.
Clone the repo:
git clone https://github.com/DT-GAMER/PersonalD.git
cd PersonalDInstall the command locally with pipx:
pipx install -e .On Arch-based systems, install pipx first if needed:
sudo pacman -S python-pipx
pipx ensurepathMake sure ~/.local/bin is in your PATH, then check:
personalctl --helpFor development without installing:
./personalctl --helpYou can also use a virtual environment:
python -m venv .venv
source .venv/bin/activate
python -m pip install -e .PersonalD reads its main schedule from:
~/.config/personald/schedule.yaml
Start from the example:
mkdir -p ~/.config/personald
cp config-examples/schedule.yaml ~/.config/personald/schedule.yaml
cp config-examples/rules.yaml ~/.config/personald/rules.yamlEdit the schedule:
$EDITOR ~/.config/personald/schedule.yamlPreview your day:
personalctl today
personalctl status
personalctl next
personalctl remindersYou can keep broad blocks broad and place specific activities inside them.
For example:
weekly_template:
monday:
- time: "09:00-15:00"
type: work
title: Software Engineering Work
- time: "13:00-14:00"
type: meeting
title: Team meetingAt 13:30, PersonalD treats Team meeting as the active block because meeting has a higher default priority than work.
Default priority is designed so specific blocks usually win over broad blocks:
schedule:
type_priority:
meeting: 90
class: 80
event: 70
weekly_review: 60
planning: 50
study: 40
work: 10You can override the priority for one block:
- time: "13:00-14:00"
type: meeting
title: Critical meeting
priority: 100Check once without sending real desktop notifications:
personalctl daemon --once --dry-runRun it manually:
personalctl daemonInstall the user service:
mkdir -p ~/.config/systemd/user
cp systemd/personald.service ~/.config/systemd/user/personald.service
systemctl --user daemon-reload
systemctl --user enable --now personald.serviceView logs:
journalctl --user -u personald.service -fRestart after config changes:
systemctl --user restart personald.serviceNotification sound is configured inside notifications.sound:
notifications:
enabled: true
poll_seconds: 60
sound:
enabled: true
file: /usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga
repeat: 2Set enabled: false to disable sound, or change file to a custom .oga, .ogg, or .wav.
personalctl status
personalctl today
personalctl next
personalctl schedule
personalctl reminders
personalctl activity now
personalctl activity track --once
personalctl activity summary
personalctl focus list
personalctl focus start mba_study --minutes 50
personalctl focus pause
personalctl focus resume
personalctl focus stop
personalctl focus status
personalctl plan today
personalctl plan accept
personalctl plan add "Read chapter 4" --at 20:00 --minutes 45 --type study
personalctl plan done s1
personalctl plan skip current
personalctl plan move current --to 21:00
personalctl browser latest
personalctl calendar import ~/Downloads/school.ics --name school
personalctl calendar sync
personalctl calendar upcoming
personalctl env list
personalctl env start mba_study --dry-run
personalctl report today
personalctl report week
personalctl ui status
personalctl ui write-statusPersonalD listens locally on:
http://127.0.0.1:47833
The extension in browser-extension/ sends active tab URL and title events to the daemon.
For Zen/Firefox:
- Open
about:debugging#/runtime/this-firefox - Click
Load Temporary Add-on - Select
browser-extension/manifest.json - Keep
personalctl daemonrunning
For Chromium/Chrome:
- Open
chrome://extensions - Enable Developer Mode
- Click
Load unpacked - Select
browser-extension/
PersonalD can import a local .ics file manually:
personalctl calendar import ~/Downloads/school.ics --name schoolIt can also sync configured .ics feeds:
calendar:
sync:
enabled: true
every_minutes: 10
sources:
- name: google
url: "https://calendar.google.com/calendar/ical/YOUR_CALENDAR/basic.ics"Run a sync manually:
personalctl calendar sync
personalctl calendar upcomingWhen the daemon is running, it syncs enabled calendar sources in the background. Imported calendar events appear in personalctl today, personalctl next, reminders, reports, and status output.
For Google Calendar, the private Secret address in iCal format is usually more useful than a public calendar URL because it can include private meeting invitations. Do not commit or share the secret URL.
PersonalD does not require Quickshell.
For shells, bars, or widgets, PersonalD writes status JSON to:
~/.local/state/personald/status.json
Generate it manually:
personalctl ui write-statusThe daemon also refreshes this file while running. A Quickshell rice can read the JSON and display the current block, next block, focus state, and activity context.
PersonalD stores data locally by default:
~/.config/personald/
~/.local/state/personald/
The browser bridge posts to 127.0.0.1 only. It does not send activity to a remote server.
Do not commit your real ~/.config/personald/schedule.yaml if it contains private class, work, or meeting details. Use config-examples/schedule.yaml as the public template.
PersonalD welcomes thoughtful contributions.
Start here:
Good first contributions include:
- Fixing unclear docs
- Adding tests for edge cases
- Improving config examples
- Improving error messages
- Adding platform notes for different Linux distributions
- Helping make optional integrations cleaner
python -m unittest discover tests