{"id":15062978,"url":"https://github.com/bartste/khalorg","last_synced_at":"2025-10-15T20:06:22.046Z","repository":{"id":65857558,"uuid":"586211158","full_name":"BartSte/khalorg","owner":"BartSte","description":"An interface between org mode and khal cli calendar","archived":false,"fork":false,"pushed_at":"2025-02-19T08:50:14.000Z","size":5954,"stargazers_count":34,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-10-05T11:03:02.361Z","etag":null,"topics":["davmail","emacs","ical","icalendar","khal","neovim","nvim-orgmode","org-mode","orgparse","outlook","python3","vdirsyncer"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/khalorg/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BartSte.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-07T10:38:16.000Z","updated_at":"2025-09-02T07:25:38.000Z","dependencies_parsed_at":"2023-05-19T22:30:22.249Z","dependency_job_id":"2ca56b18-c22e-4086-b46f-c0767dd88955","html_url":"https://github.com/BartSte/khalorg","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/BartSte/khalorg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BartSte%2Fkhalorg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BartSte%2Fkhalorg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BartSte%2Fkhalorg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BartSte%2Fkhalorg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BartSte","download_url":"https://codeload.github.com/BartSte/khalorg/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BartSte%2Fkhalorg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279110574,"owners_count":26105906,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-15T02:00:07.814Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["davmail","emacs","ical","icalendar","khal","neovim","nvim-orgmode","org-mode","orgparse","outlook","python3","vdirsyncer"],"created_at":"2024-09-24T23:49:34.872Z","updated_at":"2025-10-15T20:06:22.017Z","avatar_url":"https://github.com/BartSte.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Khalorg\n\n[Click here for the GitHub page.](https://github.com/BartSte/khalorg)\n\n\u003cimg src=\"./demo/logo.jpg\" width=50%\u003e\n\n## Demo\n\nThe demo below demonstrates the following features using the neovim plugin\ncalled [nvim-khalorg](https://github.com/BartSte/nvim-khalorg):\n\n- `khalorg new`: convert an org agenda item into a `khal` agenda item.\n- `khalorg list`: convert a `khal` agenda item into an org agenda item.\n- `khalorg edit`: edit an existing `khal` agenda item with org mode.\n- `khalorg delete`: delete an existing `khal` item.\n\n![neovim-plugin](https://github.com/BartSte/khalorg/blob/main/demo/neovim-plugin.gif?raw=true)\n\n## Contents\n\n\u003c!--toc:start--\u003e\n\n- [Demo](#demo)\n- [Contents](#contents)\n- [Introduction](#introduction)\n  - [Definitions](#definitions)\n  - [Motivation](#motivation)\n  - [Features](#features)\n- [Installation](#installation)\n  - [PyPi](#pypi)\n  - [From source](#from-source)\n  - [For development](#for-development)\n- [Usage](#usage)\n  - [List: from khal to org](#list-from-khal-to-org)\n    - [–format](#format)\n    - [Recurring items](#recurring-items)\n  - [New: from org to khal](#new-from-org-to-khal)\n    - [Recurring items](#recurring-items)\n    - [Attendees](#attendees)\n  - [Edit: from org to khal](#edit-from-org-to-khal)\n  - [Delete: from org to khal](#delete-from-org-to-khal)\n    - [Recurring items](#recurring-items)\n- [Neovim plugin](#neovim-plugin)\n- [Workflow for Office 365](#workflow-for-office-365)\n- [Troubleshooting](#troubleshooting)\n- [Contributing](#contributing)\n- [License](#license)\n- [Improvements:](#improvements)\n\n\u003c!--toc:end--\u003e\n\n## Introduction\n\n`khalorg` is an interface between Org mode and Khal cli calendar.\n\n### Definitions\n\n- [CalDav](https://en.wikipedia.org/wiki/CalDAV): internet standard for client access to calendars\n- [Davmail](https://davmail.sourceforge.net/e): CalDav exchange gateway\n- [khal](https://github.com/pimutils/khal): command line calendar app\n- [khalel](https://gitlab.com/hperrey/khalel): interface between emacs and khal\n- [nvim-orgmode](https://github.com/nvim-orgmode/orgmode): org mode for neovim\n- [org](https://orgmode.org): plain text system for keeping notes, agendas and more\n- [vdirsyncer](https://github.com/pimutils/vdirsyncer): synchronizes calendars and addressbooks between servers and the local file system\n\n### Motivation\n\nI use org mode to manage my agenda and my notes. However, in a professional\nsetting, you are often required to use proprietary software for your agenda,\nlike Office 365. Luckily, programs exist that can synchronize agendas from\ndifferent sources, by implementing the CalDav standard. Personally, I like to\nuse `vdirsyncer` with `khal` to synchronize my agendas. To bridge the gap\nbetween `khal` and `org mode`, only 1 program exists called: `khalel`. However,\nthis program is designed for `emacs`. Since there are also org mode users\noutside of `emacs` (e.g. `neovim`), `khalorg` aims to be a general interface\nbetween `vdirsyncer`/`khal` and `org mode`.\n\nBased on the above, the following workflow is desired:\n\n```example\n┌──────┐\n│CalDav│\n└┬─────┘\n┌▽─────────┐\n│vdirsyncer│\n└┬─────────┘\n┌▽───┐\n│khal│\n└┬───┘\n┌▽───────┐\n│khalorg │\n└┬───────┘\n┌▽───────┐\n│org mode│\n└────────┘\n```\n\n### Features\n\n- [x] Can be used by org mode for emacs, vim and neovim.\n- [x] Vdirsyncer calendars can be manipulated by using the cli of `khal`\n      as the interface.\n- [x] `khalorg new`: convert an org agenda item into a `khal` agenda\n      item.\n- [x] `khalorg list`: convert a `khal` agenda item into an org agenda\n      item.\n- [x] `khalorg edit`: edit an existing `khal` agenda item with org mode.\n- [x] `khalorg delete`: delete an existing `khal` item.\n- [x] Recurring items are supported by providing an org repeater in the\n      time stamp (e.g., `+1w`). The following is supported:\n  - the follow org repeaters: `+{integer}{d,w,m,y}`\n  - `khalorg new` and `khalorg edit --edit-dates` support 1 time stamp\n    per org agenda item.\n  - `khalorg list` concatenates timestamps that cannot be describes by\n    an org repeater, resulting in an org agenda item with multiple\n    timestamps.\n  - Supports an `until` date for recurring items. The until date can be\n    supplied through an org property `UNTIL`.\n- [x] Has unittests\n- [x] Includes an Office 365 workflow with a bash script\n- [x] Semantic versioning\n- [x] Gifs with demos\n- [x] Neovim plugin\n- [x] Is available on PyPI\n\n## Installation\n\nFor safety, always make a back-up of your calendar before installing software\nthat is new to you.\n\nMake sure your `khal` date format is compatible with org, otherwise it\nwill not work. When running `khal printformats` you should get:\n\n```example\nlongdatetimeformat: 2013-12-21 Sat 21:45\ndatetimeformat: 2013-12-21 Sat 21:45\nlongdateformat: 2013-12-21 Sat\ndateformat: 2013-12-21 Sat\ntimeformat: 21:45\n```\n\nIf not, check the documentation of `khal` on how to change this.\n\n### PyPi\n\nInstall by running the following command:\n\n```bash\npip install khalorg\n```\n\n### From source\n\nSet your current working directory to the root directory, i.e, the\ndirectory containing the `pyproject.toml` file. Next, run:\n\n```bash\npip install .\n```\n\nAfter this, the executable `khalorg` will be available.\n\n### For development\n\nIf you want to develop the code, debug it, and test it, run:\n\n```bash\npip install -e '.[test,debug]'\n```\n\n## Usage\n\nUse `khalorg --help` to get information about the cli of `khalorg`. The\nfollowing section discuss the `khalorg` commands that are available.\n\n### List: from khal to org\n\n![khalorg list demo](https://github.com/BartSte/khalorg/blob/main/demo/list.gif?raw=true)\n\nAgenda items from `khal` can be converted to org items using the\n`khalorg list` command. For examples:\n\n```bash\nkhalorg list my_calendar today 90d \u003e my_calendar.org\n```\n\nHere, the `khal` agenda items of the calendar `my_calendar` are\nconverted to org format and written to a file called `my_calendar.org`.\nThe range is specified from `today` till `90d` (90 days) in the future.\nFor more information about the allowed date formats, check the\n`khal list` command, which is used for this functionality. It is assumed\nthat the `khal` calendar called `my_calendar` exists. Make sure\n`my_calendar` is a calendar that exists on your local file system.\n\n#### –format\n\nIf `khalorg list --format` option is not defined, the default one is\nused which can be found at `./khalorg/static/khalorg_format.txt`. If you\nwant to define your own format, you have 2 options: you can use the\n`khalorg list --format` option, or you can place your custom format at\n`$HOME/.config/khalorg/khalorg_format.txt` this format will then be used\ninstead of the default one that is shown below.\n\n```org\n* {title}\n  {timestamps}\n  :PROPERTIES:\n  :ATTENDEES: {attendees}\n  :CALENDAR: {calendar}\n  :CATEGORIES: {categories}\n  :LOCATION: {location}\n  :ORGANIZER: {organizer}\n  :STATUS: {status}\n  :UID: {uid}\n  :URL: {url}\n  :END:\n  {description}\n```\n\nthe following keys are supported:\n\n- `{attendees}`: a comma separated list of email addresses of attendees\n- `{calendar}`: the name of the khal calendar\n- `{categories}`: the categories property of the item\n- `{description}`: the description of the item\n- `{location}`: the location of the item\n- `{organizer}`: the email of the organizer\n- `{status}`: the status of the item, e.g., TENTATIVE or ACCEPTED\n- `{timestamps}`: the timestamp of the item\n- `{title}`: the summary of the item\n- `{uid}`: the UID of the item\n- `{rrule_until}`: the until value of the RRULE.\n- `{url}`: the url property\n\nthe following keys are supported but are typically reserved for internal use\nand are therefore less informative:\n\n- `{until}`: the until property value. Is empty when using `khalorg list`.\n- `{rrule}`: the ICal RRULE of the item.\n\n#### Recurring items\n\nThe `khalorg list` command relies on the `khal list` command. Using this\ncommand the `RRULE` of each item is retrieved to created the correct org\nrepeater. Only simple org repeaters are supported that have the\nfollowing form: `+[number][h,w,m,y]`. Complex `RRULEs` are described by\nconcatenating the corresponding timestamps within 1 agenda item,\nresulting in a list of items. For example, the agenda item below\nrepresents a weekly recurring event where the first meeting was moved to\nanother date, resulting in a timestamp without a repeater, and one with\na repeater.\n\n```org\n* Meeting\n  \u003c2023-01-05 Thu 01:00-02:00\u003e\n  \u003c2023-01-08 Sun 01:00-02:00 +1w\u003e\n  :PROPERTIES:\n  :UID: 123\n  :LOCATION: Somewhere\n  :ORGANIZER: Someone (someone@outlook.com)\n  :ATTENDEES: test@test.com, test2@test.com\n  :URL: www.test.com\n  :END:\n  Hello,\n\n  Lets have a meeting.\n\n  Regards,\n\n\n  Someone\n```\n\n### New: from org to khal\n\n![khalorg new demo](https://github.com/BartSte/khalorg/blob/main/demo/new.gif?raw=true)\n\nAn org agenda item can be converted to a new `khal` agenda item by\nfeeding the org item through stdin to `khalorg new` and specifying the\nkhal calendar name as a positional argument. For example, the consider\nthe org item below, which is saved as `meeting.org`.\n\n```org\n* Meeting\n  \u003c2023-01-01 Sun 01:00-02:00 +1w\u003e\n  :PROPERTIES:\n  :UID: 123\n  :LOCATION: Somewhere\n  :ORGANIZER: Someone (someone@outlook.com)\n  :ATTENDEES: test@test.com, test2@test.com\n  :URL: www.test.com\n  :END:\n  Hello,\n\n  Lets have a meeting.\n\n  Regards,\n\n\n  Someone\n```\n\nThis item can be converted to the `khal` calendar called\n\"my\u003csub\u003ecalendar\u003c/sub\u003e\" as follows:\n\n```bash\ncat meeting.org | khalorg new my_calendar\n```\n\nIt is assumed that the `khal` calendar called \"my\u003csub\u003ecalendar\u003c/sub\u003e\"\nexists. Make sure \"my\u003csub\u003ecalendar\u003c/sub\u003e\" is a calendar that exists on\nyour local file system.\n\n#### Recurring items\n\nOnly 1 timestamp per org item is supported. Note that the meeting above\nis repeated every week (`+1w`). Only simple org repeaters are supported\nthat have the following form: `+[number][h,w,m,y]`. These events repeat\nforever, unless you specify an end date using the \\`UNTIL\\` property in\nthe org file.\n\nPersonally, when I need to create a complex repeat pattern (or when I\nneed outlook specific items like a Teams invite), I create the event in\noutlook first. Next, I use `khalorg edit` to change the fields that need\nediting (e.g., the description).\n\n#### Attendees\n\nOptionally, attendees can be added to the `ATTENDEES` property field.\nThe attendees will be added to the `Attendees` field of `khal`. Once you\nsynchronize `khal` with a server (e.g., outlook) an invitation will be\nsend to the attendees.\n\n### Edit: from org to khal\n\n![khalorg edit demo](https://github.com/BartSte/khalorg/blob/main/demo/edit.gif?raw=true)\n\nExisting `khal` events can be updates by feeding an org file with the\ncorresponding UID through stdin to the `khalorg edit` command. For\nexample, the org agenda item of \u003cspan class=\"spurious-link\"\ntarget=\"New\"\u003e_New_\u003c/span\u003e can be altered and used as an input for\n`khalorg edit`, as long as the UID remains untouched.\n\n```org\n* Edited meeting\n  \u003c2023-01-01 Sun 01:00-02:00 +1w\u003e\n  :PROPERTIES:\n  :UID: 123\n  :ORGANIZER: Someone (someone@outlook.com)\n  :ATTENDEES: other@test.com\n  :END:\n  Hello,\n\n  I edited the meeting by removing the location and url. I also changed the\n  title and the attendees field.\n\n  Regards,\n\n\n  Someone\n```\n\nNext, run the following command:\n\n```bash\ncat meeting.org | khalorg edit my_calendar\n```\n\nWhen using `khalorg edit` please consider the following:\n\n- Editing an existing event is different from creating a new one as the\n  original `icalendar` file is retained. Only parts of it are altered.\n  This is convienent when the icalendar file contains information that\n  cannot be generated by `khalorg`. For example, a Microsoft Team\n  meeting.\n- Only the PROTO event is edited, i.e., the whole series is altered not\n  only the occurence.\n- `khal edit` will only update the dates + recurrence if the\n  `--edit-dates` flag is passed. This avoids editing the start-stop date\n  when editing an event that contains multiple timestamps (which are not\n  supported).\n\n### Delete: from org to khal\n\n![khalorg deleted demo](https://github.com/BartSte/khalorg/blob/main/demo/delete.gif?raw=true)\n\nAn event can be deleted from a khal calendar by feeding an org file to the\n`khalorg delete` command through stdin. The org file must contain an agenda\nitem with a non-empty UID property. For example, the khal event that was\ncreated using the \u003cspan class=\"spurious-link\" target=\"New\"\u003e_New_\u003c/span\u003e command\nabove can be removed by feeding the same file to `khalorg delete`:\n\n```bash\ncat meeting.org | khalorg delete my_calendar\n```\n\n#### Recurring items\n\nWhen deleting recurring items the whole series will be removed. Removing\noccurrences is not supported.\n\n## Neovim plugin\n\nThe neovim plugin can be found here:\n[nvim-khalorg](https://github.com/BartSte/nvim-khalorg). Check out the demo at\nthe top of the [page](#demo).\n\n## Workflow for Office 365\n\nThe diagram below illustrates the workflow than can be achieved when using\n`khalorg`. The folder `extras`, on the\n[GitHub](https://github.com/BartSte/khalorg) page, contains a `bash` script\ncalled `calsync`, that synchronizes `vdirsyncer` calendars and exports them as\nan org file using the `khalorg list` command. Davmail is used as the CalDav\nserver in this specific example.\n\n```example\n┌──────────┐\n│Office 365│\n└┬─────────┘\n┌▽──────┐\n│Davmail│\n└┬──────┘\n┌▽─────────┐\n│vdirsyncer│\n└┬─────────┘\n┌▽───┐\n│khal│\n└┬───┘\n┌▽───────┐\n│khalorg │\n└┬───────┘\n┌▽───────┐\n│org mode│\n└────────┘\n```\n\n## Troubleshooting\n\nIf you encounter any issues, please report them on the issue tracker at:\n[khalorg issues](https://github.com/BartSte/khalorg/issues)\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING](./CONTRIBUTING.md) for\nmore information.\n\n## License\n\nDistributed under the [MIT License](./LICENCE).\n\n## Improvements:\n\n- [ ] Timezones are not yet supported, so `khalorg` will only work when\n      you agenda remain in the timezone that you specified within your\n      `khal` config.\n- [ ] Running khal commands directly from a script in not\n      straightforward. Therefore, khal is executed as a subprocess, by using\n      its command line interface.\n- [ ] `khalorg new` and `khal edit` only support 1 timestamp per item.\n      However, it is desired that all timestamps within 1 org agenda item,\n      end up in 1 khal event, as is the case for the `orgagenda`. To achieve\n      this the following could be build:\n  - [ ] When multiple timestamps without an org repeater are provided,\n        find the `RRULE` that describes them. Also, set the `UNTIL` date to\n        the last date. If no `RRULE` can be found, raise an error. Another\n        option could be to use the `RDATE` option of ICal.\n  - [ ] When multiple timestamps with an org repeater are presented, try\n        to find the `RRULE` that describes them.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbartste%2Fkhalorg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbartste%2Fkhalorg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbartste%2Fkhalorg/lists"}