tg-notes 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.
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "tg-notes-marketplace",
3
+ "owner": {
4
+ "name": "korkin25"
5
+ },
6
+ "description": "Marketplace for the tg-notes plugin — Telegram-backed notes → compiled reports.",
7
+ "plugins": [
8
+ {
9
+ "name": "tg-notes",
10
+ "source": "./",
11
+ "description": "Notes → compile → publish via a private Telegram group, under your own account.",
12
+ "version": "0.1.0",
13
+ "homepage": "https://github.com/korkin25/tg_notes",
14
+ "license": "GPL-3.0-or-later",
15
+ "keywords": ["telegram", "notes", "userbot", "reports", "cli"]
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "tg-notes",
3
+ "description": "Notes → compile → publish via a private Telegram group, posting under your own account. Bundles the tg-notes capture and compile-&-send skills, which drive the tg-notes CLI (install separately: pipx install tg-notes).",
4
+ "version": "0.1.0",
5
+ "author": {
6
+ "name": "korkin25",
7
+ "url": "https://github.com/korkin25"
8
+ },
9
+ "homepage": "https://github.com/korkin25/tg_notes",
10
+ "repository": "https://github.com/korkin25/tg_notes",
11
+ "license": "GPL-3.0-or-later",
12
+ "keywords": ["telegram", "notes", "userbot", "reports", "cli"]
13
+ }
@@ -0,0 +1,28 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ python-version: ["3.11", "3.12"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ - name: Install (with dev extras)
20
+ run: pip install -e .[dev]
21
+ - name: Lint (ruff)
22
+ run: ruff check .
23
+ - name: Test (pytest)
24
+ run: pytest -q
25
+ - name: Security scan (bandit)
26
+ run: bandit -r tg_notes
27
+ - name: Dependency audit (pip-audit)
28
+ run: pip-audit
@@ -0,0 +1,35 @@
1
+ name: Release
2
+
3
+ # Triggered by pushing a SemVer tag (vX.Y.Z). Builds the distribution and
4
+ # publishes it to PyPI via Trusted Publishing (OIDC) — no API token in secrets.
5
+ #
6
+ # ONE-TIME PyPI SETUP (before the first tag): on PyPI, add a Trusted Publisher for
7
+ # the project `tg-notes` bound to repo `korkin25/tg_notes`, workflow
8
+ # `release.yml`, environment `pypi`. Until that exists, the publish step fails by
9
+ # design. Publishing is deliberate — this runs only on a `v*` tag, which is cut
10
+ # only after the full suite is green on `main`.
11
+
12
+ on:
13
+ push:
14
+ tags:
15
+ - "v*"
16
+
17
+ jobs:
18
+ release:
19
+ runs-on: ubuntu-latest
20
+ environment: pypi
21
+ permissions:
22
+ id-token: write # OIDC token for PyPI Trusted Publishing
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: actions/setup-python@v5
26
+ with:
27
+ python-version: "3.12"
28
+ - name: Install build backend
29
+ run: pip install build
30
+ - name: Build distribution
31
+ run: python -m build
32
+ - name: Check distribution metadata
33
+ run: pipx run twine check dist/*
34
+ - name: Publish to PyPI
35
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,21 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+
9
+ # Virtualenvs
10
+ .venv/
11
+ venv/
12
+
13
+ # Secrets / auth — never commit
14
+ *.session
15
+ *.session-journal
16
+ .env
17
+ config.toml
18
+ config.json
19
+
20
+ # Claude Code personal (local) settings — never commit
21
+ .claude/settings.local.json
@@ -0,0 +1,20 @@
1
+ # AGENTS.md
2
+
3
+ This file is the standard entry point that AI coding agents look for.
4
+
5
+ **The canonical rules for this repository live in [CLAUDE.md](CLAUDE.md).** Read it
6
+ first: it defines the language rules, the documentation-sync policy, the security
7
+ conventions, and the autonomous development workflow (TDD, feature branches,
8
+ Conventional Commits, CI, releases). Everything in `CLAUDE.md` applies to every
9
+ agent working here, not only to Claude Code.
10
+
11
+ ## Cross-agent portability
12
+
13
+ This project follows the **Agent Skills** standard (<https://agentskills.io>) and its
14
+ `SKILL.md` format. Skills are authored once as plain `SKILL.md` files (standard core
15
+ frontmatter: `name`, `description`) so the same skill is read unchanged by any
16
+ Agent-Skills-compatible runtime — Claude Code, OpenCode, Hermes, and others — with no
17
+ per-agent rewrite. Only *distribution* differs per agent (plugin marketplace, `~/.claude/skills`
18
+ discovery, or a runtime's own skill store); the skill content stays portable.
19
+
20
+ For anything an agent needs to know or do in this repo, defer to `CLAUDE.md`.
@@ -0,0 +1,133 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
6
+ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-07-24
11
+
12
+ ### Added
13
+
14
+ - Project documentation and rules: `README.md`, `CLAUDE.md` (language and doc-sync
15
+ rules), `docs/architecture.md`, `docs/features.md`.
16
+ - Implementation plan in `TODO.md` (planning phase; no code yet).
17
+ - `GPL-3.0` license (`LICENSE`).
18
+ - Project scaffolding (TGN-1): `pyproject.toml` (CLI `tg-notes`, Telethon dependency,
19
+ editable-installable), `tg_notes` package, argparse command tree (`setup`, `note add`,
20
+ `notes list`, `contacts list/set/remove`, `send`, `notebooks list` — stubs so far),
21
+ local TOML config module (XDG path, `chmod 600`), and `.gitignore` for secrets and
22
+ `*.session`.
23
+ - Autonomous development-workflow rules in `CLAUDE.md` (TDD-first, feature branches,
24
+ Conventional Commits, tag-based SemVer releases, CI expectations, security bar),
25
+ replacing the previous minimal `Git` section.
26
+ - GitHub Actions workflows: CI (`.github/workflows/ci.yml`) running ruff, pytest
27
+ (Python 3.11 and 3.12), bandit, and pip-audit on every push and pull request; and
28
+ release (`.github/workflows/release.yml`) building and publishing to PyPI on `v*` tags.
29
+ - `dev` optional-dependency group in `pyproject.toml` (`pytest`, `pytest-mock`, `ruff`,
30
+ `bandit`, `pip-audit`, `build`).
31
+ - `AGENTS.md` pointing agents to `CLAUDE.md` as the canonical rules and documenting the
32
+ Agent Skills (`SKILL.md`) portability standard.
33
+ - Telegram client layer (TGN-2): `tg_notes/telegram.py` — a synchronous Telethon wrapper
34
+ (`import telethon.sync`) with `build_client` / `connect_authorized` / `whoami` / `login`
35
+ and typed `NotConfiguredError` / `NotAuthorizedError`. Sessions are locked to `chmod 600`
36
+ after login.
37
+ - CLI commands `login` (one-time interactive phone/code/2FA login, stores the session) and
38
+ `whoami` (prints the logged-in account identity as JSON); both report missing credentials
39
+ or an unauthorized session with a clear message and a nonzero exit.
40
+ - Test suite under `tests/` (pytest + pytest-mock): config round-trip / file mode / session
41
+ path, the Telegram layer with Telethon fully mocked (offline), and the CLI argument
42
+ surface. Pytest and ruff config added to `pyproject.toml`.
43
+ - Storage provisioning (TGN-3): `tg-notes setup` creates (or idempotently attaches to) the
44
+ private forum supergroup that stores notes. It ensures the `contacts` topic and a default
45
+ `daily` notebook topic (override with `--notebook`), pins a recovery marker in the group
46
+ so a lost store can be re-discovered, and persists the resolved group id to local config.
47
+ New `telegram.setup` plus helpers (`_resolve_or_create` / `_create_storage_group` /
48
+ `_ensure_topics` / `_pin_marker`) built on Telethon's forum raw API
49
+ (`CreateChannelRequest(megagroup=True, forum=True)`, `CreateForumTopicRequest`,
50
+ `GetForumTopicsRequest`); tests in `tests/test_setup.py` with Telethon fully mocked.
51
+ `setup` drives first-run onboarding itself: when `api_id`/`api_hash` are missing it
52
+ prompts for them and saves them to local config (mode 600); when the device is not
53
+ logged in it runs the interactive `login` (phone → code → 2FA) and retries the
54
+ provisioning. If the prompt is left blank (or the values are unusable) it falls back to
55
+ printing step-by-step manual guidance (my.telegram.org → config path → `chmod 600` →
56
+ `login` → re-run) and exits nonzero.
57
+ - Note capture (TGN-4): `tg-notes note add --notebook <nb> --text-file <f>` appends a note
58
+ to the notebook's forum topic, creating the topic on demand. Reads the note text from a
59
+ file or stdin (`--text-file -`), appends optional `--hashtag TAG` tokens (repeatable) on
60
+ a trailing line, refuses to post an empty note, and prints the posted note as JSON
61
+ (`notebook` / `topic_id` / `message_id` / `date`). New `telegram.note_add` (+ helpers
62
+ `_compose_note` / `_normalize_hashtag`) and a `NotSetUpError` that tells the user to run
63
+ `setup` first; tests in `tests/test_notes.py` with Telethon fully mocked.
64
+ - Note listing (TGN-5): `tg-notes notes list --notebook <nb> [--since <t>]` returns a
65
+ notebook's raw notes as a JSON array (oldest first), each `{message_id, date, text}`,
66
+ skipping the topic-opening service message. `--since` accepts `today`, `HH:MM`,
67
+ `YYYY-MM-DD`, or a full ISO datetime (interpreted as local time when it carries no
68
+ offset) and bounds the messages by date; an unknown notebook yields `[]`. New
69
+ `telegram.notes_list` and a CLI `_parse_since` parser; tests in `tests/test_notes.py`
70
+ and `tests/test_cli.py` (Telethon mocked).
71
+ - Contacts address book (TGN-6): `tg-notes contacts list|set|remove` over the
72
+ message-per-contact schema in the `contacts` topic. New pure `tg_notes.contacts` module
73
+ ((de)serializes the `#contact <key>` block; single-line fields, colons preserved) plus
74
+ `telegram.contacts_list` / `contacts_set` / `contacts_remove`. `set` creates or updates
75
+ in place (only the given fields override an existing record; a new contact requires
76
+ `--chat-id`; edits reuse the same message), `remove` deletes the contact's message
77
+ (missing key is a no-op), `list` returns all contacts as JSON sorted by key. Tests in
78
+ `tests/test_contacts.py` (pure + Telethon-mocked layer). Refactor: shared
79
+ `_resolve_store` helper (in `tg_notes.telegram`) and `_handle_store_errors` /
80
+ `_STORE_ERRORS` (in the CLI) deduplicate the not-set-up / not-configured / not-authorized
81
+ handling across `note add`, `notes list`, and `contacts`.
82
+ - Publish (TGN-7): `tg-notes send --contact <key> --text-file <f>` posts compiled text to a
83
+ contact's chat **as the user** — into a forum topic (`reply_to`) when the contact has a
84
+ `topic_id`, prepending the contact's `mention` on its own line when set. Text comes from
85
+ a file or stdin (`-`); `--dry-run` composes and prints the outgoing message (target,
86
+ topic, text) without sending. New `telegram.send` (+ `_compose_outgoing` /
87
+ `_target_from_chat_id`, resolving `chat_id` as `-100…` int or `@user` / `me`) and a
88
+ `ContactNotFoundError` (CLI exit 5); empty text is refused. Tests in `tests/test_send.py`
89
+ (Telethon mocked). This is the first command that posts outside the storage group.
90
+ - Notebook listing (TGN-8): `tg-notes notebooks list` returns the storage group's notebook
91
+ topics as JSON (`{name, topic_id}`, sorted), excluding the reserved `General` and
92
+ `contacts` topics. New `telegram.notebooks_list` and `RESERVED_TOPICS`; tests in
93
+ `tests/test_notebooks.py`. Completes **Phase 1 (CLI core)** — all deterministic Telegram
94
+ commands are implemented and verified end-to-end. Removed the leftover `_todo` stub
95
+ handler now that no command is a stub.
96
+ - Capture skill (TGN-9): `skills/tg-notes/SKILL.md` — a portable Agent Skill (standard
97
+ `name`/`description` frontmatter) that captures a work note into the Telegram-backed
98
+ store by shelling out to `tg-notes note add`. Two modes: verbatim (user dictates) and
99
+ session summary (composed from real facts — git commits since 00:00, changed files,
100
+ tickets — never invented), 2–6 concise bullets in the user's language, default `daily`
101
+ notebook, optional hashtags. Capture only — it never sends. Verified end-to-end against
102
+ the real account (both modes filed and read back). Succeeds the retired local `report`
103
+ skill, now Telegram-native.
104
+ - Compile & send skill (TGN-10): `skills/tg-notes-send/SKILL.md` — reads notes
105
+ (`tg-notes notes list`), rewrites them per the target contact's `style`, previews with
106
+ `tg-notes send --dry-run`, **always shows a draft and requires an explicit confirmation**
107
+ (the message goes out under the user's own account), then `tg-notes send`. Contacts are
108
+ the single source of chat/topic/mention/style. Verified end-to-end against the real
109
+ account (dry-run → confirmed send to Saved Messages → read back; unknown-contact exit 5).
110
+ Succeeds the retired local `report-send` skill, now driven by the `tg-notes` CLI.
111
+ - Daily-report preset (TGN-11): a first-class section of `skills/tg-notes-send/SKILL.md`
112
+ (`/tg-report`, "отправь дневной отчёт") — the compile & send flow with fixed defaults
113
+ (notebook `daily`, `--since today`), one confirmed send per recipient. Completes
114
+ **Phase 2 (the Claude Code Skill)**: capture (`tg-notes`) + compile & send / daily report
115
+ (`tg-notes-send`), the Telegram-native successor to the old `report`/`report-send` pair.
116
+ - Claude Code plugin packaging (TGN-13): `.claude-plugin/plugin.json` — plugin manifest
117
+ (`name: tg-notes`, version, author, GPL-3.0-or-later) that bundles the two skills
118
+ (auto-discovered from `skills/`). Passes `claude plugin validate . --strict`.
119
+ - Git plugin marketplace (TGN-14): `.claude-plugin/marketplace.json` — single-plugin
120
+ marketplace (`tg-notes-marketplace`) with `source: "./"` (plugin is the repo root).
121
+ Install: `/plugin marketplace add korkin25/tg_notes` then
122
+ `/plugin install tg-notes@tg-notes-marketplace`. The bundled skills drive the `tg-notes`
123
+ CLI, installed separately with `pipx install tg-notes`.
124
+
125
+ ### Changed
126
+
127
+ - Single-source the package version: `pyproject.toml` reads it from
128
+ `tg_notes/__init__.py` (`[tool.hatch.version]`, `dynamic = ["version"]`) so it can no
129
+ longer drift between the two. Bumped to `0.1.0` for the first release.
130
+ - Release workflow (`.github/workflows/release.yml`) now publishes to PyPI via **Trusted
131
+ Publishing** (OIDC, `id-token: write`, `pypi` environment) instead of a stored API
132
+ token, and runs `twine check` on the built artifacts. Publishing still triggers only on
133
+ a `v*` tag; it needs a one-time PyPI Trusted Publisher bound to `korkin25/tg_notes`.
@@ -0,0 +1,64 @@
1
+ # CLAUDE.md
2
+
3
+ Guidance for Claude Code (and other AI agents) working in this repository.
4
+
5
+ ## What this project is
6
+
7
+ `tg_notes` — a general-purpose **notes → compile → publish** tool that uses a private
8
+ Telegram forum group as its store and posts under the user's own account (userbot).
9
+ Daily work reports are one preset built on top of it.
10
+
11
+ Architecture in one line: a standalone Python CLI (`tg-notes`, Telethon/MTProto) does
12
+ all Telegram I/O; thin per-agent Skill wrappers (Claude Code first) add the
13
+ intelligence (composing notes, compiling them per recipient). See
14
+ [docs/architecture.md](docs/architecture.md).
15
+
16
+ Status: **planning** — no implementation yet. The plan lives in [TODO.md](TODO.md).
17
+
18
+ ## Language rules (STRICT)
19
+
20
+ - **All repository content is English** — code, identifiers, comments, docstrings,
21
+ commit messages, and every document (README, `docs/`, CHANGELOG, TODO, this file).
22
+ No exceptions.
23
+ - **Conversation with the user is always Russian** — reply in Russian regardless of
24
+ the language they wrote in. This applies only to the live chat, never to anything
25
+ written into the repo.
26
+
27
+ ## Documentation sync (apply without being asked)
28
+
29
+ Keep docs in lockstep with the code, **in the same change**:
30
+
31
+ | What changed | Update |
32
+ |---|---|
33
+ | New or changed feature / behavior | `docs/features.md` + `README.md` |
34
+ | CLI surface (commands, flags) | `README.md` (usage) + `docs/architecture.md` |
35
+ | Architecture, storage schema, data flow, security model | `docs/architecture.md` |
36
+ | Any user-visible change | `CHANGELOG.md` under `## [Unreleased]` |
37
+ | Task started / finished / blocked | `TODO.md` status |
38
+
39
+ - `CHANGELOG.md` follows [Keep a Changelog](https://keepachangelog.com/) + SemVer.
40
+ - `TODO.md` holds only open/in-progress work; when a task is done and verified, move
41
+ it out of `TODO.md` into `CHANGELOG.md`.
42
+ - Never mark a task done without confirmation that it actually works.
43
+
44
+ ## Conventions
45
+
46
+ - **Secrets never leave the machine.** `api_id`/`api_hash`, the Telethon `*.session`
47
+ file, and local config are git-ignored. **Notes and contacts live only in Telegram.**
48
+ - The session file grants full account access: `chmod 600`, never committed.
49
+ - Userbot automation is a Telegram-ToS gray area; the tool only publishes the user's
50
+ own notes/reports and must stay non-spammy.
51
+
52
+ ## Development workflow (autonomous — apply without being asked)
53
+
54
+ This project is developed by an AI agent under continuous, autonomous iteration.
55
+
56
+ - Test-driven: for every agreed feature write the tests FIRST (they must fail), then implement until green. No feature code without a test.
57
+ - Feature branches: work on feature/<task-id>-<slug> off main; merge to main only when the full suite is green.
58
+ - Commit periodically in small logical units, Conventional Commits (feat:, fix:, test:, docs:, chore:, ci:). Never add a Co-Authored-By trailer. Push to `origin` after every commit.
59
+ - Releases only after green tests: tag vX.Y.Z (SemVer) after the full suite passes on main. Publishing to PyPI or marketplaces is a separate, later, explicit step.
60
+ - CI on every push (GitHub Actions): ruff lint, pytest (3.11 and 3.12), security scan (bandit + pip-audit). A tag triggers the build/release job.
61
+ - Security first: no secrets in git; least privilege; treat the Telethon session / bot token as full-access credentials.
62
+ - High bar: type hints, docstrings, ruff-clean, meaningful tests. Work like a top-tier engineer + DevOps.
63
+ - Auto-logging: started/ongoing work goes to TODO.md (Current state + phase tables); completed and verified work moves to CHANGELOG.md, in the same change. Never mark a task done without a passing test.
64
+ - Cold-start: keep the top of TODO.md a "Current state / next action" block so a fresh session knows exactly what to do next.