pocketsync 0.10.0__py3-none-any.whl

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,106 @@
1
+ """``pocketsync whoami`` — the smallest identity probe.
2
+
3
+ Reports the agent's identity as declared in ``culture.yaml``: its nick
4
+ (``suffix``), the backend it runs on, and the served model (if any) — plus the
5
+ package version. Read-only; touches nothing but its own ``culture.yaml``.
6
+
7
+ When you clone this template, rename the package and update ``culture.yaml`` —
8
+ ``whoami`` then reflects your new agent's identity with no code change.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import argparse
14
+ from pathlib import Path
15
+
16
+ from pocketsync import __version__
17
+ from pocketsync.cli._output import emit_result
18
+
19
+ _FALLBACK_NICK = "pocketsync"
20
+
21
+
22
+ def find_culture_yaml() -> Path | None:
23
+ """Locate this agent's own ``culture.yaml`` by walking up from this module.
24
+
25
+ The identity must be the agent's own, not whatever ``culture.yaml`` happens
26
+ to sit in the caller's current working directory. In an editable / source
27
+ install, walking up from ``__file__`` finds the repo root; in a wheel
28
+ install no ``culture.yaml`` ships alongside the package and the caller falls
29
+ back to the literal defaults.
30
+ """
31
+ here = Path(__file__).resolve()
32
+ for parent in here.parents:
33
+ candidate = parent / "culture.yaml"
34
+ if candidate.is_file():
35
+ return candidate
36
+ return None
37
+
38
+
39
+ def read_agent_fields() -> dict[str, str]:
40
+ """Return ``suffix``/``backend``/``model`` from the first agent block.
41
+
42
+ Parsed without a YAML dependency to keep the runtime deps empty. Reads
43
+ top-level ``key: value`` lines within the first agent entry; anything
44
+ fancier than the documented shape falls back to the defaults below.
45
+ """
46
+ fields = {"nick": _FALLBACK_NICK, "backend": "unknown", "model": "unknown"}
47
+ cfg = find_culture_yaml()
48
+ if cfg is None:
49
+ return fields
50
+ try:
51
+ text = cfg.read_text(encoding="utf-8")
52
+ except OSError:
53
+ return fields
54
+ seen_agent = False
55
+ for line in text.splitlines():
56
+ stripped = line.strip()
57
+ if stripped.startswith(("- suffix:", "suffix:")):
58
+ if seen_agent: # second agent block — stop at the first
59
+ break
60
+ seen_agent = True
61
+ fields["nick"] = _scalar(stripped, "suffix")
62
+ elif seen_agent and stripped.startswith("backend:"):
63
+ fields["backend"] = _scalar(stripped, "backend")
64
+ elif seen_agent and stripped.startswith("model:"):
65
+ fields["model"] = _scalar(stripped, "model")
66
+ return fields
67
+
68
+
69
+ def _scalar(line: str, key: str) -> str:
70
+ """Extract the scalar after ``key:`` from a ``culture.yaml`` line."""
71
+ _, _, value = line.partition(f"{key}:")
72
+ return value.strip().strip("'\"") or "unknown"
73
+
74
+
75
+ def report() -> dict[str, object]:
76
+ fields = read_agent_fields()
77
+ return {
78
+ "nick": fields["nick"],
79
+ "version": __version__,
80
+ "backend": fields["backend"],
81
+ "model": fields["model"],
82
+ }
83
+
84
+
85
+ def cmd_whoami(args: argparse.Namespace) -> None:
86
+ identity = report()
87
+ json_mode = bool(getattr(args, "json", False))
88
+ if json_mode:
89
+ emit_result(identity, json_mode=True)
90
+ return
91
+ text = (
92
+ f"nick: {identity['nick']}\n"
93
+ f"version: {identity['version']}\n"
94
+ f"backend: {identity['backend']}\n"
95
+ f"model: {identity['model']}"
96
+ )
97
+ emit_result(text, json_mode=False)
98
+
99
+
100
+ def register(sub: argparse._SubParsersAction) -> None:
101
+ p = sub.add_parser(
102
+ "whoami",
103
+ help="Report this agent's nick, version, backend, and served model.",
104
+ )
105
+ p.add_argument("--json", action="store_true", help="Emit structured JSON.")
106
+ p.set_defaults(func=cmd_whoami)
@@ -0,0 +1,42 @@
1
+ """CliError and exit-code policy (stable-contract).
2
+
3
+ Every failure inside pocketsync raises :class:`CliError`. The
4
+ top-level ``main()`` catches it, formats via :mod:`pocketsync.cli._output`,
5
+ and exits with :attr:`CliError.code`. This guarantees:
6
+
7
+ * no Python traceback leaks to stderr (the agent-first error contract);
8
+ * every error has a structured shape ``{code, message, remediation}``;
9
+ * the exit-code policy is centralised in one place.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from dataclasses import dataclass
15
+
16
+ # Exit-code policy. Documented in ``pocketsync learn`` output.
17
+ # 0 = success
18
+ # 1 = user-input error (bad flag, missing required arg, unknown path)
19
+ # 2 = environment / setup error (tool not installed, file unreadable)
20
+ # 3+ = reserved for future categorisation
21
+ EXIT_SUCCESS = 0
22
+ EXIT_USER_ERROR = 1
23
+ EXIT_ENV_ERROR = 2
24
+
25
+
26
+ @dataclass
27
+ class CliError(Exception):
28
+ """Structured error raised within the CLI; carries a remediation hint for agents."""
29
+
30
+ code: int
31
+ message: str
32
+ remediation: str = ""
33
+
34
+ def __post_init__(self) -> None:
35
+ super().__init__(self.message)
36
+
37
+ def to_dict(self) -> dict[str, object]:
38
+ return {
39
+ "code": self.code,
40
+ "message": self.message,
41
+ "remediation": self.remediation,
42
+ }
@@ -0,0 +1,53 @@
1
+ """stdout / stderr helpers with a strict split (stable-contract).
2
+
3
+ Rule: **results go to stdout, diagnostics and errors go to stderr.** Agents
4
+ parsing output can rely on this invariant. JSON mode routes structured
5
+ payloads to the same streams — never mixes them.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import sys
12
+ from typing import Any, TextIO
13
+
14
+ from pocketsync.cli._errors import CliError
15
+
16
+
17
+ def emit_result(data: Any, *, json_mode: bool, stream: TextIO | None = None) -> None:
18
+ """Write a command result to stdout (or ``stream``)."""
19
+ s = stream if stream is not None else sys.stdout
20
+ if json_mode:
21
+ json.dump(data, s, ensure_ascii=False)
22
+ s.write("\n")
23
+ return
24
+ text = data if isinstance(data, str) else str(data)
25
+ s.write(text)
26
+ if not text.endswith("\n"):
27
+ s.write("\n")
28
+
29
+
30
+ def emit_error(err: CliError, *, json_mode: bool, stream: TextIO | None = None) -> None:
31
+ """Write a :class:`CliError` to stderr.
32
+
33
+ Text mode renders as two lines when a remediation is present::
34
+
35
+ error: <message>
36
+ hint: <remediation>
37
+
38
+ The ``hint:`` prefix is required by the agent-first error rubric.
39
+ """
40
+ s = stream if stream is not None else sys.stderr
41
+ if json_mode:
42
+ json.dump(err.to_dict(), s, ensure_ascii=False)
43
+ s.write("\n")
44
+ return
45
+ s.write(f"error: {err.message}\n")
46
+ if err.remediation:
47
+ s.write(f"hint: {err.remediation}\n")
48
+
49
+
50
+ def emit_diagnostic(message: str, *, stream: TextIO | None = None) -> None:
51
+ """Write a human diagnostic (progress, summary) to stderr."""
52
+ s = stream if stream is not None else sys.stderr
53
+ s.write(message if message.endswith("\n") else message + "\n")
@@ -0,0 +1,24 @@
1
+ """Explain catalog — markdown keyed by command-path tuples (stable-contract).
2
+
3
+ Every noun/verb registered in the CLI should have a catalog entry.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from pocketsync.cli._errors import EXIT_USER_ERROR, CliError
9
+ from pocketsync.explain.catalog import ENTRIES
10
+
11
+
12
+ def resolve(path: tuple[str, ...]) -> str:
13
+ if path in ENTRIES:
14
+ return ENTRIES[path]
15
+ display = " ".join(path) if path else "<root>"
16
+ raise CliError(
17
+ code=EXIT_USER_ERROR,
18
+ message=f"no explain entry for: {display}",
19
+ remediation="list entries with: pocketsync explain pocketsync",
20
+ )
21
+
22
+
23
+ def known_paths() -> list[tuple[str, ...]]:
24
+ return list(ENTRIES.keys())
@@ -0,0 +1,135 @@
1
+ """Markdown catalog for ``pocketsync explain <path>``.
2
+
3
+ Each entry is verbatim markdown. Keys are command-path tuples. The empty tuple
4
+ and ``("pocketsync",)`` both resolve to the root entry.
5
+
6
+ Keep bodies self-contained: an agent reading one entry should get enough
7
+ context without chaining reads.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ _ROOT = """\
13
+ # pocketsync
14
+
15
+ A clonable template for AgentCulture mesh agents. It carries an agent-first CLI
16
+ (cited from the teken `python-cli` reference), a mesh identity (`culture.yaml` +
17
+ `CLAUDE.md`), the canonical guildmaster skill kit under `.claude/skills/`, and a
18
+ buildable/deployable package baseline. Clone it, rename the package, edit
19
+ `culture.yaml`, and you have a new agent.
20
+
21
+ ## Verbs
22
+
23
+ - `pocketsync whoami` — identity probe from `culture.yaml`.
24
+ - `pocketsync learn` — structured self-teaching prompt.
25
+ - `pocketsync explain <path>` — markdown docs for any noun/verb.
26
+ - `pocketsync overview` — descriptive snapshot of the agent.
27
+ - `pocketsync doctor` — check the agent-identity invariants.
28
+ - `pocketsync cli overview` — describe the CLI surface.
29
+
30
+ ## Exit-code policy
31
+
32
+ - `0` success
33
+ - `1` user-input error
34
+ - `2` environment / setup error
35
+ - `3+` reserved
36
+
37
+ ## See also
38
+
39
+ - `pocketsync explain whoami`
40
+ - `pocketsync explain doctor`
41
+ """
42
+
43
+ _WHOAMI = """\
44
+ # pocketsync whoami
45
+
46
+ Reports the agent's identity from `culture.yaml`: nick (`suffix`), backend,
47
+ served model, and the package version. Read-only.
48
+
49
+ ## Usage
50
+
51
+ pocketsync whoami
52
+ pocketsync whoami --json
53
+ """
54
+
55
+ _LEARN = """\
56
+ # pocketsync learn
57
+
58
+ Prints a structured self-teaching prompt covering purpose, command map,
59
+ exit-code policy, `--json` support, and the `explain` pointer.
60
+
61
+ ## Usage
62
+
63
+ pocketsync learn
64
+ pocketsync learn --json
65
+ """
66
+
67
+ _EXPLAIN = """\
68
+ # pocketsync explain <path>
69
+
70
+ Prints markdown documentation for any noun/verb path. Unlike `--help` (terse,
71
+ positional), `explain` is global and addressable by path.
72
+
73
+ ## Usage
74
+
75
+ pocketsync explain pocketsync
76
+ pocketsync explain whoami
77
+ pocketsync explain --json <path>
78
+ """
79
+
80
+ _OVERVIEW = """\
81
+ # pocketsync overview
82
+
83
+ Read-only descriptive snapshot of the agent: identity (from `culture.yaml`), the
84
+ verb surface, and the sibling-pattern artifacts the template carries. Accepts an
85
+ ignored `target` so a stray path never hard-fails.
86
+
87
+ ## Usage
88
+
89
+ pocketsync overview
90
+ pocketsync overview --json
91
+ """
92
+
93
+ _DOCTOR = """\
94
+ # pocketsync doctor
95
+
96
+ Checks the agent-identity invariants `steward doctor` verifies:
97
+ prompt-file-present and backend-consistency (`claude` → `CLAUDE.md`), plus a
98
+ skills-present check. Exits 1 when unhealthy.
99
+
100
+ prompt-file-present requires the *resident* prompt the declared backend
101
+ actually reads. Other harness prompt files recognized under the same backend
102
+ name (`AGENTS.override.md`, `.pi/SYSTEM.md`, `QWEN.md`) belong to
103
+ interactively available harnesses the mesh daemon never loads; they are
104
+ reported by the informational harness-prompts check and never substituted.
105
+
106
+ ## Usage
107
+
108
+ pocketsync doctor
109
+ pocketsync doctor --json
110
+ """
111
+
112
+ _CLI = """\
113
+ # pocketsync cli
114
+
115
+ Noun group for CLI-surface introspection. `cli overview` describes the CLI
116
+ itself (distinct from the global `overview`, which describes the agent).
117
+
118
+ ## Usage
119
+
120
+ pocketsync cli overview
121
+ pocketsync cli overview --json
122
+ """
123
+
124
+
125
+ ENTRIES: dict[tuple[str, ...], str] = {
126
+ (): _ROOT,
127
+ ("pocketsync",): _ROOT,
128
+ ("whoami",): _WHOAMI,
129
+ ("learn",): _LEARN,
130
+ ("explain",): _EXPLAIN,
131
+ ("overview",): _OVERVIEW,
132
+ ("doctor",): _DOCTOR,
133
+ ("cli",): _CLI,
134
+ ("cli", "overview"): _CLI,
135
+ }
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.5
2
+ Name: pocketsync
3
+ Version: 0.10.0
4
+ Summary: Sync Pocket voice-recorder recordings, transcripts (STT) and summaries from the Pocket cloud to local disk or S3 - a durable landing zone that culture-rules workflows fan out to anywhere.
5
+ Project-URL: Homepage, https://github.com/agentculture/pocketsync
6
+ Project-URL: Issues, https://github.com/agentculture/pocketsync/issues
7
+ Author: AgentCulture
8
+ License-Expression: Apache-2.0
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Software Development
15
+ Requires-Python: >=3.12
16
+ Description-Content-Type: text/markdown
17
+
18
+ # pocketsync
19
+
20
+ Sync Pocket voice-recorder recordings, transcripts (STT) and summaries from the Pocket cloud to local disk or S3 - a durable landing zone that culture-rules workflows fan out to anywhere.
21
+
22
+ ## What you get
23
+
24
+ - **An agent-first CLI** cited from [teken](https://github.com/agentculture/teken)
25
+ (`afi-cli`) — the runtime package has no third-party dependencies.
26
+ - **A mesh identity** — `culture.yaml` (`suffix` + `backend`) and the matching
27
+ resident prompt file (`CLAUDE.md`, since this template runs
28
+ `backend: claude`). The mesh resident is one of **two separate
29
+ selections** over this clone — see
30
+ [Two selections, not one](#two-selections-not-one) below.
31
+ - **Four harness prompt files**, one per agent harness, each read by exactly
32
+ one of them (see [Prompt files by harness](#prompt-files-by-harness) below).
33
+ All four harnesses are usable interactively regardless of which one
34
+ `culture.yaml` names as the mesh resident.
35
+ - **The canonical guildmaster skill kit** (11 skills) under `.claude/skills/`,
36
+ vendored cite-don't-import. See [`docs/skill-sources.md`](docs/skill-sources.md).
37
+ - **A build + deploy baseline** — pytest, lint, the agent-first rubric gate, and
38
+ PyPI Trusted Publishing wired into GitHub Actions.
39
+
40
+ ## Prompt files by harness
41
+
42
+ Four harnesses, four root files, no shared base — each file is read by
43
+ exactly one harness:
44
+
45
+ | Harness | File(s) |
46
+ |---------|---------|
47
+ | Claude Code | [`CLAUDE.md`](CLAUDE.md) |
48
+ | Pi / associate | [`AGENTS.override.md`](AGENTS.override.md) + [`.pi/SYSTEM.md`](.pi/SYSTEM.md) |
49
+ | colleague | [`AGENTS.colleague.md`](AGENTS.colleague.md) |
50
+ | Qwen Code | [`QWEN.md`](QWEN.md) |
51
+
52
+ **Claude Code** — `CLAUDE.md` is the fullest write-up of the repo's
53
+ conventions; read it first.
54
+
55
+ **Pi / associate** — `AGENTS.override.md` replaces this directory's
56
+ `AGENTS.md`/`CLAUDE.md` in Pi's context layer, so Pi does not inherit
57
+ `CLAUDE.md`. `.pi/SYSTEM.md` replaces Pi's default system prompt with the
58
+ non-coding `associate` identity (read/find/summarize only).
59
+
60
+ **colleague** — colleague's prompt cascade is `AGENTS.md` →
61
+ `AGENTS.colleague.md` → `AGENTS.colleague.<model>.md`. This repo ships only
62
+ the middle layer: there is no `AGENTS.md` (a shared base across harnesses was
63
+ considered and rejected) and no per-model override file.
64
+
65
+ **Qwen Code** — Qwen Code reads `QWEN.md` and `AGENTS.md`; since there is no
66
+ `AGENTS.md`, `QWEN.md` is its sole source of guidance.
67
+
68
+ There is intentionally **no `AGENTS.md`** at the root — each harness gets an
69
+ unrelated file rather than cascading from a shared base.
70
+
71
+ ## Two selections, not one
72
+
73
+ It is tempting to read "switch harness" as one decision. It is actually two,
74
+ and this template exists partly to keep them separate:
75
+
76
+ 1. **The interactive harness** — which binary you run (`claude`, `pi`,
77
+ `colleague`, `qwen`). `cd` into the clone and run any of them; all four
78
+ are live simultaneously, and none of them requires editing a file or
79
+ flipping a switch. A harness can be force-selected for one invocation
80
+ (e.g. a CI smoke check) without ever touching `culture.yaml` — see
81
+ [`docs/automation-contract.md`](docs/automation-contract.md).
82
+ 2. **The mesh resident** — the single `backend` `culture.yaml` declares,
83
+ which is what the Culture daemon starts and what `steward doctor`
84
+ checks. `guild harness use <name>` changes only this.
85
+
86
+ `culture.yaml`'s `backend` affects (2) only. It never affects which harness
87
+ you can invoke interactively in (1). See
88
+ [`docs/harness-selection.md`](docs/harness-selection.md) for the full
89
+ writeup, including who reads this config and why existing siblings are not
90
+ retrofitted by this arc.
91
+
92
+ ## Quickstart
93
+
94
+ ```bash
95
+ uv sync
96
+ uv run pytest -n auto # run the test suite
97
+ uv run pocketsync whoami # identity from culture.yaml
98
+ uv run pocketsync learn # self-teaching prompt (add --json)
99
+ uv run teken cli doctor . --strict # the agent-first rubric gate CI runs
100
+ ```
101
+
102
+ ## CLI
103
+
104
+ | Verb | What it does |
105
+ |------|--------------|
106
+ | `whoami` | Report this agent's nick, version, backend, and model from `culture.yaml`. |
107
+ | `learn` | Print a structured self-teaching prompt. |
108
+ | `explain <path>` | Markdown docs for any noun/verb path. |
109
+ | `overview` | Read-only descriptive snapshot of the agent. |
110
+ | `doctor` | Check the agent-identity invariants (prompt-file-present, backend-consistency). |
111
+ | `cli overview` | Describe the CLI surface itself. |
112
+
113
+ Every command supports `--json`. Results go to stdout, errors/diagnostics to
114
+ stderr (never mixed). Exit codes: `0` success, `1` user error, `2` environment
115
+ error, `3+` reserved.
116
+
117
+ ## Make it your own
118
+
119
+ 1. Rename the package `pocketsync/` and the `pocketsync`
120
+ CLI/dist name throughout `pyproject.toml`, the package, `tests/`,
121
+ `sonar-project.properties`, and this `README.md`. The name is hard-coded in
122
+ ~100 places, so list every occurrence first — see the `git grep` discovery
123
+ command in [`CLAUDE.md`](CLAUDE.md), the authoritative rename procedure.
124
+ 2. Edit `culture.yaml` with your `suffix` and `backend`, and adjust its
125
+ `gate` section (below) to your project's setup and test commands.
126
+ 3. Rewrite `CLAUDE.md` for your agent and run `/init`. Rewrite the other three
127
+ harness files (`AGENTS.override.md` + `.pi/SYSTEM.md`, `AGENTS.colleague.md`,
128
+ `QWEN.md`) too if your agent uses those harnesses — don't let them drift out
129
+ of sync with `CLAUDE.md`.
130
+ 4. Re-vendor only the skills you need from guildmaster (see
131
+ [`docs/skill-sources.md`](docs/skill-sources.md)).
132
+
133
+ See [`CLAUDE.md`](CLAUDE.md) for the full conventions (version-bump-every-PR,
134
+ the `cicd` PR lane, deploy setup).
135
+
136
+ ## The `gate` section
137
+
138
+ `culture.yaml` may carry a top-level `gate` section that declares how to set
139
+ up and test this repo, so tooling (for example a PR-fixer that re-runs the
140
+ checks before pushing) needs no per-repo knowledge:
141
+
142
+ ```yaml
143
+ gate:
144
+ setup:
145
+ - [uv, sync]
146
+ test:
147
+ - [uv, run, pytest, -n, auto]
148
+ ```
149
+
150
+ `setup` and `test` are each a list of commands, and each command is an argv
151
+ list (never a shell string), run in order from the repo root. The values are
152
+ configuration only; no tool supplies a default. Culture's loader ignores
153
+ unknown top-level keys, so the section is safe alongside `agents`.
154
+
155
+ ## License
156
+
157
+ Apache 2.0 — see [`LICENSE`](LICENSE).
@@ -0,0 +1,19 @@
1
+ pocketsync/__init__.py,sha256=NYpSctaj8iph2EHMoZ0ugFQPLBqSxMdOm1f7pMEJNfw,402
2
+ pocketsync/__main__.py,sha256=yz078z6gJ4Tzm5IRPztoFfpLhTMJQeSIuhwa6A6sxDU,178
3
+ pocketsync/cli/__init__.py,sha256=MXQPXQOh2kPCzalYVNdcVKhsPElLonr6n5O-0uAfApo,4982
4
+ pocketsync/cli/_errors.py,sha256=z7XNf3wWDqb46ylPkDcg2z-LsYG79_EJ14o01ZgMO0c,1301
5
+ pocketsync/cli/_output.py,sha256=Zdi9g_CcoioC0uxC7bbzi8cJnL0m6dl8bMSz0fZv1VI,1709
6
+ pocketsync/cli/_commands/__init__.py,sha256=DqpfVkhBo7cj6eWOpSlwx1ag0nTbrYJkV8pnPgl2gyU,70
7
+ pocketsync/cli/_commands/cli.py,sha256=4t_M8Y-DTTw-cnMhfpkaqnHeJpnYCiIoXSsnetZQg74,1677
8
+ pocketsync/cli/_commands/doctor.py,sha256=0IOePf4PLmZQ0CNGai-3ZfpLM6wOR_rju38zxD_QwCs,7856
9
+ pocketsync/cli/_commands/explain.py,sha256=nmwS10b3Fu9J49nTDIqTH_16CAot-QczihepTwJZAOM,1227
10
+ pocketsync/cli/_commands/learn.py,sha256=NwcjMOOvXxk-WERbuxkYCVmEH9h94vfv82CQIBmsNsk,2999
11
+ pocketsync/cli/_commands/overview.py,sha256=joS7fQMQCD9P8ZZCZd_BX3YXIquHPKYORidiQ2JXypc,3961
12
+ pocketsync/cli/_commands/whoami.py,sha256=Xg9aZd9k4N0ayFlrQmOsrMLLs5DPhi9lo0NCdJeJgEE,3650
13
+ pocketsync/explain/__init__.py,sha256=sdFX0sX4tAOC9zjD81mOtokbdFtU0QXas_PlWZAbJFg,704
14
+ pocketsync/explain/catalog.py,sha256=kjkadO5QGAJgRzfXkBkCFrrzJgRfP_2GQ1-Zz2tDfUM,3559
15
+ pocketsync-0.10.0.dist-info/METADATA,sha256=DX6o_WIj-8wTyY93xrQEzLdo_2pfWLar43pJckAv1p8,7059
16
+ pocketsync-0.10.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
17
+ pocketsync-0.10.0.dist-info/entry_points.txt,sha256=YdBMQkHq7Rx7SC2nzdIYq6a8cNFRsv28DTQLTr4PGvk,51
18
+ pocketsync-0.10.0.dist-info/licenses/LICENSE,sha256=UTsio4-AMxNDoMcES3iMDOVbdrnTy1rQD7Be7zWjqcA,11340
19
+ pocketsync-0.10.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pocketsync = pocketsync.cli:main