lekha-poth-cli 2.1.0__tar.gz → 2.2.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.
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/PKG-INFO +32 -6
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/README.md +31 -5
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/pyproject.toml +1 -1
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/scripts/generate_spec.py +12 -3
- lekha_poth_cli-2.2.0/skills/lp-cli/README.md +98 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/SKILL.md +109 -66
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/references/admin.md +50 -50
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/references/auth-account.md +28 -28
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/references/chats.md +6 -6
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/references/legacy.md +19 -19
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/references/library.md +29 -29
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/references/public-content.md +16 -16
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/references/vocab.md +10 -4
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/scripts/generate_references.py +56 -13
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/__init__.py +1 -1
- lekha_poth_cli-2.2.0/tests/test_contract_version_parity.py +34 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/.gitignore +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/scripts/generate_catalog_v2.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/skills/lp-cli/evals/evals.json +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/__main__.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/app.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/client.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/config.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/endpoints.json +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/errors.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/media.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/output.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/register.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/src/lekha_poth_cli/spec.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/tests/test_catalog_v2.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/tests/test_config.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/tests/test_coverage.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/tests/test_errors.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/tests/test_references_current.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/tests/test_spec_fields.py +0 -0
- {lekha_poth_cli-2.1.0 → lekha_poth_cli-2.2.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: lekha-poth-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Production Typer CLI covering every Lekha Poth HTTP API endpoint.
|
|
5
5
|
Author: Hermes Agent
|
|
6
6
|
License: MIT
|
|
@@ -26,14 +26,40 @@ Replaces the old stdlib `scripts/agent/lp.py` reader CLI.
|
|
|
26
26
|
|
|
27
27
|
## Install
|
|
28
28
|
|
|
29
|
+
Published on PyPI as [`lekha-poth-cli`](https://pypi.org/project/lekha-poth-cli/).
|
|
30
|
+
No checkout needed:
|
|
31
|
+
|
|
29
32
|
```bash
|
|
30
|
-
uv
|
|
31
|
-
uv
|
|
32
|
-
|
|
33
|
-
lp --help
|
|
33
|
+
uv tool install lekha-poth-cli # → $HOME/.local/bin/lp
|
|
34
|
+
uv tool upgrade lekha-poth-cli # later, to pick up new routes and flags
|
|
35
|
+
$HOME/.local/bin/lp --version
|
|
34
36
|
```
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
On macOS `/usr/bin/lp` is the print spooler and is on `PATH`, so call the
|
|
39
|
+
Lekha Poth CLI by its absolute path (`$HOME/.local/bin/lp`), or use the
|
|
40
|
+
alias entry point `lekha-poth`, which nothing else claims. To try it without
|
|
41
|
+
installing: `uvx --from lekha-poth-cli lp --help`.
|
|
42
|
+
|
|
43
|
+
An **agent skill** that teaches an LLM agent to drive this CLI ships in the
|
|
44
|
+
sdist under `skills/lp-cli/` (and in the repository at
|
|
45
|
+
`scripts/agent/lpcli/skills/lp-cli/`); its `README.md` says where to put it.
|
|
46
|
+
|
|
47
|
+
### Developing against a checkout
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cd scripts/agent/lpcli
|
|
51
|
+
uv venv .venv && uv pip install --python .venv/bin/python -e ".[dev]"
|
|
52
|
+
.venv/bin/python -m lekha_poth_cli --version
|
|
53
|
+
# or, as a tool that tracks the working tree: uv tool install -e .
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Releasing
|
|
57
|
+
|
|
58
|
+
**Actions → Release (lekha-poth-cli) → Run workflow** (`bump` minor by default,
|
|
59
|
+
or an exact `version`). It stamps every copy of the contract version
|
|
60
|
+
(`scripts/ci/stamp-lpcli-version.py`), runs the tests, `uv build`s, commits
|
|
61
|
+
and tags `lpcli-vX.Y.Z` on `main`, then `uv publish`es to PyPI. See
|
|
62
|
+
`docs/CICD.md` → "Releasing the agent CLI".
|
|
37
63
|
|
|
38
64
|
## Configure (once)
|
|
39
65
|
|
|
@@ -10,14 +10,40 @@ Replaces the old stdlib `scripts/agent/lp.py` reader CLI.
|
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
13
|
+
Published on PyPI as [`lekha-poth-cli`](https://pypi.org/project/lekha-poth-cli/).
|
|
14
|
+
No checkout needed:
|
|
15
|
+
|
|
13
16
|
```bash
|
|
14
|
-
uv
|
|
15
|
-
uv
|
|
16
|
-
|
|
17
|
-
lp --help
|
|
17
|
+
uv tool install lekha-poth-cli # → $HOME/.local/bin/lp
|
|
18
|
+
uv tool upgrade lekha-poth-cli # later, to pick up new routes and flags
|
|
19
|
+
$HOME/.local/bin/lp --version
|
|
18
20
|
```
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
On macOS `/usr/bin/lp` is the print spooler and is on `PATH`, so call the
|
|
23
|
+
Lekha Poth CLI by its absolute path (`$HOME/.local/bin/lp`), or use the
|
|
24
|
+
alias entry point `lekha-poth`, which nothing else claims. To try it without
|
|
25
|
+
installing: `uvx --from lekha-poth-cli lp --help`.
|
|
26
|
+
|
|
27
|
+
An **agent skill** that teaches an LLM agent to drive this CLI ships in the
|
|
28
|
+
sdist under `skills/lp-cli/` (and in the repository at
|
|
29
|
+
`scripts/agent/lpcli/skills/lp-cli/`); its `README.md` says where to put it.
|
|
30
|
+
|
|
31
|
+
### Developing against a checkout
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
cd scripts/agent/lpcli
|
|
35
|
+
uv venv .venv && uv pip install --python .venv/bin/python -e ".[dev]"
|
|
36
|
+
.venv/bin/python -m lekha_poth_cli --version
|
|
37
|
+
# or, as a tool that tracks the working tree: uv tool install -e .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Releasing
|
|
41
|
+
|
|
42
|
+
**Actions → Release (lekha-poth-cli) → Run workflow** (`bump` minor by default,
|
|
43
|
+
or an exact `version`). It stamps every copy of the contract version
|
|
44
|
+
(`scripts/ci/stamp-lpcli-version.py`), runs the tests, `uv build`s, commits
|
|
45
|
+
and tags `lpcli-vX.Y.Z` on `main`, then `uv publish`es to PyPI. See
|
|
46
|
+
`docs/CICD.md` → "Releasing the agent CLI".
|
|
21
47
|
|
|
22
48
|
## Configure (once)
|
|
23
49
|
|
|
@@ -55,6 +55,8 @@ import uuid as _uuid
|
|
|
55
55
|
from pathlib import Path
|
|
56
56
|
from typing import Any
|
|
57
57
|
|
|
58
|
+
from pydantic import AwareDatetime, FutureDatetime, NaiveDatetime, PastDatetime
|
|
59
|
+
|
|
58
60
|
REPO_ROOT = Path(__file__).resolve().parents[4]
|
|
59
61
|
OUT = REPO_ROOT / "scripts" / "agent" / "lpcli" / "src" / "lekha_poth_cli" / "endpoints.json"
|
|
60
62
|
API_V1_PREFIX = "/api/v1"
|
|
@@ -105,6 +107,15 @@ _SCALARS: dict[Any, str] = {
|
|
|
105
107
|
bool: "bool",
|
|
106
108
|
_uuid.UUID: "uuid",
|
|
107
109
|
_dt.datetime: "datetime",
|
|
110
|
+
# Pydantic's constrained datetimes are distinct classes at runtime, not
|
|
111
|
+
# `Annotated[datetime, ...]`, so nothing above would unwrap them and the
|
|
112
|
+
# field would degrade to `str`. `publishedAt` is `AwareDatetime` — the API
|
|
113
|
+
# refuses a timezone-less value — and the CLI must still call it a
|
|
114
|
+
# datetime.
|
|
115
|
+
AwareDatetime: "datetime",
|
|
116
|
+
NaiveDatetime: "datetime",
|
|
117
|
+
PastDatetime: "datetime",
|
|
118
|
+
FutureDatetime: "datetime",
|
|
108
119
|
_dt.date: "date",
|
|
109
120
|
}
|
|
110
121
|
|
|
@@ -145,9 +156,7 @@ def _walk_annotation(annotation: Any) -> list[Any]:
|
|
|
145
156
|
"""The annotation and every type/metadata object nested inside it."""
|
|
146
157
|
import typing
|
|
147
158
|
|
|
148
|
-
seen: list[Any] = [annotation]
|
|
149
|
-
for metadata in getattr(annotation, "__metadata__", ()):
|
|
150
|
-
seen.append(metadata)
|
|
159
|
+
seen: list[Any] = [annotation, *getattr(annotation, "__metadata__", ())]
|
|
151
160
|
for arg in typing.get_args(annotation):
|
|
152
161
|
seen.extend(_walk_annotation(arg))
|
|
153
162
|
return seen
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# lp-cli — an agent skill for the Lekha Poth CLI
|
|
2
|
+
|
|
3
|
+
This directory is a self-contained [agent skill](https://docs.claude.com/en/docs/agents-and-tools/agent-skills)
|
|
4
|
+
that teaches an LLM agent to operate [Lekha Poth](https://lekhapoth.com) through
|
|
5
|
+
`lp`, the full-coverage command-line client published on PyPI as
|
|
6
|
+
[`lekha-poth-cli`](https://pypi.org/project/lekha-poth-cli/).
|
|
7
|
+
|
|
8
|
+
You do **not** need the Lekha Poth source repository to use it. You need:
|
|
9
|
+
|
|
10
|
+
1. **`uv`** — `curl -LsSf https://astral.sh/uv/install.sh | sh` (macOS/Linux).
|
|
11
|
+
2. **The CLI** — `uv tool install lekha-poth-cli`, which puts `lp` at
|
|
12
|
+
`$HOME/.local/bin/lp`. Keep it current with `uv tool upgrade lekha-poth-cli`.
|
|
13
|
+
3. **This directory**, placed where your agent loads skills from.
|
|
14
|
+
|
|
15
|
+
## Installing the skill
|
|
16
|
+
|
|
17
|
+
Copy the whole `lp-cli/` directory (keep `SKILL.md`, `references/`, `scripts/`
|
|
18
|
+
together) into your agent's skills location:
|
|
19
|
+
|
|
20
|
+
| Agent | Where |
|
|
21
|
+
|---|---|
|
|
22
|
+
| Claude Code, for one user | `~/.claude/skills/lp-cli/` |
|
|
23
|
+
| Claude Code, for one project | `<project>/.claude/skills/lp-cli/` |
|
|
24
|
+
| Any other agent that reads `SKILL.md` frontmatter | its skills directory |
|
|
25
|
+
|
|
26
|
+
Or package it as a single file with the skill-creator's
|
|
27
|
+
`package_skill.py` and install the resulting `lp-cli.skill`.
|
|
28
|
+
|
|
29
|
+
The agent reads `SKILL.md` first. It holds the install and pre-flight steps,
|
|
30
|
+
task recipes, the exit-code table and the wire conventions, and routes to one
|
|
31
|
+
of the `references/*.md` files for a command's exact flags.
|
|
32
|
+
|
|
33
|
+
## Layout
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
lp-cli/
|
|
37
|
+
├── SKILL.md # entry point: pre-flight, recipes, conventions, errors
|
|
38
|
+
├── README.md # this file (for humans)
|
|
39
|
+
├── references/
|
|
40
|
+
│ ├── public-content.md # generated — items, collections, search, tags, sitemap, stats
|
|
41
|
+
│ ├── auth-account.md # generated — auth, /me, API keys
|
|
42
|
+
│ ├── library.md # generated — reader library + reports
|
|
43
|
+
│ ├── chats.md # generated — persona chat
|
|
44
|
+
│ ├── admin.md # generated — every /admin/* command
|
|
45
|
+
│ ├── legacy.md # generated — deprecated /chapters, /series aliases
|
|
46
|
+
│ └── vocab.md # hand-written — what each allowed value means
|
|
47
|
+
├── scripts/
|
|
48
|
+
│ └── generate_references.py # rebuilds references/*.md from the CLI's endpoints.json
|
|
49
|
+
└── evals/
|
|
50
|
+
└── evals.json # test prompts used to evaluate the skill
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Keeping the references in step with your CLI
|
|
54
|
+
|
|
55
|
+
The six generated reference files describe the CLI at contract **2.2.0**. If
|
|
56
|
+
`lp --version` reports something newer, rebuild them from the spec that ships
|
|
57
|
+
inside the installed package — no checkout required:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
uv run --no-project --with lekha-poth-cli python3 scripts/generate_references.py # rewrite
|
|
61
|
+
uv run --no-project --with lekha-poth-cli python3 scripts/generate_references.py --check # report only
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`SKILL.md` and `references/vocab.md` are hand-written and are not touched by
|
|
65
|
+
the script; where they and `lp <command> --help` disagree, `--help` is current.
|
|
66
|
+
|
|
67
|
+
## For maintainers (inside the Lekha Poth repository)
|
|
68
|
+
|
|
69
|
+
The skill lives at `scripts/agent/lpcli/skills/lp-cli/` and CI enforces that
|
|
70
|
+
it matches the API. After any backend route or parameter change, from the
|
|
71
|
+
repository root:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cd backend && uv run python ../scripts/agent/lpcli/scripts/generate_spec.py # endpoints.json (types, choices, sentinels)
|
|
75
|
+
cd .. && python3 scripts/agent/lpcli/scripts/generate_catalog_v2.py # docs/agent/API_CATALOG_V2.md
|
|
76
|
+
python3 scripts/agent/lpcli/skills/lp-cli/scripts/generate_references.py # references/*.md
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`backend/tests/unit/test_agent_spec_current.py` compares the spec with the
|
|
80
|
+
live app; `scripts/agent/lpcli/tests/test_references_current.py` and
|
|
81
|
+
`test_catalog_v2.py` check the two derived documents. When the skill is run
|
|
82
|
+
from inside the checkout, `generate_references.py` reads the repository's
|
|
83
|
+
`endpoints.json` rather than the installed package's, so the check is against
|
|
84
|
+
the code under review. Allowed values are derived from the backend's
|
|
85
|
+
`Literal` and `pattern=` validators, so a new vocabulary appears on its own.
|
|
86
|
+
What still needs a human:
|
|
87
|
+
|
|
88
|
+
- **Behaviour that isn't visible from the schema.** Record it in
|
|
89
|
+
`ENDPOINT_NOTES` / `FIELD_VOCAB_HINTS` in `generate_references.py`, only
|
|
90
|
+
after reading the backend code.
|
|
91
|
+
- **`references/vocab.md` and `SKILL.md`.** Every claim should name the
|
|
92
|
+
source file it was checked against.
|
|
93
|
+
- **A new route** needs an entry in `NEW_IDENTITY` in `generate_spec.py`; the
|
|
94
|
+
generator refuses to invent command names.
|
|
95
|
+
- **A CLI behaviour change** means bumping `lpcli`'s `__version__` together
|
|
96
|
+
with the contract version in `SKILL.md`'s title and §11, the repo's
|
|
97
|
+
`agent/SKILL.md` `version` / `cli_package`, and publishing the new version
|
|
98
|
+
to PyPI — a user who only has `uv tool upgrade` sees nothing until then.
|
|
@@ -1,45 +1,77 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: lp-cli
|
|
3
|
-
description: Use whenever a task involves `lp`,
|
|
3
|
+
description: 'Use whenever a task involves `lp`, the full-coverage CLI for Lekha Poth (lekhapoth.com, a Bangla serial-fiction platform), or anything that CLI does from a terminal, including installing or upgrading it (`uv tool install lekha-poth-cli`) and pointing it at an API with a personal API key. Covers publishing, editing, scheduling (future publish date) or previewing chapters; reordering a serial; marking a series completed; covers and media uploads; tag descriptions; content-rating (safe/adult) and language (bn/en) search filters; the reader library (favorites, watch-later, history, collections, follows, feed); auth, account and API keys; persona chat; admin reports, takedown and users; and calling any Lekha Poth HTTP endpoint. Also use when someone says "lp" or "lekha poth cli", pastes an `lp` error or exit code, or asks which flags a subcommand takes, even if they only describe the task ("schedule chapter 12 for Friday"). Needs only the CLI from PyPI, not the Lekha Poth repo. Not for editing Lekha Poth source.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# lp — Lekha Poth CLI (contract 2.
|
|
6
|
+
# lp — Lekha Poth CLI (contract 2.2.0)
|
|
7
7
|
|
|
8
|
-
`lp` is a Typer + Pydantic + httpx CLI
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
`lp` is a Typer + Pydantic + httpx CLI, published on PyPI as
|
|
9
|
+
`lekha-poth-cli`. Every HTTP route of the Lekha Poth API is a real subcommand
|
|
10
|
+
with real flags. The commands are generated from an `endpoints.json` that
|
|
11
|
+
ships inside the package and is derived from the live FastAPI app, so
|
|
11
12
|
`lp endpoints` is the authoritative list; do not trust a number written
|
|
12
13
|
anywhere else.
|
|
13
14
|
|
|
14
|
-
This
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
15
|
+
This skill is self-contained: it needs the CLI (installed in §0) and nothing
|
|
16
|
+
else — not the Lekha Poth source repository, which is private. Where a note
|
|
17
|
+
below names a backend file, that is the provenance of the claim, not
|
|
18
|
+
something to open.
|
|
19
|
+
|
|
20
|
+
This file is the map: install and pre-flight, task recipes, conventions, and
|
|
21
|
+
errors. The per-command details (every flag, type, default, allowed values,
|
|
22
|
+
and gotchas) are in `references/*.md`, generated from the same spec. **Before
|
|
23
|
+
running an unfamiliar write, read its reference entry.** For a command you
|
|
24
|
+
already know, `lp <group> <name> --help` is current and lists allowed values
|
|
25
|
+
as `(one of: …)`.
|
|
26
|
+
|
|
27
|
+
## 0. Install and pre-flight — do this before the first command
|
|
28
|
+
|
|
29
|
+
1. **Install (or upgrade) the CLI from PyPI with `uv`.** No repository
|
|
30
|
+
checkout is involved; the package carries everything, including the
|
|
31
|
+
endpoint spec the commands are built from.
|
|
32
|
+
```bash
|
|
33
|
+
uv tool install lekha-poth-cli # first time → $HOME/.local/bin/lp
|
|
34
|
+
uv tool upgrade lekha-poth-cli # later: pick up new routes and flags
|
|
35
|
+
$HOME/.local/bin/lp --version # confirm it answers
|
|
36
|
+
```
|
|
37
|
+
If `uv` itself is missing: `curl -LsSf https://astral.sh/uv/install.sh | sh`
|
|
38
|
+
(macOS/Linux), then open a new shell. To run once without installing
|
|
39
|
+
anything permanently, `uvx --from lekha-poth-cli lp …` works too.
|
|
40
|
+
2. **Use the right binary — always the absolute path.** On macOS,
|
|
41
|
+
`/usr/bin/lp` is the system *print spooler* and is on `PATH`, so a bare
|
|
42
|
+
`lp` can end up there; its reply is `lp: Error - unknown option`. Invoke
|
|
43
|
+
the Lekha Poth CLI as `$HOME/.local/bin/lp …` in every real command (the
|
|
44
|
+
examples below write `lp` for brevity). If that path does not exist, step
|
|
45
|
+
1 has not been done on this machine.
|
|
46
|
+
3. **Check the version:** `lp --version` should print `2.2.0` or newer. On an
|
|
47
|
+
older CLI, the exit codes and typed-flag behaviour in §5–§6 do not hold —
|
|
48
|
+
run `uv tool upgrade lekha-poth-cli`. If it prints something *newer* than
|
|
49
|
+
the contract version in this file's title, the CLI may have commands or
|
|
50
|
+
flags this skill does not describe yet; see §11.
|
|
51
|
+
4. **Point it at an API and a credential.** Nothing is compiled in: a fresh
|
|
52
|
+
install has an empty `api_base` and refuses every command with exit 2
|
|
53
|
+
until you set one.
|
|
54
|
+
```bash
|
|
55
|
+
lp config set --api-base https://api.lekhapoth.com/api/v1 \
|
|
56
|
+
--site-url https://lekhapoth.com --api-key lpak_…
|
|
57
|
+
```
|
|
58
|
+
That is the hosted production site. A self-hosted or local deploy uses its
|
|
59
|
+
own origin (the base must end in `/api/v1`, e.g.
|
|
60
|
+
`http://localhost:8000/api/v1`). A personal API key (`lpak_…`) is created
|
|
61
|
+
on the website under **Account → API keys** (needs a verified email; the
|
|
62
|
+
scopes offered are the ones the account holds) — or from the CLI with a
|
|
63
|
+
JWT session: `lp auth login`, store the tokens (§4), then
|
|
64
|
+
`lp keys create-api-key`. Anonymous reads (`items`, `collections`,
|
|
65
|
+
`search`, `tags`) work with no key at all.
|
|
66
|
+
5. **Know which API you are pointed at.** Run `lp config show` (secrets
|
|
35
67
|
masked) and `env | grep ^LEKHA_POTH_ | cut -d= -f1`. Environment variables
|
|
36
|
-
beat the config file (§3)
|
|
37
|
-
|
|
38
|
-
|
|
68
|
+
beat the config file (§3), and a config written earlier on this machine
|
|
69
|
+
may target **production**.
|
|
70
|
+
6. **Confirm connectivity and identity:** run `lp status`. It returns
|
|
39
71
|
health, readiness, and `/me` in one call, and reports an unreachable API
|
|
40
72
|
instead of failing. Then run `lp keys permissions` to see what the current
|
|
41
73
|
credential may actually do.
|
|
42
|
-
|
|
74
|
+
7. **Don't experiment against production.** Anything under `lp admin`,
|
|
43
75
|
`library`, `me`, `keys`, `chats` or `reports` that isn't a read changes real
|
|
44
76
|
data for real readers. To try a command, point it at a local API
|
|
45
77
|
(`lp --api-base http://localhost:8000/api/v1 …`), or ask first.
|
|
@@ -71,7 +103,10 @@ lp admin items update <slug> --status published --published-at 2026-10-02T12:00:
|
|
|
71
103
|
```
|
|
72
104
|
An item is live only when `status=published` **and** `publishedAt` ≤ now.
|
|
73
105
|
With a future date, the item stays hidden and appears at that time with no
|
|
74
|
-
further call.
|
|
106
|
+
further call. The value **must** include a UTC offset (`Z`, or `+06:00` for
|
|
107
|
+
Dhaka) — a timezone-less `2026-10-02T12:00:00` is a 422, not a guess, because
|
|
108
|
+
a timestamp resolved in the wrong zone lands in the future and hides the item
|
|
109
|
+
everywhere but `admin items list`.
|
|
75
110
|
Convert local times yourself: 18:00 in Dhaka is 12:00Z.
|
|
76
111
|
|
|
77
112
|
**Reorder a serial's chapters** (one call, not N updates)
|
|
@@ -112,6 +147,10 @@ relevance order.
|
|
|
112
147
|
**Edit a tag's description:**
|
|
113
148
|
`lp admin tags list`, then `lp admin tags update "<tag>" --description "…"`.
|
|
114
149
|
Omitting `--description` **clears** the description.
|
|
150
|
+
**Standing rule when publishing to Lekha Poth:** after publishing any item that introduces a tag,
|
|
151
|
+
list tags and PATCH a unique ~145–165 character Bangla SEO description for every
|
|
152
|
+
row with `description` null. Include the tag name, 18+, বাংলা চটি গল্প / চটি উপন্যাস /
|
|
153
|
+
পানু গল্প, plus tag-specific keywords. Use `--body-file` for Bangla. Never skip this.
|
|
115
154
|
|
|
116
155
|
**Reader library (signed-in key):**
|
|
117
156
|
- `lp library fav list`, `lp library watch list`, `lp library history list`
|
|
@@ -221,9 +260,9 @@ code you can branch on:
|
|
|
221
260
|
|
|
222
261
|
Branch on the exit code and on `ERROR_CODE`, never on the message wording.
|
|
223
262
|
Several conditions share one HTTP status. A 410 (`CONTENT_QUARANTINED`, a
|
|
224
|
-
taken-down item on a public read) exits 1.
|
|
225
|
-
`
|
|
226
|
-
`
|
|
263
|
+
taken-down item on a public read) exits 1. The mapping is
|
|
264
|
+
`lekha_poth_cli/errors.py` inside the installed package; the codes themselves
|
|
265
|
+
are the backend's `ErrorCode` enum.
|
|
227
266
|
|
|
228
267
|
## 7. PATCH semantics
|
|
229
268
|
|
|
@@ -235,10 +274,11 @@ exceptions:
|
|
|
235
274
|
- the sentinel fields in §2 clear with `null`;
|
|
236
275
|
- `admin tags update` clears the description when `--description` is omitted;
|
|
237
276
|
- `--attributes` and `--tag` replace the whole value you send;
|
|
238
|
-
- `publishedAt` can be moved but never nulled
|
|
277
|
+
- `publishedAt` can be moved but never nulled, and only to a value with a UTC
|
|
278
|
+
offset (`Z` / `+06:00`); a timezone-less timestamp is a 422.
|
|
239
279
|
|
|
240
|
-
|
|
241
|
-
`backend/src/app/services/admin_service.py
|
|
280
|
+
Verified against the backend's `AdminService.update_chapter`
|
|
281
|
+
(`backend/src/app/services/admin_service.py` in the Lekha Poth repository).
|
|
242
282
|
|
|
243
283
|
## 8. Built-in commands (not generated)
|
|
244
284
|
|
|
@@ -263,10 +303,13 @@ Source: `AdminService.update_chapter` in
|
|
|
263
303
|
|
|
264
304
|
## 9. Where every generated command is documented
|
|
265
305
|
|
|
266
|
-
Each file is generated by `scripts/generate_references.py
|
|
267
|
-
it lists the exact syntax, each path,
|
|
268
|
-
|
|
269
|
-
any command-specific notes checked
|
|
306
|
+
Each file is generated by `scripts/generate_references.py` from the CLI's
|
|
307
|
+
own `endpoints.json`. For every command it lists the exact syntax, each path,
|
|
308
|
+
query, header and body field with its type, required/optional status,
|
|
309
|
+
default, allowed values and wire name, and any command-specific notes checked
|
|
310
|
+
against the backend. The `Backend source: backend/src/app/…` footer under
|
|
311
|
+
each entry names the file that note was checked against in the (private)
|
|
312
|
+
Lekha Poth repository — provenance, not reading material.
|
|
270
313
|
|
|
271
314
|
| File | Covers |
|
|
272
315
|
|---|---|
|
|
@@ -313,28 +356,28 @@ text on `admin takedown`. `--sort` differs between `items list` and
|
|
|
313
356
|
|
|
314
357
|
## 11. Keeping this skill in sync
|
|
315
358
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
needs
|
|
331
|
-
|
|
332
|
-
-
|
|
333
|
-
`
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
359
|
+
The CLI moves with the API; this skill is a snapshot of it at contract
|
|
360
|
+
**2.2.0**. Three things can drift, and each has a check:
|
|
361
|
+
|
|
362
|
+
- **The CLI on this machine is behind the skill.** `lp --version` is older
|
|
363
|
+
than the title above → `uv tool upgrade lekha-poth-cli`. Flags this file
|
|
364
|
+
describes (`--published-at` scheduling, `--content-rating`, typed
|
|
365
|
+
`--attributes`, `null` sentinels, the exit codes) do not exist on 2.0.x.
|
|
366
|
+
- **The CLI is ahead of the skill.** `lp --version` is newer than the title
|
|
367
|
+
→ `lp endpoints` and `lp <cmd> --help` are the truth wherever they and a
|
|
368
|
+
reference file disagree. Rebuild the reference files from the installed
|
|
369
|
+
package so they match your CLI exactly:
|
|
370
|
+
```bash
|
|
371
|
+
uv run --no-project --with lekha-poth-cli python3 scripts/generate_references.py
|
|
372
|
+
```
|
|
373
|
+
The script reads `endpoints.json` out of the package (it needs no checkout;
|
|
374
|
+
`--check` reports staleness without writing). What it cannot refresh is the
|
|
375
|
+
hand-written prose — this file and `references/vocab.md` — so treat a value
|
|
376
|
+
that `--help` lists and `vocab.md` does not as real but unexplained.
|
|
377
|
+
- **The API is ahead of the CLI.** A value the API accepts but `--help` does
|
|
378
|
+
not list still works: the CLI shows choices but never enforces them (§2).
|
|
379
|
+
`lp api request` reaches any route that has no generated command yet.
|
|
380
|
+
|
|
381
|
+
Maintainers working inside the Lekha Poth repository regenerate
|
|
382
|
+
`endpoints.json` itself and the derived documents there; the procedure and
|
|
383
|
+
the CI checks that enforce it are in this skill's `README.md`.
|