<h1 align="center">unit-text</h1>
<h3 align="center">Unit tests for plain text</h3>
<p align="center">
<a href="https://pypi.org/project/unit-text/">
<img alt="CI" src="https://img.shields.io/pypi/v/unit-text.svg?style=flat-round&logo=pypi&logoColor=white">
</a>
</p>
<div align="center">

</div>
---
Don't let LLMs write blog posts for you. Do your research, bring your own voice,
and use LLMs to criticise and iterate on your writing.
## 🤌 Why unit-text?
If you're a developer like us:
- You're probably aware you should write more (either because your leadership asks for it,
or because you'd like to be invited as a conference speaker, or <insert your own reason here>...)
- You don't know what to write about.
- You have considered letting ChatGPT write blog posts for you.
If you tried the last option (or read anything on the Internet in the past 2 years)
you would also know why it's not really that good of an idea.
Sure, you may get a perfectly good post, but it won't be your own.
`unit-text` applies the concept of unit tests to prose. You are the one writing, the LLM is just your critic.
First, you define a goal, the audience you have in mind,
and what you wanted them to do differently after they read your post.
Then, you start writing and iterating on your draft. `unit-text` gives you feedback: you run _tests_
to validate whether your draft is going in the right direction.
An AI copy editor, you could say.
## ⚙️ Installation
[We recommend](https://sealambda.com/blog/hygienic-python-in-2025) [uv](https://github.com/astral-sh/uv) to run the CLI.
```bash
# to run the CLI straight away
uvx unit-text --help
# or if you prefer to install it
uv tool install unit-text
```
You may of course also use `pip` to install the CLI - or `pipx` if you prefer to install it in an isolated environment.
```bash
pipx install unit-text
# ...or if you like to live on the edge
pip install unit-text
```
## 🔨 Usage
### Requirements
Either:
- [Ollama](https://ollama.com) must be running locally;
- `OLLAMA_HOST` should point to an Ollama server.
```bash
# To generate a blog idea
unit-text ideate
# To validate the working draft
unit-text test <path-to-the-draft.md>
```
## 📝 Process
The ideation phase is where you define your blog idea. It looks something like this:

Your idea is now stored in a `unit-text.json` file, in the current directory.
You may run `unit-text ideate` again at any time to finetune it.
Now you can start writing, let's say you're writing in a file called `draft.md`.
At any time, you can run `unit-text test draft.md` to validate it.
Initially, it may look something like this:

Keep iterating on your draft, based on feedback from `unit-text`, until it passes all tests:

## 💻 Contributing
If you want to contribute to the project, please read the [CONTRIBUTING.md](./CONTRIBUTING.md) file.
It contains information on how to set up your development environment, submit issues, and create pull requests.
## 📜 License
This project is licensed under the AGPLv3 License. See the [LICENSE](LICENSE) file for details.
Raw data
{
"_id": null,
"home_page": null,
"name": "unit-text",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "ai, blog, cli, editor, language, llm, ollama, test, unit",
"author": null,
"author_email": "Giorgio Azzinnaro <giorgio.azzinnaro@sealambda.com>, Sealambda <hello@sealambda.com>",
"download_url": "https://files.pythonhosted.org/packages/2c/44/ef8e8145b748c7569425f93684afcec280ae22fff82739389a26db31f795/unit_text-0.2.5.tar.gz",
"platform": null,
"description": "<h1 align=\"center\">unit-text</h1>\n<h3 align=\"center\">Unit tests for plain text</h3>\n\n<p align=\"center\">\n <a href=\"https://pypi.org/project/unit-text/\">\n <img alt=\"CI\" src=\"https://img.shields.io/pypi/v/unit-text.svg?style=flat-round&logo=pypi&logoColor=white\">\n </a>\n</p>\n\n<div align=\"center\">\n\n\n\n</div>\n\n---\n\nDon't let LLMs write blog posts for you. Do your research, bring your own voice,\nand use LLMs to criticise and iterate on your writing.\n\n## \ud83e\udd0c Why unit-text?\n\nIf you're a developer like us:\n\n- You're probably aware you should write more (either because your leadership asks for it,\n or because you'd like to be invited as a conference speaker, or <insert your own reason here>...)\n- You don't know what to write about.\n- You have considered letting ChatGPT write blog posts for you.\n\nIf you tried the last option (or read anything on the Internet in the past 2 years)\nyou would also know why it's not really that good of an idea.\n\nSure, you may get a perfectly good post, but it won't be your own.\n\n`unit-text` applies the concept of unit tests to prose. You are the one writing, the LLM is just your critic.\n\nFirst, you define a goal, the audience you have in mind,\nand what you wanted them to do differently after they read your post.\nThen, you start writing and iterating on your draft. `unit-text` gives you feedback: you run _tests_\nto validate whether your draft is going in the right direction.\n\nAn AI copy editor, you could say.\n\n## \u2699\ufe0f Installation\n\n[We recommend](https://sealambda.com/blog/hygienic-python-in-2025) [uv](https://github.com/astral-sh/uv) to run the CLI.\n\n```bash\n# to run the CLI straight away\nuvx unit-text --help\n\n# or if you prefer to install it\nuv tool install unit-text\n```\n\nYou may of course also use `pip` to install the CLI - or `pipx` if you prefer to install it in an isolated environment.\n\n```bash\npipx install unit-text\n\n# ...or if you like to live on the edge\npip install unit-text\n```\n\n## \ud83d\udd28 Usage\n\n### Requirements\n\nEither:\n\n- [Ollama](https://ollama.com) must be running locally;\n- `OLLAMA_HOST` should point to an Ollama server.\n\n```bash\n# To generate a blog idea\nunit-text ideate\n\n# To validate the working draft\nunit-text test <path-to-the-draft.md>\n```\n\n## \ud83d\udcdd Process\n\nThe ideation phase is where you define your blog idea. It looks something like this:\n\n\n\nYour idea is now stored in a `unit-text.json` file, in the current directory.\n\nYou may run `unit-text ideate` again at any time to finetune it.\n\nNow you can start writing, let's say you're writing in a file called `draft.md`.\n\nAt any time, you can run `unit-text test draft.md` to validate it.\nInitially, it may look something like this:\n\n\n\nKeep iterating on your draft, based on feedback from `unit-text`, until it passes all tests:\n\n\n\n## \ud83d\udcbb Contributing\n\nIf you want to contribute to the project, please read the [CONTRIBUTING.md](./CONTRIBUTING.md) file.\n\nIt contains information on how to set up your development environment, submit issues, and create pull requests.\n\n## \ud83d\udcdc License\n\nThis project is licensed under the AGPLv3 License. See the [LICENSE](LICENSE) file for details.\n",
"bugtrack_url": null,
"license": null,
"summary": "Unit tests for plain text",
"version": "0.2.5",
"project_urls": {
"issues": "https://github.com/sealambda/unit-text/issues",
"source": "https://github.com/sealambda/unit-text"
},
"split_keywords": [
"ai",
" blog",
" cli",
" editor",
" language",
" llm",
" ollama",
" test",
" unit"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "784ee94d91a0d71394a030baca5837c2b51c56bf677db6250166d618eed2ce08",
"md5": "0fd40b2349c9456884adeea561e10f19",
"sha256": "0a90aea9fd44c040af2ea9a5a3b4eb9bb8fa7ab702d5188b317989719e845139"
},
"downloads": -1,
"filename": "unit_text-0.2.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0fd40b2349c9456884adeea561e10f19",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 18289,
"upload_time": "2025-03-09T16:39:47",
"upload_time_iso_8601": "2025-03-09T16:39:47.128056Z",
"url": "https://files.pythonhosted.org/packages/78/4e/e94d91a0d71394a030baca5837c2b51c56bf677db6250166d618eed2ce08/unit_text-0.2.5-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "2c44ef8e8145b748c7569425f93684afcec280ae22fff82739389a26db31f795",
"md5": "8b467a68fe8fe325b4f74cc9806e15f3",
"sha256": "7579f61fcf7aab7c795afd830f832d60dfe203898a42d87fd613eea25058b802"
},
"downloads": -1,
"filename": "unit_text-0.2.5.tar.gz",
"has_sig": false,
"md5_digest": "8b467a68fe8fe325b4f74cc9806e15f3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 1708323,
"upload_time": "2025-03-09T16:39:49",
"upload_time_iso_8601": "2025-03-09T16:39:49.074556Z",
"url": "https://files.pythonhosted.org/packages/2c/44/ef8e8145b748c7569425f93684afcec280ae22fff82739389a26db31f795/unit_text-0.2.5.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-03-09 16:39:49",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "sealambda",
"github_project": "unit-text",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "unit-text"
}