papycli 0.4.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,7 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash"
5
+ ]
6
+ }
7
+ }
@@ -0,0 +1,207 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ #uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ #poetry.lock
109
+ #poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ #pdm.lock
116
+ #pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ #pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # SageMath parsed files
135
+ *.sage.py
136
+
137
+ # Environments
138
+ .env
139
+ .envrc
140
+ .venv
141
+ env/
142
+ venv/
143
+ ENV/
144
+ env.bak/
145
+ venv.bak/
146
+
147
+ # Spyder project settings
148
+ .spyderproject
149
+ .spyproject
150
+
151
+ # Rope project settings
152
+ .ropeproject
153
+
154
+ # mkdocs documentation
155
+ /site
156
+
157
+ # mypy
158
+ .mypy_cache/
159
+ .dmypy.json
160
+ dmypy.json
161
+
162
+ # Pyre type checker
163
+ .pyre/
164
+
165
+ # pytype static type analyzer
166
+ .pytype/
167
+
168
+ # Cython debug symbols
169
+ cython_debug/
170
+
171
+ # PyCharm
172
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
173
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
174
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
175
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
176
+ #.idea/
177
+
178
+ # Abstra
179
+ # Abstra is an AI-powered process automation framework.
180
+ # Ignore directories containing user credentials, local state, and settings.
181
+ # Learn more at https://abstra.io/docs
182
+ .abstra/
183
+
184
+ # Visual Studio Code
185
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
188
+ # you could uncomment the following to ignore the entire vscode folder
189
+ # .vscode/
190
+
191
+ # Ruff stuff:
192
+ .ruff_cache/
193
+
194
+ # PyPI configuration file
195
+ .pypirc
196
+
197
+ # Cursor
198
+ # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
199
+ # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
200
+ # refer to https://docs.cursor.com/context/ignore-files
201
+ .cursorignore
202
+ .cursorindexingignore
203
+
204
+ # Marimo
205
+ marimo/_static/
206
+ marimo/_lsp/
207
+ __marimo__/
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,191 @@
1
+ # CLAUDE.md
2
+
3
+ ## プロジェクト概要
4
+
5
+ `papycli` は OpenAPI 3.0 仕様を読み込み、REST API エンドポイントをターミナルから直接呼び出せるインタラクティブな CLI を提供する Python 製ツールです。
6
+
7
+ ---
8
+
9
+ ## 開発環境
10
+
11
+ - Python 3.12 以上
12
+ - 依存ライブラリは `pyproject.toml` で管理する
13
+
14
+ ### セットアップ
15
+
16
+ ```bash
17
+ pip install -e ".[dev]"
18
+ ```
19
+
20
+ ### 開発用ツール
21
+
22
+ | ツール | 用途 |
23
+ |--------|------|
24
+ | `pytest` | テスト実行 |
25
+ | `ruff` | Lint + フォーマット |
26
+ | `mypy` | 型チェック |
27
+
28
+ ---
29
+
30
+ ## アーキテクチャ
31
+
32
+ ### ディレクトリ構成
33
+
34
+ ```
35
+ papycli/
36
+ ├── src/
37
+ │ └── papycli/
38
+ │ ├── __init__.py
39
+ │ ├── main.py # エントリポイント・引数パース
40
+ │ ├── init_cmd.py # --init コマンド(spec の変換・保存)
41
+ │ ├── api_call.py # HTTP リクエスト実行
42
+ │ ├── completion.py # シェル補完スクリプト生成
43
+ │ ├── config.py # 設定ファイルの読み書き
44
+ │ ├── spec_loader.py # OpenAPI spec の読み込み・$ref 解決
45
+ │ └── summary.py # --summary / --summary-csv
46
+ ├── tests/
47
+ ├── examples/
48
+ │ ├── docker-compose.yml
49
+ │ └── petstore-oas3.json
50
+ ├── pyproject.toml
51
+ ├── README.md
52
+ └── CLAUDE.md
53
+ ```
54
+
55
+ ### 主要モジュール
56
+
57
+ **`main.py`** — CLI エントリポイント
58
+ 引数をパースし、各コマンド(`init`、`use`、`conf`、`summary`、`completion-script`、メソッド呼び出し)に処理を委譲する。シェル補完用の `_complete` 内部コマンドもここで定義する。
59
+
60
+ **`init_cmd.py`** — API 初期化
61
+ OpenAPI spec ファイルを受け取り、`$ref` を解決した上で papycli 内部の API 定義フォーマットに変換し、`$PAPYCLI_CONF_DIR/apis/<name>.json` に保存する。設定ファイル (`papycli.conf`) も更新する。
62
+
63
+ **`spec_loader.py`** — spec 読み込み・変換
64
+ OpenAPI spec の JSON/YAML を読み込み、`$ref` を再帰的に解決して、papycli の内部フォーマット(後述)に変換する。Python 標準ライブラリのみ(または最小限の依存)で実装する。
65
+
66
+ **`api_call.py`** — HTTP リクエスト実行
67
+ メソッド・リソースパス・オプションを受け取り、`requests` ライブラリで HTTP リクエストを実行する。パステンプレート(`/pet/{petId}`)のマッチングと値の埋め込みも担当する。
68
+
69
+ **`completion.py`** — シェル補完
70
+ bash / zsh 向けの補完スクリプトを生成する。補完の候補はメソッド、リソースパス、パラメータ名、enum 値の順にコンテキストに応じて提供する。
71
+
72
+ **`config.py`** — 設定管理
73
+ `papycli.conf` の読み書きと、`PAPYCLI_CONF_DIR` 環境変数の解決を行う。
74
+
75
+ **`summary.py`** — サマリー表示
76
+ 登録済み API のエンドポイント一覧を整形して出力する。`--summary-csv` では CSV 形式で出力する。
77
+
78
+ ---
79
+
80
+ ## 内部データフォーマット
81
+
82
+ ### API 定義ファイル (`apis/<name>.json`)
83
+
84
+ ```json
85
+ {
86
+ "/pet": [
87
+ {
88
+ "method": "post",
89
+ "query_parameters": [],
90
+ "post_parameters": [
91
+ {"name": "name", "type": "string", "required": true},
92
+ {"name": "status", "type": "string", "required": false, "enum": ["available", "pending", "sold"]},
93
+ {"name": "photoUrls", "type": "array", "required": true}
94
+ ]
95
+ }
96
+ ],
97
+ "/pet/findByStatus": [
98
+ {
99
+ "method": "get",
100
+ "query_parameters": [
101
+ {"name": "status", "type": "string", "required": false, "enum": ["available", "pending", "sold"]}
102
+ ],
103
+ "post_parameters": []
104
+ }
105
+ ],
106
+ "/pet/{petId}": [
107
+ {
108
+ "method": "get",
109
+ "query_parameters": [],
110
+ "post_parameters": []
111
+ },
112
+ {
113
+ "method": "delete",
114
+ "query_parameters": [],
115
+ "post_parameters": []
116
+ }
117
+ ]
118
+ }
119
+ ```
120
+
121
+ ### 設定ファイル (`papycli.conf`)
122
+
123
+ ```json
124
+ {
125
+ "default": "petstore",
126
+ "petstore": {
127
+ "openapispec": "petstore.json",
128
+ "apidef": "petstore.json",
129
+ "url": "http://localhost:8080/api/v3"
130
+ }
131
+ }
132
+ ```
133
+
134
+ ---
135
+
136
+ ## CLI 仕様
137
+
138
+ ### コマンド構文
139
+
140
+ ```
141
+ papycli <method> <resource> [options]
142
+ papycli init <spec-file>
143
+ papycli use <api-name>
144
+ papycli conf
145
+ papycli summary [resource] [--csv]
146
+ papycli completion-script <bash|zsh>
147
+ papycli --version
148
+ papycli --help / -h
149
+ ```
150
+
151
+ ### サポートするメソッド
152
+
153
+ `get | post | put | patch | delete` をサポートする。
154
+
155
+ ### パラメータ処理
156
+
157
+ - `-q <name> <value>` — URL クエリパラメータ。同じ名前を繰り返し可能(`?status=a&status=b`)
158
+ - `-p <name> <value>` — JSON ボディパラメータ。同じキーを繰り返すと配列を構築する
159
+ - `-p <name.subname> <value>` — ドット記法で 1 レベルのネストオブジェクトを構築する
160
+ - `-d <json>` — 生の JSON 文字列。`-p` オプションを上書きする
161
+ - `-H <header: value>` — カスタム HTTP ヘッダー
162
+
163
+ ### パステンプレートのマッチング
164
+
165
+ リソースパスに数値や文字列が含まれる場合(例:`/pet/99`)、API 定義内のテンプレート(`/pet/{petId}`)にマッチさせ、値を埋め込んでリクエストを送信する。
166
+
167
+ ---
168
+
169
+ ## 環境変数
170
+
171
+ | 変数 | デフォルト | 説明 |
172
+ |------|-----------|------|
173
+ | `PAPYCLI_CONF_DIR` | `~/.papycli` | 設定ディレクトリのパス |
174
+ | `PAPYCLI_CUSTOM_HEADER` | (なし) | 全リクエストに付与するカスタムヘッダー(改行区切りで複数指定可) |
175
+
176
+ ---
177
+
178
+ ## テスト方針
179
+
180
+ - `tests/` 以下にユニットテストを配置する
181
+ - HTTP リクエストは `responses` ライブラリ等でモックして実テストしない
182
+ - OpenAPI spec の変換ロジックは代表的なケースを網羅するテストを書く
183
+
184
+ ---
185
+
186
+ ## コーディング規約
187
+
188
+ - フォーマッタ・Lint は `ruff` を使用する
189
+ - 型ヒントを積極的に使用し、`mypy` でチェックを通す
190
+ - 関数・モジュールの公開 API にのみ docstring を書く(内部実装には不要)
191
+ - エラーメッセージはユーザーが原因を特定しやすい内容にする
papycli-0.4.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Taro Monji
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
papycli-0.4.0/PKG-INFO ADDED
@@ -0,0 +1,252 @@
1
+ Metadata-Version: 2.4
2
+ Name: papycli
3
+ Version: 0.4.0
4
+ Summary: A CLI tool to call REST APIs defined in OpenAPI 3.0 specs
5
+ Project-URL: Homepage, https://github.com/tmonj1/papycli
6
+ Project-URL: Repository, https://github.com/tmonj1/papycli
7
+ Project-URL: Bug Tracker, https://github.com/tmonj1/papycli/issues
8
+ Author-email: tmonj1 <tmonj1@gmail.com>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: api,cli,http,openapi,rest
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Internet :: WWW/HTTP
20
+ Classifier: Topic :: Utilities
21
+ Requires-Python: >=3.12
22
+ Requires-Dist: click>=8.1
23
+ Requires-Dist: pyyaml>=6.0
24
+ Requires-Dist: requests>=2.32
25
+ Requires-Dist: rich>=13.0
26
+ Description-Content-Type: text/markdown
27
+
28
+ # papycli — Python CLI for OpenAPI 3.0 REST APIs
29
+
30
+ `papycli` is an interactive CLI that reads OpenAPI 3.0 specs and lets you call REST API endpoints directly from the terminal.
31
+
32
+ ## Features
33
+
34
+ - Auto-generates a CLI from any OpenAPI 3.0 spec
35
+ - Shell completion for bash and zsh
36
+ - Register and switch between multiple APIs
37
+
38
+ ## Requirements
39
+
40
+ | Item | Notes |
41
+ |------|-------|
42
+ | Python | 3.12 or later |
43
+
44
+ No external tools (e.g. `jq`) required. Works with Python and pip alone.
45
+
46
+ ---
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ pip install papycli
52
+ ```
53
+
54
+ ### Enable Shell Completion
55
+
56
+ **bash:**
57
+
58
+ ```bash
59
+ # Add to ~/.bashrc or ~/.bash_profile
60
+ eval "$(papycli completion-script bash)"
61
+ ```
62
+
63
+ **zsh:**
64
+
65
+ ```bash
66
+ # Add to ~/.zshrc
67
+ eval "$(papycli completion-script zsh)"
68
+ ```
69
+
70
+ Restart your shell or run `source ~/.bashrc` / `source ~/.zshrc` to apply.
71
+
72
+ ---
73
+
74
+ ## Quick Start — Petstore Demo
75
+
76
+ This repository includes a demo using the [Swagger Petstore](https://github.com/swagger-api/swagger-petstore).
77
+
78
+ ### 1. Start the Petstore server
79
+
80
+ ```bash
81
+ docker compose -f examples/docker-compose.yml up -d
82
+ ```
83
+
84
+ The API will be available at `http://localhost:8080/api/v3/`.
85
+
86
+ ### 2. Register the API
87
+
88
+ ```bash
89
+ papycli init examples/petstore-oas3.json
90
+ ```
91
+
92
+ ### 3. Try some commands
93
+
94
+ ```bash
95
+ # List available endpoints
96
+ papycli summary
97
+
98
+ # GET /store/inventory
99
+ papycli get /store/inventory
100
+
101
+ # GET with a path parameter
102
+ papycli get /pet/99
103
+
104
+ # GET with a query parameter
105
+ papycli get /pet/findByStatus -q status available
106
+
107
+ # POST with body parameters
108
+ papycli post /pet -p name "My Dog" -p status available -p photoUrls "http://example.com/photo.jpg"
109
+
110
+ # POST with a raw JSON body
111
+ papycli post /pet -d '{"name": "My Dog", "status": "available", "photoUrls": ["http://example.com/photo.jpg"]}'
112
+
113
+ # Array parameter (repeat the same key)
114
+ papycli put /pet -p id 1 -p name "My Dog" -p photoUrls "http://example.com/a.jpg" -p photoUrls "http://example.com/b.jpg" -p status available
115
+
116
+ # Nested object (dot notation)
117
+ papycli put /pet -p id 1 -p name "My Dog" -p category.id 2 -p category.name "Dogs" -p photoUrls "http://example.com/photo.jpg" -p status available
118
+
119
+ # DELETE /pet/{petId}
120
+ papycli delete /pet/1
121
+ ```
122
+
123
+ ### 4. Tab completion
124
+
125
+ Once shell completion is enabled, tab completion is available:
126
+
127
+ ```
128
+ $ papycli <TAB>
129
+ get post put delete patch
130
+
131
+ $ papycli get <TAB>
132
+ /pet/findByStatus /pet/{petId} /store/inventory ...
133
+
134
+ $ papycli get /pet/findByStatus <TAB>
135
+ -q --summary --help
136
+
137
+ $ papycli get /pet/findByStatus -q <TAB>
138
+ status
139
+
140
+ $ papycli get /pet/findByStatus -q status <TAB>
141
+ available pending sold
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Adding Your Own API
147
+
148
+ ### Step 1 — Run `init`
149
+
150
+ ```bash
151
+ papycli init your-api-spec.json
152
+ ```
153
+
154
+ This command will:
155
+
156
+ 1. Resolve all `$ref` references in the OpenAPI spec
157
+ 2. Convert the spec to papycli's internal API definition format
158
+ 3. Save the result to `$PAPYCLI_CONF_DIR/apis/<name>.json`
159
+ 4. Create or update `$PAPYCLI_CONF_DIR/papycli.conf`
160
+
161
+ The API name is derived from the filename (e.g. `your-api-spec.json` → `your-api-spec`).
162
+
163
+ ### Step 2 — Set the base URL
164
+
165
+ If the spec contains `servers[0].url`, it is used automatically. Otherwise, edit `$PAPYCLI_CONF_DIR/papycli.conf` and set the `url` field:
166
+
167
+ ```json
168
+ {
169
+ "default": "your-api-spec",
170
+ "your-api-spec": {
171
+ "openapispec": "your-api-spec.json",
172
+ "apidef": "your-api-spec.json",
173
+ "url": "https://your-api-base-url/"
174
+ }
175
+ }
176
+ ```
177
+
178
+ ### Managing Multiple APIs
179
+
180
+ ```bash
181
+ # Register multiple APIs
182
+ papycli init petstore-oas3.json
183
+ papycli init myapi.json
184
+
185
+ # Switch the active API
186
+ papycli use myapi
187
+
188
+ # Show registered APIs and the current default
189
+ papycli conf
190
+ ```
191
+
192
+ ---
193
+
194
+ ## Reference
195
+
196
+ ```
197
+ # API management commands
198
+ papycli init <spec-file> Initialize an API from an OpenAPI spec file
199
+ papycli use <api-name> Switch the active API
200
+ papycli conf Show current configuration
201
+ papycli summary [resource] List available endpoints (filter by resource prefix)
202
+ Required params marked with *, array params with []
203
+ papycli summary --csv Output endpoints in CSV format
204
+ papycli completion-script <bash|zsh> Print a shell completion script
205
+
206
+ # API call commands
207
+ papycli <method> <resource> [options]
208
+
209
+ Methods:
210
+ get | post | put | patch | delete
211
+
212
+ Options:
213
+ -H <header: value> Custom HTTP header (repeatable)
214
+ -q <name> <value> Query parameter (repeatable)
215
+ -p <name> <value> Body parameter (repeatable)
216
+ - Repeat the same key to build a JSON array:
217
+ -p tags foo -p tags bar → {"tags":["foo","bar"]}
218
+ - Use dot notation to build a nested object:
219
+ -p category.id 1 -p category.name Dogs
220
+ → {"category":{"id":"1","name":"Dogs"}}
221
+ -d <json> Raw JSON body (overrides -p)
222
+ --summary Show endpoint info without sending a request
223
+ --version Show version
224
+ --help / -h Show help
225
+
226
+ Environment variables:
227
+ PAPYCLI_CONF_DIR Path to the config directory (default: ~/.papycli)
228
+ PAPYCLI_CUSTOM_HEADER Custom HTTP headers applied to every request.
229
+ Separate multiple headers with newlines:
230
+ export PAPYCLI_CUSTOM_HEADER=$'Authorization: Bearer token\nX-Tenant: acme'
231
+ ```
232
+
233
+ ---
234
+
235
+ ## Limitations
236
+
237
+ - Request bodies are `application/json` only
238
+ - Array parameters support scalar element types only (arrays of objects are not supported)
239
+ - Dot notation for nested objects supports one level of nesting only
240
+ - Pass auth headers via `-H "Authorization: Bearer token"` or the `PAPYCLI_CUSTOM_HEADER` env var
241
+
242
+ ---
243
+
244
+ ## Development
245
+
246
+ ```bash
247
+ git clone https://github.com/tmonj1/papycli.git
248
+ cd papycli
249
+ pip install -e ".[dev]"
250
+ ```
251
+
252
+ See [CLAUDE.md](CLAUDE.md) for details.