diff --git a/COMMERCIAL_LICENSE.md b/COMMERCIAL_LICENSE.md index f94dfff..624a288 100644 --- a/COMMERCIAL_LICENSE.md +++ b/COMMERCIAL_LICENSE.md @@ -1,6 +1,6 @@ # Commercial License Terms (Summary) -For **production or commercial use** of `contentkit`, you must obtain a commercial license from the Licensor. +For **production or commercial use** of `PulseWriter`, you must obtain a commercial license from the Licensor. Contact: nikita.koselev@gmail.com Typical grant includes: diff --git a/FEATURES.md b/FEATURES.md index 09afaea..397e4c6 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -4,7 +4,7 @@ Status: ๐ŸŸข Ready ยท ๐ŸŸก In Progress ยท ๐Ÿ”ด Blocked ยท โœ… Done | ID | Feature | Status | Notes / Acceptance Criteria | Owner | |----|---------|--------|-----------------------------|-------| -| F-001 | CLI: transform markdown โ†’ blog/LinkedIn/X/Dev.to | โœ… | `contentkit_cli transform` writes files to /out | core | +| F-001 | CLI: transform markdown โ†’ blog/LinkedIn/X/Dev.to | โœ… | `pulsewriter` writes files to /out | core | | F-002 | API: `/generate` + `/revise` | โœ… | Accepts `topic` or `body_markdown`, returns drafts | api | | F-003 | Templates: tone/persona system | โœ… | Jinja templates parametrize `{tone, persona, word_target}` | core | | F-004 | GitHub PR helper (blog repo) | ๐ŸŸข | Function: create branch, commit file, open PR to `nikitakoselev/nikitakoselev.github.io` | connectors | diff --git a/README.md b/README.md index 0e23c21..862625f 100644 --- a/README.md +++ b/README.md @@ -6,31 +6,82 @@ This MVP intentionally keeps logic simple (template-based) so you can ship fast; ## Quick start +### 1. Create and activate a virtual environment + +**macOS / Linux (bash or zsh)** + ```bash -# Create & activate venv (example) -python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate +python -m venv .venv # -m: run the venv module to create env in .venv +source .venv/bin/activate # activate the virtual environment +``` + +**Windows PowerShell** + +```powershell +python -m venv .venv # -m: run the venv module; .venv is env folder +.\.venv\Scripts\Activate.ps1 # activate the virtual environment +``` + +**Windows CMD** -# Install +```cmd +python -m venv .venv +REM -m: run the venv module; .venv is env folder +.\.venv\Scripts\activate.bat +REM Activate the virtual environment +``` + +### 2. Install dependencies + +**macOS / Linux** + +```bash +pip install -e .[dev] # -e: editable install; .[dev]: include dev extras +``` + +**Windows PowerShell** + +```powershell +pip install -e ".[dev]" # -e: editable install; "[dev]": include dev extras +``` + +**Windows CMD** + +```cmd pip install -e .[dev] +REM -e: editable install +REM .[dev]: include dev extras +``` -# Try CLI -python -m PulseWriter_cli --help -python -m PulseWriter_cli transform examples/input.md --platforms linkedin x devto --out-dir ./out +### 3. Run the CLI -# Run API -uvicorn PulseWriter_api.main:app --reload +```bash +pulsewriter --help # show CLI usage and exit +pulsewriter examples/input.md \ # source markdown + --platforms linkedin \ # include LinkedIn draft + --platforms x \ # include X (Twitter) draft + --platforms devto \ # include Dev.to draft + --out-dir ./out # write output files to ./out +``` + +### 4. Run the API + +```bash +uvicorn pulsewriter_api.main:app --reload # --reload: restart on code changes # POST /generate with JSON: {"topic":"Impact to Cashflow","platforms":["blog","linkedin","x"]} ``` ## Project layout ``` -packages/ - core/PulseWriter_core/ # Open core: transforms, templates, validators - cli/PulseWriter_cli/ # Typer CLI (calls core) - api/PulseWriter_api/ # FastAPI (calls core) +src/ + pulsewriter_core/ # Open core: transforms, templates, validators + pulsewriter_cli/ # Typer CLI (calls core) + pulsewriter_api/ # FastAPI (calls core) examples/ # Sample input & config recipes/n8n/ # (Optional) n8n workflow stubs +tests/ # Test suite +connectors/ # Optional helper modules ``` ## License @@ -43,7 +94,6 @@ You may run, modify, and use non-production internally. **Production/commercial - v0.2: add optional LLM augment in core (behind a flag) - v0.3: connectors (Buffer/Notion/GitHub PR helper) - v0.4: n8n nodes + Telegram bot adapter -``` --- diff --git a/packages/connectors/github_pr.py b/connectors/github_pr.py similarity index 100% rename from packages/connectors/github_pr.py rename to connectors/github_pr.py diff --git a/packages/core/contentkit_core/__init__.py b/packages/core/contentkit_core/__init__.py deleted file mode 100644 index afcfc67..0000000 --- a/packages/core/contentkit_core/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .transform import TransformConfig, generate, revise diff --git a/pyproject.toml b/pyproject.toml index 40ff0c5..5e0b82f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,5 +22,12 @@ dependencies = [ [project.optional-dependencies] dev = ["pytest>=8.2.0", "pytest-cov>=5.0.0"] -[tool.setuptools.packages.find] -where = ["packages"] +[project.scripts] +pulsewriter = "pulsewriter_cli.main:app" + +[tool.setuptools] +packages = ["pulsewriter_core", "pulsewriter_cli", "pulsewriter_api"] +package-dir = {"" = "src"} + +[tool.setuptools.package-data] +pulsewriter_core = ["templates/*.j2"] diff --git a/packages/api/contentkit_api/main.py b/src/pulsewriter_api/main.py similarity index 92% rename from packages/api/contentkit_api/main.py rename to src/pulsewriter_api/main.py index 1e01380..fb996f5 100644 --- a/packages/api/contentkit_api/main.py +++ b/src/pulsewriter_api/main.py @@ -1,9 +1,9 @@ from fastapi import FastAPI, Body from pydantic import BaseModel from typing import List, Optional, Dict, Any -from contentkit_core import TransformConfig, generate, revise +from pulsewriter_core import TransformConfig, generate, revise -app = FastAPI(title="contentkit API", version="0.1.0") +app = FastAPI(title="PulseWriter API", version="0.1.0") class GenerateRequest(BaseModel): topic: Optional[str] = None diff --git a/packages/cli/contentkit_cli/__init__.py b/src/pulsewriter_cli/__init__.py similarity index 100% rename from packages/cli/contentkit_cli/__init__.py rename to src/pulsewriter_cli/__init__.py diff --git a/src/pulsewriter_cli/__main__.py b/src/pulsewriter_cli/__main__.py new file mode 100644 index 0000000..3e6e96f --- /dev/null +++ b/src/pulsewriter_cli/__main__.py @@ -0,0 +1,4 @@ +from .main import app + +if __name__ == "__main__": + app() diff --git a/packages/cli/contentkit_cli/main.py b/src/pulsewriter_cli/main.py similarity index 85% rename from packages/cli/contentkit_cli/main.py rename to src/pulsewriter_cli/main.py index 4644388..aa40390 100644 --- a/packages/cli/contentkit_cli/main.py +++ b/src/pulsewriter_cli/main.py @@ -1,9 +1,9 @@ import typer from pathlib import Path from typing import List -from contentkit_core import TransformConfig, generate, save_text, load_markdown +from pulsewriter_core import TransformConfig, generate, save_text, load_markdown -app = typer.Typer(help="contentkit CLI โ€” transform a single markdown into platform drafts.") +app = typer.Typer(help="PulseWriter CLI โ€” transform a single markdown into platform drafts.") @app.command() def transform( diff --git a/src/pulsewriter_core/__init__.py b/src/pulsewriter_core/__init__.py new file mode 100644 index 0000000..23592ba --- /dev/null +++ b/src/pulsewriter_core/__init__.py @@ -0,0 +1,15 @@ +from .transform import ( + TransformConfig, + generate, + revise, + load_markdown, + save_text, +) + +__all__ = [ + "TransformConfig", + "generate", + "revise", + "load_markdown", + "save_text", +] diff --git a/packages/core/contentkit_core/templates/blog.md.j2 b/src/pulsewriter_core/templates/blog.md.j2 similarity index 100% rename from packages/core/contentkit_core/templates/blog.md.j2 rename to src/pulsewriter_core/templates/blog.md.j2 diff --git a/packages/core/contentkit_core/templates/devto.md.j2 b/src/pulsewriter_core/templates/devto.md.j2 similarity index 100% rename from packages/core/contentkit_core/templates/devto.md.j2 rename to src/pulsewriter_core/templates/devto.md.j2 diff --git a/packages/core/contentkit_core/templates/linkedin.md.j2 b/src/pulsewriter_core/templates/linkedin.md.j2 similarity index 100% rename from packages/core/contentkit_core/templates/linkedin.md.j2 rename to src/pulsewriter_core/templates/linkedin.md.j2 diff --git a/packages/core/contentkit_core/templates/x_thread.txt.j2 b/src/pulsewriter_core/templates/x_thread.txt.j2 similarity index 100% rename from packages/core/contentkit_core/templates/x_thread.txt.j2 rename to src/pulsewriter_core/templates/x_thread.txt.j2 diff --git a/packages/core/contentkit_core/transform.py b/src/pulsewriter_core/transform.py similarity index 100% rename from packages/core/contentkit_core/transform.py rename to src/pulsewriter_core/transform.py diff --git a/packages/tests/test_sanity.py b/tests/test_sanity.py similarity index 100% rename from packages/tests/test_sanity.py rename to tests/test_sanity.py