markdown-os 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. markdown_os-0.1.0/.codex/environments/environment.toml +11 -0
  2. markdown_os-0.1.0/.cursor/worktrees.json +5 -0
  3. markdown_os-0.1.0/.github/workflows/publish.yml +58 -0
  4. markdown_os-0.1.0/.gitignore +14 -0
  5. markdown_os-0.1.0/.python-version +1 -0
  6. markdown_os-0.1.0/CLAUDE.md +160 -0
  7. markdown_os-0.1.0/LICENSE +182 -0
  8. markdown_os-0.1.0/PKG-INFO +108 -0
  9. markdown_os-0.1.0/README.md +75 -0
  10. markdown_os-0.1.0/docs/plans/feature-file-tree-browser.md +1736 -0
  11. markdown_os-0.1.0/docs/plans/feature-pypi-publishing.md +484 -0
  12. markdown_os-0.1.0/docs/roadmap.md +149 -0
  13. markdown_os-0.1.0/example.md +409 -0
  14. markdown_os-0.1.0/hello.py +6 -0
  15. markdown_os-0.1.0/markdown_os/__init__.py +12 -0
  16. markdown_os-0.1.0/markdown_os/cli.py +272 -0
  17. markdown_os-0.1.0/markdown_os/file_handler.py +193 -0
  18. markdown_os-0.1.0/markdown_os/server.py +437 -0
  19. markdown_os-0.1.0/markdown_os/static/css/styles.css +774 -0
  20. markdown_os-0.1.0/markdown_os/static/favicon.svg +4 -0
  21. markdown_os-0.1.0/markdown_os/static/index.html +151 -0
  22. markdown_os-0.1.0/markdown_os/static/js/editor.js +335 -0
  23. markdown_os-0.1.0/markdown_os/static/js/markdown.js +451 -0
  24. markdown_os-0.1.0/markdown_os/static/js/theme.js +158 -0
  25. markdown_os-0.1.0/markdown_os/static/js/toc.js +156 -0
  26. markdown_os-0.1.0/markdown_os/static/js/websocket.js +86 -0
  27. markdown_os-0.1.0/markdown_os/templates/example_template.md +409 -0
  28. markdown_os-0.1.0/pyproject.toml +58 -0
  29. markdown_os-0.1.0/tests/test_cli.py +424 -0
  30. markdown_os-0.1.0/tests/test_file_handler.py +66 -0
  31. markdown_os-0.1.0/tests/test_server.py +87 -0
  32. markdown_os-0.1.0/tests/test_version.py +19 -0
  33. markdown_os-0.1.0/uv.lock +776 -0
