pesa-cli 1.0.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.
pesa_cli-1.0.0/LICENSE ADDED
@@ -0,0 +1,3 @@
1
+ Creative Commons Attribution-NonCommercial-NoDerivatives 4.0
2
+ Copyright (c) 2026 Gabriel Mahia <contact@aikungfu.dev>
3
+ https://creativecommons.org/licenses/by-nc-nd/4.0/
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.4
2
+ Name: pesa-cli
3
+ Version: 1.0.0
4
+ Summary: Command-line tool for M-Pesa Daraja v3 — STK Push, B2C, balance, config management.
5
+ Author-email: Gabriel Mahia <contact@aikungfu.dev>
6
+ License: CC-BY-NC-ND-4.0
7
+ Project-URL: Homepage, https://github.com/gabrielmahia/pesa-cli
8
+ Keywords: mpesa,safaricom,daraja,cli,kenya,fintech,python,typer
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: typer>=0.12
20
+ Requires-Dist: requests>=2.28
21
+ Requires-Dist: rich>=13
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7; extra == "dev"
24
+ Requires-Dist: ruff; extra == "dev"
25
+ Dynamic: license-file
26
+
27
+ # pesa-cli
28
+
29
+ **Command-line tool for M-Pesa Daraja v3 — STK Push, B2C, balance check, config management.**
30
+
31
+ [![CI](https://github.com/gabrielmahia/pesa-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/gabrielmahia/pesa-cli/actions)
32
+ [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](#)
33
+ [![Tests](https://img.shields.io/badge/tests-34%20passing-brightgreen)](#)
34
+ [![License](https://img.shields.io/badge/License-CC%20BY--NC--ND%204.0-lightgrey)](LICENSE)
35
+
36
+ Test integrations, trigger payments, and check balances from your terminal —
37
+ without opening the Safaricom portal or writing a script.
38
+
39
+ ---
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pip install pesa-cli
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Setup
50
+
51
+ ```bash
52
+ # Set credentials once — stored in ~/.pesa/config.json (mode 600)
53
+ pesa config set --key consumer-key --value YOUR_CONSUMER_KEY
54
+ pesa config set --key consumer-secret --value YOUR_CONSUMER_SECRET
55
+ pesa config set --key shortcode --value 174379
56
+ pesa config set --key passkey --value YOUR_PASSKEY
57
+ pesa config set --key environment --value sandbox # or production
58
+
59
+ # Or use environment variables (useful in CI/CD)
60
+ export DARAJA_CONSUMER_KEY=...
61
+ export DARAJA_CONSUMER_SECRET=...
62
+
63
+ # Test credentials
64
+ pesa auth
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Commands
70
+
71
+ ### `pesa auth`
72
+ Test credentials and verify connectivity.
73
+ ```
74
+ ✓ Authenticated
75
+ Environment: sandbox
76
+ Token: mock_token_ab...3456
77
+ Expires in: ~60 minutes
78
+ ```
79
+
80
+ ### `pesa stk push PHONE AMOUNT`
81
+ Initiate an STK Push payment request. The customer receives a PIN prompt on their phone.
82
+ ```bash
83
+ pesa stk push 0712345678 500
84
+ pesa stk push 0712345678 500 --ref "Invoice001" --desc "Monthly contribution"
85
+ ```
86
+ ```
87
+ ✓ STK Push sent
88
+ Phone: +254712345678
89
+ Amount: KES 500
90
+ Reference: Invoice001
91
+ Checkout ID: ws_CO_150120241430221234567890
92
+
93
+ Run: pesa stk query ws_CO_150120241430221234567890
94
+ ```
95
+
96
+ ### `pesa stk query CHECKOUT_ID`
97
+ Poll the status of an STK Push.
98
+ ```bash
99
+ pesa stk query ws_CO_150120241430221234567890
100
+ ```
101
+ ```
102
+ ✓ The service request is processed successfully.
103
+ Result Code: 0
104
+ ```
105
+
106
+ ### `pesa b2c PHONE AMOUNT`
107
+ Send money from your shortcode to a phone number.
108
+ ```bash
109
+ pesa b2c 0712345678 1000 --remarks "Chama disbursement"
110
+ ```
111
+
112
+ ### `pesa balance`
113
+ Request account balance (result posted to your ResultURL asynchronously).
114
+ ```bash
115
+ pesa balance
116
+ ```
117
+
118
+ ### `pesa config show`
119
+ Display current configuration with secrets masked.
120
+ ```
121
+ ┌──────────────────────────────────────────────────┐
122
+ │ pesa configuration │
123
+ ├──────────────────┬─────────────┬─────────────────┤
124
+ │ consumer_key │ config file │ ************3456 │
125
+ │ consumer_secret │ config file │ ************abcd │
126
+ │ shortcode │ config file │ 174379 │
127
+ │ environment │ config file │ sandbox │
128
+ └──────────────────┴─────────────┴─────────────────┘
129
+ ```
130
+
131
+ ---
132
+
133
+ ## Credentials
134
+
135
+ Credentials are resolved in this order: **environment variable** → **config file**.
136
+
137
+ | Credential | Config key | Environment variable |
138
+ |------------|-----------|----------------------|
139
+ | Consumer Key | `consumer_key` | `DARAJA_CONSUMER_KEY` |
140
+ | Consumer Secret | `consumer_secret` | `DARAJA_CONSUMER_SECRET` |
141
+ | Shortcode | `shortcode` | `DARAJA_SHORTCODE` |
142
+ | Passkey | `passkey` | `DARAJA_PASSKEY` |
143
+ | Initiator Name | `initiator_name` | `DARAJA_INITIATOR_NAME` |
144
+ | Security Credential | `security_credential` | `DARAJA_SECURITY_CREDENTIAL` |
145
+ | Environment | `environment` | `DARAJA_ENVIRONMENT` |
146
+
147
+ Config file is stored at `~/.pesa/config.json` with mode 600 (owner read/write only).
148
+ Override location with `PESA_CONFIG=/path/to/config.json`.
149
+
150
+ ---
151
+
152
+ ## Use with daraja-mock
153
+
154
+ ```bash
155
+ # Start daraja-mock
156
+ python -m daraja_mock --port 8765
157
+
158
+ # Point pesa-cli at the mock
159
+ export PESA_BASE_URL=http://localhost:8765
160
+ pesa auth
161
+ pesa stk push 0712345678 100 --ref "Test"
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Design decisions
167
+
168
+ **Credentials resolved env → file.** CI/CD environments should use env vars.
169
+ Developer machines use the config file. The CLI never asks for credentials
170
+ interactively — that would break scripting.
171
+
172
+ **Secrets masked at 600.** The config file is created with `chmod 600` so
173
+ other users on shared systems cannot read Daraja credentials.
174
+
175
+ **AccountReference truncated silently.** Daraja rejects `AccountReference` > 12 chars
176
+ with a cryptic error. The CLI truncates to 12 and shows what was sent.
177
+
178
+ **Rich output, not JSON by default.** For human use. Add `--output json` flag
179
+ if scripting against pesa-cli output is needed.
180
+
181
+ ---
182
+
183
+ *Part of the [nairobi-stack](https://github.com/gabrielmahia/nairobi-stack) East Africa engineering ecosystem.*
184
+ *Maintained by [Gabriel Mahia](https://github.com/gabrielmahia). Kenya × USA.*
@@ -0,0 +1,158 @@
1
+ # pesa-cli
2
+
3
+ **Command-line tool for M-Pesa Daraja v3 — STK Push, B2C, balance check, config management.**
4
+
5
+ [![CI](https://github.com/gabrielmahia/pesa-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/gabrielmahia/pesa-cli/actions)
6
+ [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](#)
7
+ [![Tests](https://img.shields.io/badge/tests-34%20passing-brightgreen)](#)
8
+ [![License](https://img.shields.io/badge/License-CC%20BY--NC--ND%204.0-lightgrey)](LICENSE)
9
+
10
+ Test integrations, trigger payments, and check balances from your terminal —
11
+ without opening the Safaricom portal or writing a script.
12
+
13
+ ---
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pip install pesa-cli
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Setup
24
+
25
+ ```bash
26
+ # Set credentials once — stored in ~/.pesa/config.json (mode 600)
27
+ pesa config set --key consumer-key --value YOUR_CONSUMER_KEY
28
+ pesa config set --key consumer-secret --value YOUR_CONSUMER_SECRET
29
+ pesa config set --key shortcode --value 174379
30
+ pesa config set --key passkey --value YOUR_PASSKEY
31
+ pesa config set --key environment --value sandbox # or production
32
+
33
+ # Or use environment variables (useful in CI/CD)
34
+ export DARAJA_CONSUMER_KEY=...
35
+ export DARAJA_CONSUMER_SECRET=...
36
+
37
+ # Test credentials
38
+ pesa auth
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Commands
44
+
45
+ ### `pesa auth`
46
+ Test credentials and verify connectivity.
47
+ ```
48
+ ✓ Authenticated
49
+ Environment: sandbox
50
+ Token: mock_token_ab...3456
51
+ Expires in: ~60 minutes
52
+ ```
53
+
54
+ ### `pesa stk push PHONE AMOUNT`
55
+ Initiate an STK Push payment request. The customer receives a PIN prompt on their phone.
56
+ ```bash
57
+ pesa stk push 0712345678 500
58
+ pesa stk push 0712345678 500 --ref "Invoice001" --desc "Monthly contribution"
59
+ ```
60
+ ```
61
+ ✓ STK Push sent
62
+ Phone: +254712345678
63
+ Amount: KES 500
64
+ Reference: Invoice001
65
+ Checkout ID: ws_CO_150120241430221234567890
66
+
67
+ Run: pesa stk query ws_CO_150120241430221234567890
68
+ ```
69
+
70
+ ### `pesa stk query CHECKOUT_ID`
71
+ Poll the status of an STK Push.
72
+ ```bash
73
+ pesa stk query ws_CO_150120241430221234567890
74
+ ```
75
+ ```
76
+ ✓ The service request is processed successfully.
77
+ Result Code: 0
78
+ ```
79
+
80
+ ### `pesa b2c PHONE AMOUNT`
81
+ Send money from your shortcode to a phone number.
82
+ ```bash
83
+ pesa b2c 0712345678 1000 --remarks "Chama disbursement"
84
+ ```
85
+
86
+ ### `pesa balance`
87
+ Request account balance (result posted to your ResultURL asynchronously).
88
+ ```bash
89
+ pesa balance
90
+ ```
91
+
92
+ ### `pesa config show`
93
+ Display current configuration with secrets masked.
94
+ ```
95
+ ┌──────────────────────────────────────────────────┐
96
+ │ pesa configuration │
97
+ ├──────────────────┬─────────────┬─────────────────┤
98
+ │ consumer_key │ config file │ ************3456 │
99
+ │ consumer_secret │ config file │ ************abcd │
100
+ │ shortcode │ config file │ 174379 │
101
+ │ environment │ config file │ sandbox │
102
+ └──────────────────┴─────────────┴─────────────────┘
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Credentials
108
+
109
+ Credentials are resolved in this order: **environment variable** → **config file**.
110
+
111
+ | Credential | Config key | Environment variable |
112
+ |------------|-----------|----------------------|
113
+ | Consumer Key | `consumer_key` | `DARAJA_CONSUMER_KEY` |
114
+ | Consumer Secret | `consumer_secret` | `DARAJA_CONSUMER_SECRET` |
115
+ | Shortcode | `shortcode` | `DARAJA_SHORTCODE` |
116
+ | Passkey | `passkey` | `DARAJA_PASSKEY` |
117
+ | Initiator Name | `initiator_name` | `DARAJA_INITIATOR_NAME` |
118
+ | Security Credential | `security_credential` | `DARAJA_SECURITY_CREDENTIAL` |
119
+ | Environment | `environment` | `DARAJA_ENVIRONMENT` |
120
+
121
+ Config file is stored at `~/.pesa/config.json` with mode 600 (owner read/write only).
122
+ Override location with `PESA_CONFIG=/path/to/config.json`.
123
+
124
+ ---
125
+
126
+ ## Use with daraja-mock
127
+
128
+ ```bash
129
+ # Start daraja-mock
130
+ python -m daraja_mock --port 8765
131
+
132
+ # Point pesa-cli at the mock
133
+ export PESA_BASE_URL=http://localhost:8765
134
+ pesa auth
135
+ pesa stk push 0712345678 100 --ref "Test"
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Design decisions
141
+
142
+ **Credentials resolved env → file.** CI/CD environments should use env vars.
143
+ Developer machines use the config file. The CLI never asks for credentials
144
+ interactively — that would break scripting.
145
+
146
+ **Secrets masked at 600.** The config file is created with `chmod 600` so
147
+ other users on shared systems cannot read Daraja credentials.
148
+
149
+ **AccountReference truncated silently.** Daraja rejects `AccountReference` > 12 chars
150
+ with a cryptic error. The CLI truncates to 12 and shows what was sent.
151
+
152
+ **Rich output, not JSON by default.** For human use. Add `--output json` flag
153
+ if scripting against pesa-cli output is needed.
154
+
155
+ ---
156
+
157
+ *Part of the [nairobi-stack](https://github.com/gabrielmahia/nairobi-stack) East Africa engineering ecosystem.*
158
+ *Maintained by [Gabriel Mahia](https://github.com/gabrielmahia). Kenya × USA.*
@@ -0,0 +1,2 @@
1
+ from .main import app, main
2
+ __all__ = ["app", "main"]
@@ -0,0 +1,4 @@
1
+ from pesa_cli.cli import app
2
+
3
+ if __name__ == "__main__":
4
+ app()