{"id":48088070,"url":"https://github.com/tnoff/enheduanna","last_synced_at":"2026-04-04T15:25:47.402Z","repository":{"id":275530762,"uuid":"926357209","full_name":"tnoff/enheduanna","owner":"tnoff","description":"Enheduanna Note App","archived":false,"fork":false,"pushed_at":"2026-03-30T03:50:28.000Z","size":214,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-30T05:59:56.589Z","etag":null,"topics":["documentation","notes","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tnoff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.rst","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-02-03T05:16:51.000Z","updated_at":"2026-03-30T03:50:30.000Z","dependencies_parsed_at":"2025-03-10T20:29:56.306Z","dependency_job_id":"0df62faf-b565-463e-aef1-bbef17894877","html_url":"https://github.com/tnoff/enheduanna","commit_stats":null,"previous_names":["tnoff/enheduanna"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/tnoff/enheduanna","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tnoff%2Fenheduanna","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tnoff%2Fenheduanna/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tnoff%2Fenheduanna/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tnoff%2Fenheduanna/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tnoff","download_url":"https://codeload.github.com/tnoff/enheduanna/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tnoff%2Fenheduanna/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31403958,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["documentation","notes","python"],"created_at":"2026-04-04T15:25:44.378Z","updated_at":"2026-04-04T15:25:47.391Z","avatar_url":"https://github.com/tnoff.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Enheduanna\n\nCommand line tool for creating entries in Markdown. Organizes entries into sub-folders, and has functions to \"collate\" multiple entries into summaries and create additional \"documentation\" files from these notes.\n\nUseful for keeping track of work done throughout the week, tracking follow up items, and starting proper documentation from your notes. In particular helps with keeping track of your work throughout the year/quarter for when you do self-reviews or need to update your resume.\n\nNamed after [Enheduanna](https://en.wikipedia.org/wiki/Enheduanna), sometimes considered the first known author in history.\n\n## Install\n\nInstall via pip\n\n```\n$ git clone https://github.com/tnoff/enheduanna.git\n$ pip install enheduanna/\n```\n\n## Docker Usage\n\nIf you have trouble setting up Python environments, you can use Docker:\n\n### Build the Docker image\n\n```bash\n$ git clone https://github.com/tnoff/enheduanna.git\n$ cd enheduanna\n$ docker build -t enheduanna .\n```\n\n### Run commands with Docker\n\nThe Docker container comes with a default configuration that uses `/notes` and `/documents` as the base folders. Mount your local folders to these paths:\n\n```bash\n# Run new-entry command (creates today's note)\n$ docker run --rm \\\n  -v ~/Notes:/notes \\\n  enheduanna new-entry\n\n# Run collate command on a specific week\n$ docker run --rm \\\n  -v ~/Notes:/notes \\\n  -v ~/Documents:/documents \\\n  enheduanna collate /notes/2025-01-20_2025-01-26\n\n# Run merge command\n$ docker run --rm \\\n  -v ~/Documents:/documents \\\n  enheduanna merge /documents /documents/combined-runbook.md\n```\n\n### Using a custom config file\n\nIf you need custom settings, mount your config file and specify it:\n\n```bash\n$ docker run --rm \\\n  -v ~/Notes:/notes \\\n  -v ~/.enheduanna.yml:/config/.enheduanna.yml \\\n  enheduanna -c /config/.enheduanna.yml new-entry\n```\n\n**Note**: When using a custom config with Docker, paths should reference the container's mounted paths (e.g., `/notes` instead of `~/Notes`).\n\n## Basic Usage\n\nComes with three commands to start:\n\n- `enheduanna new-entry` Creates the entry file for today\n- `enheduanna collate` Collates entries into summaries and other documentation\n- `enheduanna merge` Merges multiple markdown files into a single file\n\nRun `enheduanna --help` to see all options.\n\n## Entry Files\n\nThe `new-entry` command will create a markdown entry file for today. The entry file will be named for the current day, such as `2025-01-21.md`. By default, the file will be placed in a sub-folder for the current week, but this can be configured to be a sub-folder for the entire month. \n\nThe format will look like this:\n\n```\nNotes/\n  2025-01-20_2025-01_26/\n    2025-01-20.md\n    2025-01-21.md\n    2025-01-22.md\n    2025-01-23.md\n```\n\nThe date format used in the file names can be overridden, as well as the note folder location.\n\nEach entry file will have default sections given, with a title of today's date:\n\n```\n# 2025-01-23\n\n## Work Done\n\n- \n\n## Meetings\n\n| Time | Meeting Name |\n| ---- | ------------ |\n| | |\n\n## Follow Ups\n\n- \n\n## Scratch\n```\n\nThese default sections for the entry files can be overridden via the config.\n\n\n### Rollover Sections\n\nBy default the `Follow Ups` section is set is a \"rollover section\". This means that enheduanna will find the most recent existing entry file, find the section within that file, and \"roll it over\" to the new file. The contents of the section in the older file will be removed and automatically added into the new entry file.\n\n\nFor example, if you have the following files, with `2025-01-23.md` being the most recent file:\n\n```\nNotes/\n  2025-01-20_2025-01_26/\n    2025-01-20.md\n    2025-01-21.md\n    2025-01-22.md\n    2025-01-23.md\n```\n\nAnd the `2025-01-23.md` file contains a `Follow Ups` section:\n\n2025-01-23.md\n```\n# 2025-01-23\n\n## Follow Ups\n\n- Need to follow up with product about the new feature\n```\n\nWhen you run the `new-entry` the next day (or any later date), a new file is created, it will have the following contents:\n\n```\n# 2025-01-24\n\n## Work Done\n\n- \n\n## Meetings\n\n| Time | Meeting Name |\n| ---- | ------------ |\n| | |\n\n## Follow Ups\n\n- Need to follow up with product about the new feature\n\n## Scratch\n```\n\nThe contents of the `2025-01-23.md` file will also be updated to remove the `Follow Ups` section.\n\n\n## Collation\n\nUse the `collate` command against a note folder to collate all of the entry files in that folder into a `summary.md` file in that same folder.\n\nBy default the `Work Done` section will be combined together and placed into the new `summary.md` file.\n\nThe contents of the combined sections can also be grouped together by a regex to make it easier to edit later. By default the `Work Done` section is grouped together by a regex which looks for Jira ticket numbers within parenthesis, such as `(ABC-1234)`.\n\nIf no regex grouping options are given, the contents will be placed into the collated sections in the order they are read.\n\nFor example if you had these lines in different note files:\n\n2025-01-20.md\n```\n## Work Done\n\n- Working on some ticket (ABC-1234)\n- Fixing that one bug that's been bugging me forever (XYZ-2345)\n```\n\n2025-01-21.md\n```\n## Work Done\n\n- Working on that same ticket, had more issues (ABC-1234)\n```\n\nAfter running the `collate` command, the `summary.md` file will include:\n\nsummary.md\n```\n## Work Done\n\n- Working on some ticket (ABC-1234)\n- Working on that same ticket, had more issues (ABC-1234)\n- Fixing that one bug that's been bugging me forever (XYZ-2345)\n```\n\n### Document Collation\n\nAdditionally set a \"Document\" folder to pull out write ups you've placed in your entries. The idea here is that one-off sections that are not part of the normal section process can be removed and moved to the Document section, as a way of prototyping documentation bits such as runbooks. By default the new documents will be placed in the `~/Documents` folder.\n\nFor example if you have the following entry:\n\n2025-01-20.md\n```\n## Work Done\n\n- Working on some ticket (ABC-1234)\n- Fixing that one bug that's been bugging me forever (XYZ-2345)\n\n## Steps to Reboot Servers\n\nRun these commands\nssh ubuntu@foo.com\nsudo reboot\n```\n\nThe `collate` command will create a new file named `2025-01-20 Steps to Reboot Servers.md` in the document folder with the following contents:\n\n```\n## 2025-01-20 Steps to Reboot Servers\n\nRun these commands\nssh ubuntu@foo.com\nsudo reboot\n```\n\nThe contents of the section that was moved will also be removed from the original notes file, in this case `2025-01-20.md`.\n\n## Merge\n\nUse the `merge` command to combine all markdown files from a folder into a single markdown file. Unlike `collate`, the merge command:\n\n- Combines **all** sections from all files (doesn't use collate section configuration)\n- Preserves each file as a separate section with subsections increased by 1 level\n- Does not apply regex grouping or content reorganization\n- Does not extract separate documentation files\n\nMost useful as a utility to combine various documentation files. A common workflow is to use `collate` to extract documentation sections from entries, then use `merge` to combine related documentation files into comprehensive runbooks.\n\nEach input file becomes a level 2 section (##) in the merged document, with all its subsections increased by one level (e.g., ## becomes ###).\n\n**Usage:**\n\n```bash\nenheduanna merge \u003cfolder\u003e \u003coutput_file\u003e\n\n# Example: Combine documentation files\nenheduanna merge ~/Documents ~/Documents/complete-runbook.md\n\n# Example: Merge project notes\nenheduanna merge ~/Notes/Project_Prometheus_Notes ~/prometheus-notes.md\n\n# With custom title\nenheduanna merge ~/Documents ~/Documents/deploy-guide.md -t \"Complete Deployment Guide\"\n```\n\n## Config File\n\nThe config is a YAML config that allows for environment variable options through [pyaml-env](https://github.com/mkaranasou/pyaml_env).\nBy default the cli will look for the config file at `~/.enheduanna.yml`, and this can be overridden with the cli `-c` option.\n\n## Config Options\n\nThe various config options.\n\n### Date Format\n\nSet the date format in the config file. The date format will determine the paths of the folders and the note files, as well as the default title of each note file.\n\nShould be in the standard [python datetime format](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes).\n\nExample config:\n\n```\n---\nfile:\n  date_format: %Y-%m-%d\n```\n\n### Entries Folder\n\nOverride the entries folder where all parent folders are placed.\n\nExample Config\n\n```\n---\nfile:\n  entries_folder: /home/user/Notes\n```\n\n### Document Folder\n\nOverride the document folder where collation docs are placed in.\n\nExample Config\n\n```\n---\nfile:\n  document_folder: /home/user/Documents\n```\n\n### Entry Sections\n\nThe default sections for the entry markdown files. Each \"MarkdownSection\" should have the following params:\n\n| Param | Type | Description |\n| ----- | ---- | ----------- |\n| title | str | Title of section |\n| contents | str | Placeholder contents of section |\n| level | int | Level of section, meaning how many `#`'s are placed before the title\n| rollover | boolean | If the contents of the previous entry should be rolled over |\n| auto_generate | boolean | If the section should be included when generating a new entry (default: true) |\n\n\nThe config can take a list of these, they will be added to the file in order. Note that these will override all of the existing defaults.\n\nExample config:\n\n```\n---\nfile:\n  entry_sections:\n    - title: Work Done\n      contents: \"- \"\n      level: 2\n    - title: Meetings\n      contents: \" Time | Meeting Name |\\n| ---- | ------------ |\\n| | |\"\n      level: 2\n    - title: Follow Ups\n      contents: \"- Follow Ups\"\n      level: 2\n      rollover: true\n    - title: Scratch\n      contents: \"- \"\n      level: 2\n    - title: Notes\n      contents: \"- \"\n      level: 2\n      auto_generate: false\n```\n\nSections with `auto_generate: false` will not be included when creating a new entry via `new-entry`, but are still recognized by the system for collation, merge, and rollover. This is useful for sections you only want to add manually to specific entries.\n\n### Collate Sections\n\nCollate sections that determine which sections are combined together during the `collate` command. A better summary is above, but you can set `regex` and `groupBy` options to group common bits of content in the sections.\n\nOnly the `title` is required, the `regex` and `groupBy` are optional. You can also override the `level` that is combined, meaning the section level of the collate section, by default this is set to 2.\n\nExample config:\n\n```\n---\nfile:\n  collate_sections:\n    - title: Work Done\n      level: 2\n      regex: \"\\\\((?P\u003cticket\u003e[A-Za-z]+-[0-9]+)\\\\)\"\n      groupBy: ticket\n```\n\n### Media Organization\n\nOptionally organize screenshots, downloads, and photos into your collation folders during the `collate` command. When enabled, media files from one or more source folders (like `~/Screenshots`, `~/Downloads`) will be moved or copied to subfolders within each collation folder, and markdown image references will be automatically updated.\n\n**Note:** This feature is disabled by default. Set `enabled: true` in the config to activate it.\n\n**Configuration Parameters:**\n\n| Param | Type | Description |\n| ----- | ---- | ----------- |\n| sources | list[MediaSource] | List of source folders to scan for media files |\n| extensions | list[str] | List of file extensions to process (default: `[\".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\"]`) |\n| enabled | boolean | Enable or disable media organization (default: `false`) |\n\n**MediaSource Parameters:**\n\n| Param | Type | Description |\n| ----- | ---- | ----------- |\n| folder | Path | Source folder to scan for media files (e.g., `~/Screenshots`, `~/Downloads`) |\n| operation | str | Either `\"move\"` or `\"copy\"` - whether to move or copy files from source to collation folder |\n| subfolder | str | Subfolder path within the collation folder to store media files (e.g., `\"media/screenshots\"`) |\n\n**How it works:**\n- Files are identified by their **modified time** (no regex parsing needed)\n- Files are renamed to: `YYYY-MM-DD_HH-MM-SS.ext` (e.g., `2025-01-20_14-30-45.png`)\n- Only files with modified times within the collation date range are processed\n- Each source folder can have different operations (move vs copy) and destination subfolders\n- Markdown image references are automatically updated to point to the new locations\n\n**Example config:**\n\n```yaml\n---\nfile:\n  media:\n    sources:\n      - folder: ~/Screenshots\n        operation: move\n        subfolder: media/screenshots\n      - folder: ~/Downloads\n        operation: copy\n        subfolder: media/downloads\n    extensions:\n      - .png\n      - .jpg\n      - .jpeg\n      - .gif\n      - .webp\n    enabled: true\n```\n\n**Workflow Example:**\n\n1. You take screenshots and download images during the week:\n   - `~/Screenshots/screenshot1.png` (modified: 2025-01-20 14:30:45)\n   - `~/Downloads/diagram.jpg` (modified: 2025-01-21 09:15:30)\n\n2. You reference them in your entries:\n   ```markdown\n   # 2025-01-20\n   ## Work Done\n   - Fixed the login bug ![screenshot](~/Screenshots/screenshot1.png)\n   - Updated architecture ![diagram](~/Downloads/diagram.jpg)\n   ```\n\n3. When you run `enheduanna collate ~/Notes/2025-01-20_2025-01-26`:\n   - `screenshot1.png` is moved to `~/Notes/2025-01-20_2025-01-26/media/screenshots/2025-01-20_14-30-45.png`\n   - `diagram.jpg` is copied to `~/Notes/2025-01-20_2025-01-26/media/downloads/2025-01-21_09-15-30.jpg`\n   - Markdown references are updated:\n     - `![screenshot](./media/screenshots/2025-01-20_14-30-45.png)`\n     - `![diagram](./media/downloads/2025-01-21_09-15-30.jpg)`\n\n### Collation Settings\n\nYou can configure whether you want the sub-folders created to be on a per week or per month basis. The accepted values here are `weekly` and `monthly`.\n\n```\ncollation:\n  type: monthly\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftnoff%2Fenheduanna","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftnoff%2Fenheduanna","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftnoff%2Fenheduanna/lists"}