@@ -0,0 +1,11 @@
1
+ # THIS IS AUTOGENERATED. DO NOT EDIT MANUALLY
2
+ version = 1
3
+ name = "markdown-os"
4
+
5
+ [setup]
6
+ script = ""
7
+
8
+ [[actions]]
9
+ name = "Run"
10
+ icon = "run"
11
+ command = "uv run markdown-os open docs/roadmap.md"
@@ -0,0 +1,5 @@
1
+ {
2
+ "setup-worktree": [
3
+ "npm install"
4
+ ]
5
+ }
@@ -0,0 +1,58 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Checkout repository
17
+ uses: actions/checkout@v4
18
+
19
+ - name: Set up uv
20
+ uses: astral-sh/setup-uv@v5
21
+
22
+ - name: Validate tag matches package version
23
+ run: |
24
+ python - <<'PY'
25
+ import tomllib
26
+ from pathlib import Path
27
+
28
+ pyproject = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
29
+ package_version = pyproject["project"]["version"]
30
+ tag_version = "${{ github.ref_name }}".lstrip("v")
31
+ if package_version != tag_version:
32
+ raise SystemExit(
33
+ f"Tag version '{tag_version}' does not match pyproject version '{package_version}'."
34
+ )
35
+ PY
36
+
37
+ - name: Install dependencies
38
+ run: uv sync --dev
39
+
40
+ - name: Run tests
41
+ run: uv run pytest
42
+
43
+ publish:
44
+ needs: test
45
+ runs-on: ubuntu-latest
46
+ environment: pypi
47
+ steps:
48
+ - name: Checkout repository
49
+ uses: actions/checkout@v4
50
+
51
+ - name: Set up uv
52
+ uses: astral-sh/setup-uv@v5
53
+
54
+ - name: Build distributions
55
+ run: uv build
56
+
57
+ - name: Publish to PyPI
58
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,14 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # lock files except uv.lock
13
+ *.lock
14
+ !uv.lock
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,160 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ Markdown-OS is a developer-focused, CLI-driven markdown editor that runs as a local web server. It provides real-time editing with a read-first workflow, Mermaid diagram support, syntax highlighting, auto-saving, and light/dark theme switching.
8
+
9
+ **Tech Stack:**
10
+ - Backend: Python 3.11+ with FastAPI, Typer CLI, Uvicorn ASGI server, Watchdog for file monitoring
11
+ - Frontend: Vanilla HTML/CSS/JavaScript with Marked.js (markdown parsing), Mermaid.js (diagrams), highlight.js (syntax highlighting), svg-pan-zoom (interactive diagrams)
12
+
13
+ ## Common Commands
14
+
15
+ ### Development Setup
16
+ ```bash
17
+ # Install dependencies (uses uv package manager)
18
+ uv sync
19
+
20
+ # Run the editor
21
+ uv run markdown-os open ./notes.md
22
+
23
+ # Generate a feature showcase markdown file
24
+ uv run markdown-os example
25
+
26
+ # Generate showcase and open it immediately
27
+ uv run markdown-os example --open
28
+
29
+ # Run all tests
30
+ uv run pytest
31
+
32
+ # Run specific test file
33
+ uv run pytest tests/test_cli.py
34
+
35
+ # Run single test
36
+ uv run pytest tests/test_cli.py::test_validate_markdown_file_returns_resolved_path
37
+
38
+ # Run tests with verbose output
39
+ uv run pytest -v
40
+
41
+ # Run tests with output capture disabled (see print statements)
42
+ uv run pytest -s
43
+ ```
44
+
45
+ ### Running the Application
46
+ ```bash
47
+ # Basic usage
48
+ uv run markdown-os open <filepath.md>
49
+
50
+ # Custom host and port
51
+ uv run markdown-os open <filepath.md> --host 0.0.0.0 --port 9000
52
+
53
+ # If port is occupied, the app auto-increments (8000 → 8001 → 8002...)
54
+ ```
55
+
56
+ ## Architecture Overview
57
+
58
+ ### High-Level Flow
59
+ ```
60
+ CLI Command → Typer validates file → FastAPI server starts → Browser opens
61
+
62
+ User edits in browser → WebSocket connection → Server saves to disk
63
+
64
+ External file change → Watchdog detects → WebSocket notifies browser
65
+ ```
66
+
67
+ ### Key Components
68
+
69
+ #### 1. CLI Layer (`markdown_os/cli.py`)
70
+ - Entry point: `markdown-os` command defined in `pyproject.toml`
71
+ - Validates markdown file paths (.md, .markdown extensions only)
72
+ - Implements port auto-increment logic (tries 8000-65535)
73
+ - Opens browser automatically after 0.4s delay
74
+ - Creates FileHandler and FastAPI app, then runs uvicorn server
75
+
76
+ #### 2. FastAPI Server (`markdown_os/server.py`)
77
+ - **Routes:**
78
+ - `GET /`: Serves the editor HTML page
79
+ - `GET /api/content`: Returns markdown content and metadata
80
+ - `POST /api/save`: Saves content atomically to disk
81
+ - `WebSocket /ws`: Real-time notifications for external file changes
82
+ - **WebSocketHub**: Manages active websocket clients and broadcasts messages
83
+ - **MarkdownFileEventHandler**: Watchdog event handler that filters events for the target file and throttles notifications (0.2s minimum interval)
84
+ - **Lifespan management**: Starts/stops filesystem observer with the app
85
+
86
+ #### 3. File Handler (`markdown_os/file_handler.py`)
87
+ - Implements safe file I/O with POSIX file locks (fcntl)
88
+ - **Read operations**: Use shared locks (LOCK_SH) for concurrent reads
89
+ - **Write operations**: Use exclusive locks (LOCK_EX) with atomic file replacement
90
+ - Write to temporary file with fsync
91
+ - Replace original file with os.replace() (atomic on POSIX)
92
+ - Uses .lock files in same directory as markdown file
93
+ - **Error handling**: Custom FileReadError and FileWriteError exceptions
94
+
95
+ #### 4. Frontend (`markdown_os/static/`)
96
+ - **index.html**: Main editor page with tabbed interface (Edit/Preview modes)
97
+ - **js/editor.js**: Content loading, tab switching, conflict handling, auto-save with 1s debouncing
98
+ - **js/markdown.js**: Markdown rendering with Marked.js, Mermaid diagram rendering, syntax highlighting, code block enhancements (copy button, language labels)
99
+ - **js/theme.js**: Theme preference management, system preference detection, highlight theme switching, Mermaid re-render trigger
100
+ - **js/toc.js**: Auto-generated table of contents from headings with smooth scrolling
101
+ - **js/websocket.js**: WebSocket connection for external file change notifications
102
+ - **css/styles.css**: Layout and styling
103
+
104
+ ### Critical Implementation Details
105
+
106
+ #### File Locking Strategy
107
+ - Lock files are created at `<filename>.md.lock` next to the markdown file
108
+ - Shared locks (LOCK_SH) allow multiple concurrent readers
109
+ - Exclusive locks (LOCK_EX) ensure only one writer at a time
110
+ - Locks are always released in finally blocks
111
+
112
+ #### External Change Detection
113
+ - Watchdog monitors the markdown file's parent directory (non-recursive)
114
+ - Events are filtered to match only the target file path
115
+ - Events within 0.5s of internal writes are ignored to prevent self-notification
116
+ - Events are throttled to max one notification per 0.2s
117
+ - Browser receives `{"type": "file_changed", "content": "<new content>"}` via WebSocket
118
+
119
+ #### Auto-save and Mode Behavior
120
+ - Files open in `Preview` mode by default (`read-first` behavior).
121
+ - `Edit` mode is active only when the Edit tab is selected.
122
+ - Editor input triggers debounced save after 1 second of inactivity
123
+ - Preview renders on demand when Preview tab is active (not on every edit keystroke)
124
+ - Save status indicator shows "Saving...", "Saved", or error states
125
+ - Switching `Edit → Preview` auto-saves unless a conflict is detected
126
+ - Conflict detection compares `/api/content` against `lastSavedContent`; if different and there are unsaved edits, a 3-button modal is shown (`Save My Changes`, `Discard My Changes`, `Cancel`)
127
+ - Server timestamps internal writes to distinguish from external changes
128
+
129
+ #### Theme Behavior
130
+ - Theme defaults to system preference (`prefers-color-scheme`) when no manual choice exists
131
+ - Manual theme toggles are persisted in `localStorage` key `markdown-os-theme`
132
+ - Syntax highlighting switches between `github` and `github-dark` highlight.js stylesheets
133
+ - Mermaid diagrams are re-rendered on theme changes using source stored in `data-original-content`
134
+
135
+ ## Testing Conventions
136
+
137
+ - Tests use pytest with async support (pytest-asyncio)
138
+ - Test files mirror source structure: `tests/test_<module>.py`
139
+ - Use pytest fixtures: `tmp_path` for temporary directories, httpx.AsyncClient for API testing
140
+ - Test both success paths and error conditions (missing files, invalid permissions, etc.)
141
+ - Server tests create test apps with temporary file handlers
142
+
143
+ ## Code Style and Patterns
144
+
145
+ - Type hints are used throughout (PEP 484)
146
+ - Docstrings follow Google-style format with Args/Returns sections
147
+ - All public functions/methods have docstrings
148
+ - Error handling uses custom exceptions (FileReadError, FileWriteError)
149
+ - Async/await is used consistently in FastAPI routes
150
+ - Context managers are used for resource management (locks, files)
151
+
152
+ ## Important Notes
153
+
154
+ - The app only supports one markdown file at a time (MVP constraint)
155
+ - Port 8000 is preferred but auto-increments if occupied
156
+ - Browser opens automatically 0.4s after server start
157
+ - File locks use POSIX fcntl (may not work on Windows without adaptation)
158
+ - WebSocket reconnection logic is handled client-side
159
+ - Static files are served from `markdown_os/static/` directory
160
+ - The CLI script is exposed via `pyproject.toml` entry points
@@ -0,0 +1,182 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction, and
10
+ distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright
13
+ owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all other entities
16
+ that control, are controlled by, or are under common control with that entity.
17
+ For the purposes of this definition, "control" means (i) the power, direct or
18
+ indirect, to cause the direction or management of such entity, whether by
19
+ contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20
+ outstanding shares, or (iii) beneficial ownership of such entity.
21
+
22
+ "You" (or "Your") shall mean an individual or Legal Entity exercising
23
+ permissions granted by this License.
24
+
25
+ "Source" form shall mean the preferred form for making modifications, including
26
+ but not limited to software source code, documentation source, and configuration
27
+ files.
28
+
29
+ "Object" form shall mean any form resulting from mechanical transformation or
30
+ translation of a Source form, including but not limited to compiled object code,
31
+ generated documentation, and conversions to other media types.
32
+
33
+ "Work" shall mean the work of authorship, whether in Source or Object form, made
34
+ available under the License, as indicated by a copyright notice that is included
35
+ in or attached to the work (an example is provided in the Appendix below).
36
+
37
+ "Derivative Works" shall mean any work, whether in Source or Object form, that
38
+ is based on (or derived from) the Work and for which the editorial revisions,
39
+ annotations, elaborations, or other modifications represent, as a whole, an
40
+ original work of authorship. For the purposes of this License, Derivative Works
41
+ shall not include works that remain separable from, or merely link (or bind by
42
+ name) to the interfaces of, the Work and Derivative Works thereof.
43
+
44
+ "Contribution" shall mean any work of authorship, including the original version
45
+ of the Work and any modifications or additions to that Work or Derivative Works
46
+ thereof, that is intentionally submitted to Licensor for inclusion in the Work
47
+ by the copyright owner or by an individual or Legal Entity authorized to submit
48
+ on behalf of the copyright owner. For the purposes of this definition,
49
+ "submitted" means any form of electronic, verbal, or written communication sent
50
+ to the Licensor or its representatives, including but not limited to
51
+ communication on electronic mailing lists, source code control systems, and
52
+ issue tracking systems that are managed by, or on behalf of, the Licensor for
53
+ the purpose of discussing and improving the Work, but excluding communication
54
+ that is conspicuously marked or otherwise designated in writing by the copyright
55
+ owner as "Not a Contribution."
56
+
57
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58
+ of whom a Contribution has been received by Licensor and subsequently
59
+ incorporated within the Work.
60
+
61
+ 2. Grant of Copyright License. Subject to the terms and conditions of this
62
+ License, each Contributor hereby grants to You a perpetual, worldwide,
63
+ non-exclusive, no-charge, royalty-free, irrevocable copyright license to
64
+ reproduce, prepare Derivative Works of, publicly display, publicly perform,
65
+ sublicense, and distribute the Work and such Derivative Works in Source or
66
+ Object form.
67
+
68
+ 3. Grant of Patent License. Subject to the terms and conditions of this License,
69
+ each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
70
+ no-charge, royalty-free, irrevocable (except as stated in this section) patent
71
+ license to make, have made, use, offer to sell, sell, import, and otherwise
72
+ transfer the Work, where such license applies only to those patent claims
73
+ licensable by such Contributor that are necessarily infringed by their
74
+ Contribution(s) alone or by combination of their Contribution(s) with the Work
75
+ to which such Contribution(s) was submitted. If You institute patent litigation
76
+ against any entity (including a cross-claim or counterclaim in a lawsuit)
77
+ alleging that the Work or a Contribution incorporated within the Work constitutes
78
+ direct or contributory patent infringement, then any patent licenses granted to
79
+ You under this License for that Work shall terminate as of the date such
80
+ litigation is filed.
81
+
82
+ 4. Redistribution. You may reproduce and distribute copies of the Work or
83
+ Derivative Works thereof in any medium, with or without modifications, and in
84
+ Source or Object form, provided that You meet the following conditions:
85
+
86
+ (a) You must give any other recipients of the Work or Derivative Works a copy of
87
+ this License; and
88
+
89
+ (b) You must cause any modified files to carry prominent notices stating that You
90
+ changed the files; and
91
+
92
+ (c) You must retain, in the Source form of any Derivative Works that You
93
+ distribute, all copyright, patent, trademark, and attribution notices from the
94
+ Source form of the Work, excluding those notices that do not pertain to any part
95
+ of the Derivative Works; and
96
+
97
+ (d) If the Work includes a "NOTICE" text file as part of its distribution, then
98
+ any Derivative Works that You distribute must include a readable copy of the
99
+ attribution notices contained within such NOTICE file, excluding those notices
100
+ that do not pertain to any part of the Derivative Works, in at least one of the
101
+ following places: within a NOTICE text file distributed as part of the Derivative
102
+ Works; within the Source form or documentation, if provided along with the
103
+ Derivative Works; or, within a display generated by the Derivative Works, if and
104
+ wherever such third-party notices normally appear. The contents of the NOTICE
105
+ file are for informational purposes only and do not modify the License. You may
106
+ add Your own attribution notices within Derivative Works that You distribute,
107
+ alongside or as an addendum to the NOTICE text from the Work, provided that such
108
+ additional attribution notices cannot be construed as modifying the License.
109
+
110
+ You may add Your own copyright statement to Your modifications and may provide
111
+ additional or different license terms and conditions for use, reproduction, or
112
+ distribution of Your modifications, or for any such Derivative Works as a whole,
113
+ provided Your use, reproduction, and distribution of the Work otherwise complies
114
+ with the conditions stated in this License.
115
+
116
+ 5. Submission of Contributions. Unless You explicitly state otherwise, any
117
+ Contribution intentionally submitted for inclusion in the Work by You to the
118
+ Licensor shall be under the terms and conditions of this License, without any
119
+ additional terms or conditions. Notwithstanding the above, nothing herein shall
120
+ supersede or modify the terms of any separate license agreement you may have
121
+ executed with Licensor regarding such Contributions.
122
+
123
+ 6. Trademarks. This License does not grant permission to use the trade names,
124
+ trademarks, service marks, or product names of the Licensor, except as required
125
+ for reasonable and customary use in describing the origin of the Work and
126
+ reproducing the content of the NOTICE file.
127
+
128
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in
129
+ writing, Licensor provides the Work (and each Contributor provides its
130
+ Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
131
+ either express or implied, including, without limitation, any warranties or
132
+ conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
133
+ PARTICULAR PURPOSE. You are solely responsible for determining the
134
+ appropriateness of using or redistributing the Work and assume any risks
135
+ associated with Your exercise of permissions under this License.
136
+
137
+ 8. Limitation of Liability. In no event and under no legal theory, whether in
138
+ tort (including negligence), contract, or otherwise, unless required by
139
+ applicable law (such as deliberate and grossly negligent acts) or agreed to in
140
+ writing, shall any Contributor be liable to You for damages, including any
141
+ direct, indirect, special, incidental, or consequential damages of any character
142
+ arising as a result of this License or out of the use or inability to use the
143
+ Work (including but not limited to damages for loss of goodwill, work stoppage,
144
+ computer failure or malfunction, or any and all other commercial damages or
145
+ losses), even if such Contributor has been advised of the possibility of such
146
+ damages.
147
+
148
+ 9. Accepting Warranty or Additional Liability. While redistributing the Work or
149
+ Derivative Works thereof, You may choose to offer, and charge a fee for,
150
+ acceptance of support, warranty, indemnity, or other liability obligations and/or
151
+ rights consistent with this License. However, in accepting such obligations, You
152
+ may act only on Your own behalf and on Your sole responsibility, not on behalf of
153
+ any other Contributor, and only if You agree to indemnify, defend, and hold each
154
+ Contributor harmless for any liability incurred by, or claims asserted against,
155
+ such Contributor by reason of your accepting any such warranty or additional
156
+ liability.
157
+
158
+ END OF TERMS AND CONDITIONS
159
+
160
+ APPENDIX: How to apply the Apache License to your work.
161
+
162
+ To apply the Apache License to your work, attach the following boilerplate
163
+ notice, with the fields enclosed by brackets "[]" replaced with your own
164
+ identifying information. (Don't include the brackets!) The text should be
165
+ enclosed in the appropriate comment syntax for the file format. We also recommend
166
+ that a file or class name and description of purpose be included on the same
167
+ "printed page" as the copyright notice for easier identification within
168
+ third-party archives.
169
+
170
+ Copyright 2026 Elena Cabrera
171
+
172
+ Licensed under the Apache License, Version 2.0 (the "License");
173
+ you may not use this file except in compliance with the License.
174
+ You may obtain a copy of the License at
175
+
176
+ http://www.apache.org/licenses/LICENSE-2.0
177
+
178
+ Unless required by applicable law or agreed to in writing, software
179
+ distributed under the License is distributed on an "AS IS" BASIS,
180
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
181
+ See the License for the specific language governing permissions and
182
+ limitations under the License.
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.4
2
+ Name: markdown-os
3
+ Version: 0.1.0
4
+ Summary: Developer-focused markdown editor served from a local CLI.
5
+ Project-URL: Homepage, https://github.com/elena-cabrera/markdown-os
6
+ Project-URL: Repository, https://github.com/elena-cabrera/markdown-os
7
+ Project-URL: Issues, https://github.com/elena-cabrera/markdown-os/issues
8
+ Author: Elena Cabrera
9
+ License-Expression: Apache-2.0
10
+ License-File: LICENSE
11
+ Keywords: cli,developer-tools,editor,markdown,preview
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Framework :: FastAPI
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: License :: OSI Approved :: Apache Software License
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Text Editors
23
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.11
26
+ Requires-Dist: fastapi>=0.129.0
27
+ Requires-Dist: python-multipart>=0.0.22
28
+ Requires-Dist: typer>=0.23.1
29
+ Requires-Dist: uvicorn[standard]>=0.40.0
30
+ Requires-Dist: watchdog>=6.0.0
31
+ Requires-Dist: websockets>=16.0
32
+ Description-Content-Type: text/markdown
33
+
34
+ # Markdown-OS
35
+
36
+ [![PyPI version](https://img.shields.io/pypi/v/markdown-os)](https://pypi.org/project/markdown-os/)
37
+
38
+ Markdown-OS is a local, developer-focused markdown editor served by FastAPI and launched from a Typer CLI.
39
+
40
+ ## Quick Install
41
+
42
+ ```bash
43
+ pip install markdown-os
44
+ ```
45
+
46
+ Or install as a global tool with uv:
47
+
48
+ ```bash
49
+ uv tool install markdown-os
50
+ ```
51
+
52
+ Then run:
53
+
54
+ ```bash
55
+ markdown-os open ./notes.md
56
+ ```
57
+
58
+ ## Read-first workflow
59
+
60
+ - Files open in `Preview` mode by default for safer browsing.
61
+ - Switch to `Edit` when you want to type.
62
+ - Switching from `Edit` to `Preview` auto-saves changes when there is no external conflict.
63
+ - If the file changed externally and you have unsaved edits, Markdown-OS shows a conflict dialog:
64
+ - `Save My Changes` overwrites disk with your editor content.
65
+ - `Discard My Changes` reloads content from disk.
66
+ - `Cancel` keeps you in edit mode with unsaved changes intact.
67
+ - External file changes auto-reload without prompts when safe:
68
+ - always in preview mode
69
+ - in edit mode when there are no unsaved changes
70
+
71
+ ## Install dependencies
72
+
73
+ ```bash
74
+ uv sync
75
+ ```
76
+
77
+ ## Run
78
+
79
+ ```bash
80
+ uv run markdown-os open ./notes.md
81
+ ```
82
+
83
+ If port `8000` is occupied, Markdown-OS auto-selects the next available port.
84
+
85
+ ## Theme toggle
86
+
87
+ - The editor detects your system color preference on first load.
88
+ - Use the sun/moon toggle in the top-right header to switch between light and dark themes.
89
+ - Manual selection is persisted in `localStorage` and restored on reload.
90
+
91
+ ## Interactive task lists
92
+
93
+ - In `Preview`, markdown task list items (`- [ ]` and `- [x]`) are clickable.
94
+ - Clicking a checkbox updates markdown source immediately and auto-saves to disk.
95
+ - External-change conflicts use the same `Save My Changes` / `Discard My Changes` / `Cancel` flow.
96
+
97
+ ## Generate a showcase file
98
+
99
+ ```bash
100
+ # Create example.md in current directory
101
+ uv run markdown-os example
102
+
103
+ # Create at a custom location
104
+ uv run markdown-os example ./docs/showcase.md
105
+
106
+ # Generate and open immediately
107
+ uv run markdown-os example --open
108
+ ```
@@ -0,0 +1,75 @@
1
+ # Markdown-OS
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/markdown-os)](https://pypi.org/project/markdown-os/)
4
+
5
+ Markdown-OS is a local, developer-focused markdown editor served by FastAPI and launched from a Typer CLI.
6
+
7
+ ## Quick Install
8
+
9
+ ```bash
10
+ pip install markdown-os
11
+ ```
12
+
13
+ Or install as a global tool with uv:
14
+
15
+ ```bash
16
+ uv tool install markdown-os
17
+ ```
18
+
19
+ Then run:
20
+
21
+ ```bash
22
+ markdown-os open ./notes.md
23
+ ```
24
+
25
+ ## Read-first workflow
26
+
27
+ - Files open in `Preview` mode by default for safer browsing.
28
+ - Switch to `Edit` when you want to type.
29
+ - Switching from `Edit` to `Preview` auto-saves changes when there is no external conflict.
30
+ - If the file changed externally and you have unsaved edits, Markdown-OS shows a conflict dialog:
31
+ - `Save My Changes` overwrites disk with your editor content.
32
+ - `Discard My Changes` reloads content from disk.
33
+ - `Cancel` keeps you in edit mode with unsaved changes intact.
34
+ - External file changes auto-reload without prompts when safe:
35
+ - always in preview mode
36
+ - in edit mode when there are no unsaved changes
37
+
38
+ ## Install dependencies
39
+
40
+ ```bash
41
+ uv sync
42
+ ```
43
+
44
+ ## Run
45
+
46
+ ```bash
47
+ uv run markdown-os open ./notes.md
48
+ ```
49
+
50
+ If port `8000` is occupied, Markdown-OS auto-selects the next available port.
51
+
52
+ ## Theme toggle
53
+
54
+ - The editor detects your system color preference on first load.
55
+ - Use the sun/moon toggle in the top-right header to switch between light and dark themes.
56
+ - Manual selection is persisted in `localStorage` and restored on reload.
57
+
58
+ ## Interactive task lists
59
+
60
+ - In `Preview`, markdown task list items (`- [ ]` and `- [x]`) are clickable.
61
+ - Clicking a checkbox updates markdown source immediately and auto-saves to disk.
62
+ - External-change conflicts use the same `Save My Changes` / `Discard My Changes` / `Cancel` flow.
63
+
64
+ ## Generate a showcase file
65
+
66
+ ```bash
67
+ # Create example.md in current directory
68
+ uv run markdown-os example
69
+
70
+ # Create at a custom location
71
+ uv run markdown-os example ./docs/showcase.md
72
+
73
+ # Generate and open immediately
74
+ uv run markdown-os example --open
75
+ ```