Skip to content

Commit 944fe6b

Browse files
authored
Merge pull request #20 from NHagar/NHagar/add-cli
Add CLI with quickstart command
2 parents 23278f3 + 1e14636 commit 944fe6b

10 files changed

Lines changed: 1386 additions & 411 deletions

File tree

‎README.md‎

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,38 @@ This library provides Python interfaces for interacting with Substack's unoffici
1818
# Using pip
1919
pip install substack-api
2020

21-
# Using poetry
22-
poetry add substack-api
21+
# Using uv
22+
uv add substack-api
2323
```
2424

25-
## Usage Examples
25+
## Command-Line Interface
26+
27+
The library includes a CLI for quick access from the terminal. All commands output JSON by default.
28+
29+
```bash
30+
# Get the 5 newest posts from a newsletter
31+
substack newsletter posts https://example.substack.com --limit 5
32+
33+
# Search for posts
34+
substack newsletter search https://example.substack.com "machine learning"
35+
36+
# Get metadata for a specific post
37+
substack post metadata https://example.substack.com/p/my-post --pretty
38+
39+
# Look up a user's subscriptions
40+
substack user subscriptions username
41+
42+
# Browse categories
43+
substack categories
44+
substack category newsletters --name Technology
45+
46+
# Run the quickstart guide for a full command reference
47+
substack quickstart
48+
```
49+
50+
Use `--pretty` for human-readable output and `--cookies <path>` for authenticated access to paywalled content.
51+
52+
## Python Usage Examples
2653

2754
### Working with Newsletters
2855

‎docs/cli.md‎

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# Command-Line Interface
2+
3+
The `substack` CLI provides terminal access to Substack newsletters, posts, users, and categories. All commands output JSON by default.
4+
5+
## Global Options
6+
7+
| Option | Description |
8+
|--------|-------------|
9+
| `--pretty` | Pretty-print JSON output with indentation |
10+
| `--cookies PATH` | Path to a cookies JSON file for authenticated access to paywalled content |
11+
12+
## Newsletter Commands
13+
14+
### Get posts
15+
16+
```bash
17+
substack newsletter posts <url> [--sort new|top|pinned|community] [--limit N]
18+
```
19+
20+
Returns a list of post URLs from the newsletter.
21+
22+
```bash
23+
# Get the 5 newest posts
24+
substack newsletter posts https://example.substack.com --limit 5
25+
26+
# Get top posts
27+
substack newsletter posts https://example.substack.com --sort top --limit 10
28+
```
29+
30+
### Search posts
31+
32+
```bash
33+
substack newsletter search <url> <query> [--limit N]
34+
```
35+
36+
```bash
37+
substack newsletter search https://example.substack.com "machine learning" --limit 3
38+
```
39+
40+
### Get podcasts
41+
42+
```bash
43+
substack newsletter podcasts <url> [--limit N]
44+
```
45+
46+
### Get recommendations
47+
48+
```bash
49+
substack newsletter recs <url>
50+
```
51+
52+
Returns URLs of newsletters recommended by the given newsletter.
53+
54+
### Get authors
55+
56+
```bash
57+
substack newsletter authors <url>
58+
```
59+
60+
Returns usernames of the newsletter's authors.
61+
62+
## Post Commands
63+
64+
### Get metadata
65+
66+
```bash
67+
substack post metadata <url>
68+
```
69+
70+
Returns the full metadata dictionary for a post.
71+
72+
```bash
73+
substack post metadata https://example.substack.com/p/my-post --pretty
74+
```
75+
76+
### Get content
77+
78+
```bash
79+
substack post content <url>
80+
```
81+
82+
Returns the post URL and its HTML body content.
83+
84+
### Check paywall status
85+
86+
```bash
87+
substack post paywalled <url>
88+
```
89+
90+
Returns whether the post is paywalled.
91+
92+
## User Commands
93+
94+
### Get user info
95+
96+
```bash
97+
substack user info <username>
98+
```
99+
100+
Returns the full user profile data.
101+
102+
### Get subscriptions
103+
104+
```bash
105+
substack user subscriptions <username>
106+
```
107+
108+
Returns the list of newsletters the user is subscribed to.
109+
110+
## Category Commands
111+
112+
### List all categories
113+
114+
```bash
115+
substack categories
116+
```
117+
118+
Returns all available newsletter categories with their names and IDs.
119+
120+
### Get newsletters in a category
121+
122+
```bash
123+
substack category newsletters --name <name> [--metadata]
124+
substack category newsletters --id <id> [--metadata]
125+
```
126+
127+
Returns newsletter URLs in the category. Add `--metadata` to get full newsletter metadata instead.
128+
129+
```bash
130+
# By name
131+
substack category newsletters --name Technology
132+
133+
# By ID with full metadata
134+
substack category newsletters --id 42 --metadata --pretty
135+
```
136+
137+
## Other Commands
138+
139+
### Resolve a renamed handle
140+
141+
```bash
142+
substack resolve-handle <handle>
143+
```
144+
145+
Checks if a Substack user handle has been renamed and returns the new handle.
146+
147+
### Quickstart
148+
149+
```bash
150+
substack quickstart
151+
```
152+
153+
Prints a concise reference guide covering all CLI commands and options.
154+
155+
### Version
156+
157+
```bash
158+
substack version
159+
```
160+
161+
## Authentication
162+
163+
To access paywalled content from the CLI, pass `--cookies` before the command:
164+
165+
```bash
166+
substack --cookies cookies.json post content https://example.substack.com/p/paid-post
167+
substack --cookies cookies.json newsletter posts https://example.substack.com
168+
```
169+
170+
See the [Authentication Guide](authentication.md) for details on obtaining cookies.
171+
172+
## Notes
173+
174+
- API calls include a 2-second delay to be respectful to Substack's servers. Use `--limit` to avoid long waits on large newsletters.
175+
- All output is JSON. Pipe to `jq` for further processing, or use `--pretty` for readability.
176+
- The CLI can also be invoked as `python -m substack_api`.

‎docs/index.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ paywalled_content = authenticated_post.get_content()
4141

4242
## Features
4343

44-
- Simple, intuitive API
44+
- Simple, intuitive Python API
45+
- Command-line interface for quick terminal access
4546
- Comprehensive access to Substack data
4647
- Pagination support for large collections
4748
- Automatic caching to minimize API calls

‎docs/installation.md‎

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
## Requirements
44

5-
- Python 3.7 or higher
6-
- pip (Python package installer)
5+
- Python 3.12 or higher
6+
- pip or uv (Python package installer)
77

88
## Install from PyPI
99

@@ -30,3 +30,13 @@ The library has minimal dependencies:
3030

3131
These dependencies will be automatically installed when you install the package.
3232

33+
## CLI
34+
35+
Installing the package also installs the `substack` command-line tool:
36+
37+
```bash
38+
substack --help
39+
substack quickstart
40+
```
41+
42+
See the [CLI Guide](cli.md) for full documentation.

‎mkdocs.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ plugins:
5252
nav:
5353
- Home: index.md
5454
- Installation: installation.md
55+
- CLI: cli.md
5556
- User Guide: user-guide.md
5657
- Authentication: authentication.md
5758
- API Reference:

‎pyproject.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ dev = [
2222
"ruff>=0.9.9",
2323
]
2424

25+
[project.scripts]
26+
substack = "substack_api.cli:main"
27+
2528
[project.urls]
2629
"Homepage" = "https://github.com/nhagar/substack_api"
2730
"Bug Tracker" = "https://github.com/nhagar/substack_api/issues"

‎substack_api/__main__.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from substack_api.cli import main
2+
3+
main()

0 commit comments

Comments
 (0)