pipper-cli 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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sanjay (sanjoxtech)
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.
@@ -0,0 +1,95 @@
1
+ Metadata-Version: 2.4
2
+ Name: pipper-cli
3
+ Version: 0.1.0
4
+ Summary: Drive Claude Code headlessly in a tmux session โ€” script and automate the claude CLI.
5
+ Author-email: "Sanjay (sanjoxtech)" <sanjox.tech@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://sanjox.tech
8
+ Project-URL: Repository, https://github.com/sanjoxtech/pipper
9
+ Keywords: claude,claude-code,tmux,automation,headless,cli,agents
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: POSIX
13
+ Classifier: Topic :: Software Development :: Build Tools
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Dynamic: license-file
18
+
19
+ # ๐Ÿชˆ pipper
20
+
21
+ <p align="center">
22
+ <img src="docs/assets/readme-banner.png" alt="pipper โ€” drive Claude Code, headlessly" width="100%">
23
+ </p>
24
+
25
+ **Drive Claude Code headlessly in a tmux session โ€” script and automate the `claude` CLI from shell, cron, or code.**
26
+
27
+ ![python](https://img.shields.io/badge/python-3.9+-blue)
28
+ ![deps](https://img.shields.io/badge/dependencies-0-brightgreen)
29
+ ![license](https://img.shields.io/badge/license-MIT-black)
30
+
31
+ ---
32
+
33
+ `pipper` is a tiny harness that runs the interactive `claude` CLI inside **tmux**, auto-accepts its permission dialogs, sends a prompt, and returns Claude's answer. It lets you call Claude Code from scripts, cron jobs, pipelines, or another program โ€” without sitting at the terminal.
34
+
35
+ It drives your normal, already-logged-in `claude` client, so it inherits whatever plan and limits that login has. **Use it within [Anthropic's terms of service](https://www.anthropic.com/legal/aup).**
36
+
37
+ ## Why
38
+
39
+ - **Automate Claude Code** in CI, cron, or batch jobs
40
+ - **Glue it into other tools** โ€” get an answer back as text or JSON
41
+ - **TUI-version-proof** โ€” instead of scraping the terminal, pipper asks Claude to write its answer to a temp file, then reads it back
42
+
43
+ ## Requires
44
+
45
+ - [`tmux`](https://github.com/tmux/tmux)
46
+ - the [`claude` CLI](https://docs.claude.com/en/docs/claude-code) โ€” installed **and already authenticated** (`claude` runs without a login prompt)
47
+
48
+ ## Install
49
+
50
+ ```bash
51
+ pip install pipper-cli # once published; command is `pipper`
52
+ # or from source:
53
+ git clone https://github.com/sanjoxtech/pipper && cd pipper && pip install -e .
54
+ ```
55
+
56
+ Zero dependencies โ€” Python stdlib only.
57
+
58
+ ## Use
59
+
60
+ ```bash
61
+ pipper "summarize this repo's README in 3 bullets"
62
+ echo "list the riskiest lines in auth.py" | pipper --cwd ./myproject
63
+ pipper -f task.txt --timeout 900 --json
64
+ ```
65
+
66
+ Options: `--cwd <dir>`, `--session <name>`, `--timeout <s>`, `--boot-timeout <s>`, `--json`.
67
+
68
+ From Python:
69
+
70
+ ```python
71
+ import pipper
72
+ answer = pipper.run("explain what this project does", cwd="./repo")
73
+ ```
74
+
75
+ ## How it works
76
+
77
+ 1. Spawns `claude --permission-mode bypassPermissions` in a fresh tmux session
78
+ 2. Auto-accepts the startup/permission dialogs (handles different orderings + plain y/n)
79
+ 3. Pastes your prompt via an isolated tmux buffer (so parallel runs don't clash)
80
+ 4. Asks Claude to **write its final answer to a temp file**, then polls that file
81
+ 5. Returns the answer; tears the session down; bails early on repeated API errors
82
+
83
+ ## Limitations / honest notes
84
+
85
+ - Relies on `tmux` + the interactive `claude` TUI. If Claude Code changes its startup dialogs a lot, the auto-accept heuristics may need a tweak.
86
+ - `bypassPermissions` means Claude can run tools without asking โ€” only point it at directories you trust.
87
+ - It automates your normal `claude` login; respect Anthropic's usage terms and rate limits.
88
+
89
+ ## Author
90
+
91
+ Built by **Sanjay** ([sanjoxtech](https://github.com/sanjoxtech)) โ€” [sanjox.tech](https://sanjox.tech) ยท sanjox.tech@gmail.com
92
+
93
+ ## License
94
+
95
+ MIT โ€” see [LICENSE](LICENSE).
@@ -0,0 +1,77 @@
1
+ # ๐Ÿชˆ pipper
2
+
3
+ <p align="center">
4
+ <img src="docs/assets/readme-banner.png" alt="pipper โ€” drive Claude Code, headlessly" width="100%">
5
+ </p>
6
+
7
+ **Drive Claude Code headlessly in a tmux session โ€” script and automate the `claude` CLI from shell, cron, or code.**
8
+
9
+ ![python](https://img.shields.io/badge/python-3.9+-blue)
10
+ ![deps](https://img.shields.io/badge/dependencies-0-brightgreen)
11
+ ![license](https://img.shields.io/badge/license-MIT-black)
12
+
13
+ ---
14
+
15
+ `pipper` is a tiny harness that runs the interactive `claude` CLI inside **tmux**, auto-accepts its permission dialogs, sends a prompt, and returns Claude's answer. It lets you call Claude Code from scripts, cron jobs, pipelines, or another program โ€” without sitting at the terminal.
16
+
17
+ It drives your normal, already-logged-in `claude` client, so it inherits whatever plan and limits that login has. **Use it within [Anthropic's terms of service](https://www.anthropic.com/legal/aup).**
18
+
19
+ ## Why
20
+
21
+ - **Automate Claude Code** in CI, cron, or batch jobs
22
+ - **Glue it into other tools** โ€” get an answer back as text or JSON
23
+ - **TUI-version-proof** โ€” instead of scraping the terminal, pipper asks Claude to write its answer to a temp file, then reads it back
24
+
25
+ ## Requires
26
+
27
+ - [`tmux`](https://github.com/tmux/tmux)
28
+ - the [`claude` CLI](https://docs.claude.com/en/docs/claude-code) โ€” installed **and already authenticated** (`claude` runs without a login prompt)
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pip install pipper-cli # once published; command is `pipper`
34
+ # or from source:
35
+ git clone https://github.com/sanjoxtech/pipper && cd pipper && pip install -e .
36
+ ```
37
+
38
+ Zero dependencies โ€” Python stdlib only.
39
+
40
+ ## Use
41
+
42
+ ```bash
43
+ pipper "summarize this repo's README in 3 bullets"
44
+ echo "list the riskiest lines in auth.py" | pipper --cwd ./myproject
45
+ pipper -f task.txt --timeout 900 --json
46
+ ```
47
+
48
+ Options: `--cwd <dir>`, `--session <name>`, `--timeout <s>`, `--boot-timeout <s>`, `--json`.
49
+
50
+ From Python:
51
+
52
+ ```python
53
+ import pipper
54
+ answer = pipper.run("explain what this project does", cwd="./repo")
55
+ ```
56
+
57
+ ## How it works
58
+
59
+ 1. Spawns `claude --permission-mode bypassPermissions` in a fresh tmux session
60
+ 2. Auto-accepts the startup/permission dialogs (handles different orderings + plain y/n)
61
+ 3. Pastes your prompt via an isolated tmux buffer (so parallel runs don't clash)
62
+ 4. Asks Claude to **write its final answer to a temp file**, then polls that file
63
+ 5. Returns the answer; tears the session down; bails early on repeated API errors
64
+
65
+ ## Limitations / honest notes
66
+
67
+ - Relies on `tmux` + the interactive `claude` TUI. If Claude Code changes its startup dialogs a lot, the auto-accept heuristics may need a tweak.
68
+ - `bypassPermissions` means Claude can run tools without asking โ€” only point it at directories you trust.
69
+ - It automates your normal `claude` login; respect Anthropic's usage terms and rate limits.
70
+
71
+ ## Author
72
+
73
+ Built by **Sanjay** ([sanjoxtech](https://github.com/sanjoxtech)) โ€” [sanjox.tech](https://sanjox.tech) ยท sanjox.tech@gmail.com
74
+
75
+ ## License
76
+
77
+ MIT โ€” see [LICENSE](LICENSE).
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ pipper โ€” drive Claude Code headlessly in a tmux session.
4
+
5
+ A tiny harness that runs the interactive `claude` CLI inside tmux, auto-accepts its
6
+ permission dialogs, sends a prompt, and returns Claude's answer โ€” so you can script
7
+ and automate Claude Code from a shell, cron job, or another program.
8
+
9
+ It drives your normal, already-logged-in `claude` client (so it inherits whatever
10
+ plan and limits that login has). Use it within Anthropic's terms of service.
11
+
12
+ Requires: `tmux` and the `claude` CLI installed and already authenticated.
13
+
14
+ pipper "summarize this repo's README in 3 bullets"
15
+ echo "list the riskiest lines in auth.py" | pipper --cwd ./myproject
16
+ pipper -f task.txt --timeout 900 --json
17
+
18
+ How it works: pipper asks Claude to write its final answer to a temp file (instead of
19
+ scraping the terminal UI), then polls that file โ€” robust and TUI-version-proof.
20
+
21
+ Zero dependencies. Python stdlib only.
22
+ """
23
+ from __future__ import annotations
24
+ import argparse, json, os, re, subprocess, sys, tempfile, time
25
+ from pathlib import Path
26
+
27
+ __version__ = "0.1.0"
28
+
29
+ _OPT_RE = re.compile(r"^\s*(?:โฏ\s*)?(\d+)\.\s*(.+)$")
30
+ _DIALOG_HINTS = ("enter to confirm", "do you want", "do you trust", "i accept",
31
+ "proceed?", "(y/n)", "[y/n]", "trust the files")
32
+ _YES_WORDS = ("yes", "accept", "proceed", "trust", "continue", "allow")
33
+
34
+
35
+ def _tmux(*args) -> subprocess.CompletedProcess:
36
+ return subprocess.run(["tmux", *args], capture_output=True, text=True)
37
+
38
+
39
+ def _require_tools():
40
+ for tool in ("tmux", "claude"):
41
+ if subprocess.run(["which", tool], capture_output=True).returncode != 0:
42
+ sys.exit(f"pipper: `{tool}` not found on PATH. Install it and make sure it works first.")
43
+
44
+
45
+ def auto_accept(session: str) -> bool:
46
+ """If a yes/no confirmation dialog is showing, press the affirmative option.
47
+ Handles different option orderings (Yes can be 1 or 2) and plain y/n prompts."""
48
+ pane = _tmux("capture-pane", "-t", session, "-p").stdout
49
+ low = pane.lower()
50
+ if not any(h in low for h in _DIALOG_HINTS):
51
+ return False
52
+ for line in pane.splitlines():
53
+ m = _OPT_RE.match(line.strip())
54
+ if m and any(w in m.group(2).lower() for w in _YES_WORDS):
55
+ _tmux("send-keys", "-t", session, m.group(1)); time.sleep(0.3)
56
+ _tmux("send-keys", "-t", session, "Enter"); time.sleep(1.0)
57
+ return True
58
+ if "(y/n)" in low or "[y/n]" in low:
59
+ _tmux("send-keys", "-t", session, "y")
60
+ _tmux("send-keys", "-t", session, "Enter"); time.sleep(0.8)
61
+ return True
62
+ return False
63
+
64
+
65
+ def run(prompt: str, cwd: str = ".", session: str | None = None,
66
+ boot_timeout: int = 30, work_timeout: int = 600) -> str:
67
+ """Run `prompt` through interactive claude in tmux; return Claude's answer text."""
68
+ _require_tools()
69
+ session = session or f"pipper_{os.getpid()}"
70
+ cwd = str(Path(cwd).resolve())
71
+ tmp = Path(tempfile.mkdtemp(prefix="pipper_"))
72
+ outfile = tmp / "answer.txt"
73
+ promptfile = tmp / "prompt.txt"
74
+
75
+ wrapped = (
76
+ "Work autonomously. Do NOT ask me any questions. Do NOT print the final answer "
77
+ f"to chat. When done, use your Write tool to save your FINAL ANSWER to:\n{outfile}\n\n"
78
+ "--- TASK ---\n" + prompt
79
+ )
80
+ promptfile.write_text(wrapped, encoding="utf-8")
81
+
82
+ _tmux("kill-session", "-t", session)
83
+ _tmux("new-session", "-d", "-s", session, "-x", "220", "-y", "50")
84
+ _tmux("send-keys", "-t", session,
85
+ f"cd {cwd} && claude --permission-mode bypassPermissions", "Enter")
86
+
87
+ # wait for the input box, accepting any startup dialogs
88
+ t0 = time.time(); ready = False
89
+ while time.time() - t0 < boot_timeout:
90
+ pane = _tmux("capture-pane", "-t", session, "-p").stdout
91
+ low = pane.lower()
92
+ if ("shortcuts" in pane or "Welcome to Claude" in pane) and not any(
93
+ h in low for h in ("i accept", "do you trust", "trust the files", "enter to confirm")):
94
+ ready = True; break
95
+ auto_accept(session); time.sleep(1)
96
+ if not ready:
97
+ time.sleep(4)
98
+
99
+ # paste the prompt via an isolated named buffer, then submit
100
+ buf = f"b_{session}"
101
+ _tmux("load-buffer", "-b", buf, str(promptfile))
102
+ _tmux("paste-buffer", "-b", buf, "-t", session, "-d")
103
+ time.sleep(1.5)
104
+ _tmux("send-keys", "-t", session, "Enter")
105
+
106
+ # poll for the answer file; bail early on repeated API errors
107
+ t0 = time.time()
108
+ while time.time() - t0 < work_timeout:
109
+ if outfile.exists():
110
+ text = outfile.read_text(encoding="utf-8").strip()
111
+ if text:
112
+ _tmux("kill-session", "-t", session)
113
+ return text
114
+ pane = _tmux("capture-pane", "-t", session, "-p").stdout
115
+ auto_accept(session)
116
+ m = re.search(r"(API error.*?attempt\s+(\d+)/10|overloaded|rate.?limit|Connection error)", pane, re.I)
117
+ if m and (int(m.group(2)) if m.group(2) else 99) >= 4:
118
+ line = next((l.strip() for l in pane.splitlines() if "error" in l.lower()), m.group(0))
119
+ _tmux("kill-session", "-t", session)
120
+ raise RuntimeError(f"claude reported a repeated error: {line}")
121
+ time.sleep(3)
122
+
123
+ tail = _tmux("capture-pane", "-t", session, "-p").stdout[-1200:]
124
+ _tmux("kill-session", "-t", session)
125
+ raise TimeoutError(f"pipper timed out after {work_timeout}s. claude pane tail:\n{tail}")
126
+
127
+
128
+ def main(argv=None) -> int:
129
+ ap = argparse.ArgumentParser(prog="pipper", description="Drive Claude Code headlessly via tmux.")
130
+ ap.add_argument("prompt", nargs="?", help="the prompt (or use -f / stdin)")
131
+ ap.add_argument("-f", "--file", help="read the prompt from a file")
132
+ ap.add_argument("--cwd", default=".", help="working directory to run claude in")
133
+ ap.add_argument("--session", default=None, help="tmux session name (default: pipper_<pid>)")
134
+ ap.add_argument("--timeout", type=int, default=600, help="max seconds to wait for the answer")
135
+ ap.add_argument("--boot-timeout", type=int, default=30, help="max seconds to wait for claude to start")
136
+ ap.add_argument("--json", action="store_true", help="print {\"answer\": ...} as JSON")
137
+ ap.add_argument("--version", action="version", version=f"pipper {__version__}")
138
+ args = ap.parse_args(argv)
139
+
140
+ if args.file:
141
+ prompt = Path(args.file).read_text(encoding="utf-8")
142
+ elif args.prompt:
143
+ prompt = args.prompt
144
+ elif not sys.stdin.isatty():
145
+ prompt = sys.stdin.read()
146
+ else:
147
+ ap.error("no prompt given (pass it as an argument, with -f, or via stdin)")
148
+
149
+ if not prompt.strip():
150
+ ap.error("empty prompt")
151
+
152
+ answer = run(prompt, cwd=args.cwd, session=args.session,
153
+ boot_timeout=args.boot_timeout, work_timeout=args.timeout)
154
+ print(json.dumps({"answer": answer}) if args.json else answer)
155
+ return 0
156
+
157
+
158
+ if __name__ == "__main__":
159
+ raise SystemExit(main())
@@ -0,0 +1,95 @@
1
+ Metadata-Version: 2.4
2
+ Name: pipper-cli
3
+ Version: 0.1.0
4
+ Summary: Drive Claude Code headlessly in a tmux session โ€” script and automate the claude CLI.
5
+ Author-email: "Sanjay (sanjoxtech)" <sanjox.tech@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://sanjox.tech
8
+ Project-URL: Repository, https://github.com/sanjoxtech/pipper
9
+ Keywords: claude,claude-code,tmux,automation,headless,cli,agents
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: POSIX
13
+ Classifier: Topic :: Software Development :: Build Tools
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Dynamic: license-file
18
+
19
+ # ๐Ÿชˆ pipper
20
+
21
+ <p align="center">
22
+ <img src="docs/assets/readme-banner.png" alt="pipper โ€” drive Claude Code, headlessly" width="100%">
23
+ </p>
24
+
25
+ **Drive Claude Code headlessly in a tmux session โ€” script and automate the `claude` CLI from shell, cron, or code.**
26
+
27
+ ![python](https://img.shields.io/badge/python-3.9+-blue)
28
+ ![deps](https://img.shields.io/badge/dependencies-0-brightgreen)
29
+ ![license](https://img.shields.io/badge/license-MIT-black)
30
+
31
+ ---
32
+
33
+ `pipper` is a tiny harness that runs the interactive `claude` CLI inside **tmux**, auto-accepts its permission dialogs, sends a prompt, and returns Claude's answer. It lets you call Claude Code from scripts, cron jobs, pipelines, or another program โ€” without sitting at the terminal.
34
+
35
+ It drives your normal, already-logged-in `claude` client, so it inherits whatever plan and limits that login has. **Use it within [Anthropic's terms of service](https://www.anthropic.com/legal/aup).**
36
+
37
+ ## Why
38
+
39
+ - **Automate Claude Code** in CI, cron, or batch jobs
40
+ - **Glue it into other tools** โ€” get an answer back as text or JSON
41
+ - **TUI-version-proof** โ€” instead of scraping the terminal, pipper asks Claude to write its answer to a temp file, then reads it back
42
+
43
+ ## Requires
44
+
45
+ - [`tmux`](https://github.com/tmux/tmux)
46
+ - the [`claude` CLI](https://docs.claude.com/en/docs/claude-code) โ€” installed **and already authenticated** (`claude` runs without a login prompt)
47
+
48
+ ## Install
49
+
50
+ ```bash
51
+ pip install pipper-cli # once published; command is `pipper`
52
+ # or from source:
53
+ git clone https://github.com/sanjoxtech/pipper && cd pipper && pip install -e .
54
+ ```
55
+
56
+ Zero dependencies โ€” Python stdlib only.
57
+
58
+ ## Use
59
+
60
+ ```bash
61
+ pipper "summarize this repo's README in 3 bullets"
62
+ echo "list the riskiest lines in auth.py" | pipper --cwd ./myproject
63
+ pipper -f task.txt --timeout 900 --json
64
+ ```
65
+
66
+ Options: `--cwd <dir>`, `--session <name>`, `--timeout <s>`, `--boot-timeout <s>`, `--json`.
67
+
68
+ From Python:
69
+
70
+ ```python
71
+ import pipper
72
+ answer = pipper.run("explain what this project does", cwd="./repo")
73
+ ```
74
+
75
+ ## How it works
76
+
77
+ 1. Spawns `claude --permission-mode bypassPermissions` in a fresh tmux session
78
+ 2. Auto-accepts the startup/permission dialogs (handles different orderings + plain y/n)
79
+ 3. Pastes your prompt via an isolated tmux buffer (so parallel runs don't clash)
80
+ 4. Asks Claude to **write its final answer to a temp file**, then polls that file
81
+ 5. Returns the answer; tears the session down; bails early on repeated API errors
82
+
83
+ ## Limitations / honest notes
84
+
85
+ - Relies on `tmux` + the interactive `claude` TUI. If Claude Code changes its startup dialogs a lot, the auto-accept heuristics may need a tweak.
86
+ - `bypassPermissions` means Claude can run tools without asking โ€” only point it at directories you trust.
87
+ - It automates your normal `claude` login; respect Anthropic's usage terms and rate limits.
88
+
89
+ ## Author
90
+
91
+ Built by **Sanjay** ([sanjoxtech](https://github.com/sanjoxtech)) โ€” [sanjox.tech](https://sanjox.tech) ยท sanjox.tech@gmail.com
92
+
93
+ ## License
94
+
95
+ MIT โ€” see [LICENSE](LICENSE).
@@ -0,0 +1,9 @@
1
+ LICENSE
2
+ README.md
3
+ pipper.py
4
+ pyproject.toml
5
+ pipper_cli.egg-info/PKG-INFO
6
+ pipper_cli.egg-info/SOURCES.txt
7
+ pipper_cli.egg-info/dependency_links.txt
8
+ pipper_cli.egg-info/entry_points.txt
9
+ pipper_cli.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pipper = pipper:main
@@ -0,0 +1 @@
1
+ pipper
@@ -0,0 +1,30 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pipper-cli"
7
+ version = "0.1.0"
8
+ description = "Drive Claude Code headlessly in a tmux session โ€” script and automate the claude CLI."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Sanjay (sanjoxtech)", email = "sanjox.tech@gmail.com" }]
13
+ keywords = ["claude", "claude-code", "tmux", "automation", "headless", "cli", "agents"]
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Operating System :: POSIX",
18
+ "Topic :: Software Development :: Build Tools",
19
+ ]
20
+ dependencies = [] # zero dependencies, on purpose
21
+
22
+ [project.urls]
23
+ Homepage = "https://sanjox.tech"
24
+ Repository = "https://github.com/sanjoxtech/pipper"
25
+
26
+ [project.scripts]
27
+ pipper = "pipper:main"
28
+
29
+ [tool.setuptools]
30
+ py-modules = ["pipper"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+