lockedpass-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,8 @@
1
+ Copyright (c) 2026 Nextcoders LLC. All Rights Reserved.
2
+
3
+ This software and its source code are proprietary and confidential.
4
+ Unauthorized copying, distribution, modification, or use of this software,
5
+ via any medium, is strictly prohibited without the express written permission
6
+ of Nextcoders LLC.
7
+
8
+ For licensing inquiries, contact: hello@lockedpass.com
@@ -0,0 +1,107 @@
1
+ Metadata-Version: 2.4
2
+ Name: lockedpass-cli
3
+ Version: 0.1.0
4
+ Summary: Official CLI for LockedPass — zero-knowledge password manager
5
+ Author-email: Nextcoders <hello@lockedpass.com>
6
+ License-Expression: LicenseRef-Proprietary
7
+ Project-URL: Homepage, https://lockedpass.com
8
+ Project-URL: Documentation, https://account.lockedpass.com/api-docs
9
+ Project-URL: Repository, https://github.com/nextcoders/lockedpass-cli
10
+ Keywords: password,manager,cli,zero-knowledge,vault,encryption
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: End Users/Desktop
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Security :: Cryptography
19
+ Classifier: Topic :: Utilities
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: click>=8.0
24
+ Requires-Dist: httpx>=0.28
25
+ Requires-Dist: pynacl>=1.5
26
+ Requires-Dist: argon2-cffi>=23.0
27
+ Requires-Dist: cryptography>=41.0
28
+ Requires-Dist: pyperclip>=1.8
29
+ Dynamic: license-file
30
+
31
+ # LockedPass CLI
32
+
33
+ Official command-line interface for [LockedPass](https://lockedpass.com) — a zero-knowledge password manager for teams and AI agents.
34
+
35
+ All encryption and decryption happens **locally on your machine**. The server never sees your master password, private key, or any plaintext credential data.
36
+
37
+ ## Requirements
38
+
39
+ - Python 3.11+
40
+ - A LockedPass account (Pro plan or higher)
41
+ - An active CLI token generated from **Settings → API & CLI**
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ pip install lockedpass-cli
47
+ ```
48
+
49
+ ## Quick start
50
+
51
+ ```bash
52
+ lp login you@example.com
53
+ # Master password: •••••••• (prompted once, then cached)
54
+
55
+ lp vault list
56
+ lp ls
57
+ lp get "GitHub"
58
+ lp get "GitHub" --field password
59
+ ```
60
+
61
+ ## Commands
62
+
63
+ | Command | Description |
64
+ |---|---|
65
+ | `lp login <email>` | Authenticate — master password required once |
66
+ | `lp lock` | Wipe cached keys (re-prompt on next use) |
67
+ | `lp unlock` | Re-cache keys from master password after lock |
68
+ | `lp vault list` | List all vaults |
69
+ | `lp ls` | List credentials in default vault |
70
+ | `lp get <name>` | Show a credential |
71
+ | `lp get <name> --field password` | Print a single field (scriptable) |
72
+ | `lp add` | Create a credential interactively |
73
+ | `lp edit <name>` | Edit a credential |
74
+ | `lp rm <name>` | Delete a credential |
75
+ | `lp otp <name>` | Generate a live TOTP code |
76
+ | `lp generate` | Generate a random password |
77
+ | `lp copy <name>` | Copy password to clipboard (clears in 30s) |
78
+ | `lp status` | Show session status |
79
+ | `lp logout` | Clear saved session |
80
+
81
+ ## Non-interactive / AI agent use
82
+
83
+ The master password can be passed as an argument or environment variable — useful for automation and AI agents:
84
+
85
+ ```bash
86
+ # Argument
87
+ lp login lp.aivault@example.com "$LP_AI_PASSWORD"
88
+
89
+ # Environment variable
90
+ LP_MASTER_PASSWORD="$LP_AI_PASSWORD" lp login lp.aivault@example.com
91
+ ```
92
+
93
+ After login the session is cached — subsequent commands run without any password.
94
+
95
+ See [AGENT.md](AGENT.md) for the full AI agent setup guide.
96
+
97
+ ## Security
98
+
99
+ - **Argon2id** key derivation — only a one-way hash (`auth_verifier`) is sent to the server
100
+ - **X25519 + XSalsa20-Poly1305** (NaCl) for vault key encryption
101
+ - **XSalsa20-Poly1305** for credential data encryption
102
+ - Private key and vault keys never leave your machine in plaintext
103
+ - Session cached with a random local key — wiped on `lp lock`
104
+
105
+ ## License
106
+
107
+ Copyright (c) 2026 Nextcoders LLC. All Rights Reserved. — see [LICENSE](LICENSE)
@@ -0,0 +1,77 @@
1
+ # LockedPass CLI
2
+
3
+ Official command-line interface for [LockedPass](https://lockedpass.com) — a zero-knowledge password manager for teams and AI agents.
4
+
5
+ All encryption and decryption happens **locally on your machine**. The server never sees your master password, private key, or any plaintext credential data.
6
+
7
+ ## Requirements
8
+
9
+ - Python 3.11+
10
+ - A LockedPass account (Pro plan or higher)
11
+ - An active CLI token generated from **Settings → API & CLI**
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pip install lockedpass-cli
17
+ ```
18
+
19
+ ## Quick start
20
+
21
+ ```bash
22
+ lp login you@example.com
23
+ # Master password: •••••••• (prompted once, then cached)
24
+
25
+ lp vault list
26
+ lp ls
27
+ lp get "GitHub"
28
+ lp get "GitHub" --field password
29
+ ```
30
+
31
+ ## Commands
32
+
33
+ | Command | Description |
34
+ |---|---|
35
+ | `lp login <email>` | Authenticate — master password required once |
36
+ | `lp lock` | Wipe cached keys (re-prompt on next use) |
37
+ | `lp unlock` | Re-cache keys from master password after lock |
38
+ | `lp vault list` | List all vaults |
39
+ | `lp ls` | List credentials in default vault |
40
+ | `lp get <name>` | Show a credential |
41
+ | `lp get <name> --field password` | Print a single field (scriptable) |
42
+ | `lp add` | Create a credential interactively |
43
+ | `lp edit <name>` | Edit a credential |
44
+ | `lp rm <name>` | Delete a credential |
45
+ | `lp otp <name>` | Generate a live TOTP code |
46
+ | `lp generate` | Generate a random password |
47
+ | `lp copy <name>` | Copy password to clipboard (clears in 30s) |
48
+ | `lp status` | Show session status |
49
+ | `lp logout` | Clear saved session |
50
+
51
+ ## Non-interactive / AI agent use
52
+
53
+ The master password can be passed as an argument or environment variable — useful for automation and AI agents:
54
+
55
+ ```bash
56
+ # Argument
57
+ lp login lp.aivault@example.com "$LP_AI_PASSWORD"
58
+
59
+ # Environment variable
60
+ LP_MASTER_PASSWORD="$LP_AI_PASSWORD" lp login lp.aivault@example.com
61
+ ```
62
+
63
+ After login the session is cached — subsequent commands run without any password.
64
+
65
+ See [AGENT.md](AGENT.md) for the full AI agent setup guide.
66
+
67
+ ## Security
68
+
69
+ - **Argon2id** key derivation — only a one-way hash (`auth_verifier`) is sent to the server
70
+ - **X25519 + XSalsa20-Poly1305** (NaCl) for vault key encryption
71
+ - **XSalsa20-Poly1305** for credential data encryption
72
+ - Private key and vault keys never leave your machine in plaintext
73
+ - Session cached with a random local key — wiped on `lp lock`
74
+
75
+ ## License
76
+
77
+ Copyright (c) 2026 Nextcoders LLC. All Rights Reserved. — see [LICENSE](LICENSE)
@@ -0,0 +1,107 @@
1
+ Metadata-Version: 2.4
2
+ Name: lockedpass-cli
3
+ Version: 0.1.0
4
+ Summary: Official CLI for LockedPass — zero-knowledge password manager
5
+ Author-email: Nextcoders <hello@lockedpass.com>
6
+ License-Expression: LicenseRef-Proprietary
7
+ Project-URL: Homepage, https://lockedpass.com
8
+ Project-URL: Documentation, https://account.lockedpass.com/api-docs
9
+ Project-URL: Repository, https://github.com/nextcoders/lockedpass-cli
10
+ Keywords: password,manager,cli,zero-knowledge,vault,encryption
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: End Users/Desktop
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Security :: Cryptography
19
+ Classifier: Topic :: Utilities
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: click>=8.0
24
+ Requires-Dist: httpx>=0.28
25
+ Requires-Dist: pynacl>=1.5
26
+ Requires-Dist: argon2-cffi>=23.0
27
+ Requires-Dist: cryptography>=41.0
28
+ Requires-Dist: pyperclip>=1.8
29
+ Dynamic: license-file
30
+
31
+ # LockedPass CLI
32
+
33
+ Official command-line interface for [LockedPass](https://lockedpass.com) — a zero-knowledge password manager for teams and AI agents.
34
+
35
+ All encryption and decryption happens **locally on your machine**. The server never sees your master password, private key, or any plaintext credential data.
36
+
37
+ ## Requirements
38
+
39
+ - Python 3.11+
40
+ - A LockedPass account (Pro plan or higher)
41
+ - An active CLI token generated from **Settings → API & CLI**
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ pip install lockedpass-cli
47
+ ```
48
+
49
+ ## Quick start
50
+
51
+ ```bash
52
+ lp login you@example.com
53
+ # Master password: •••••••• (prompted once, then cached)
54
+
55
+ lp vault list
56
+ lp ls
57
+ lp get "GitHub"
58
+ lp get "GitHub" --field password
59
+ ```
60
+
61
+ ## Commands
62
+
63
+ | Command | Description |
64
+ |---|---|
65
+ | `lp login <email>` | Authenticate — master password required once |
66
+ | `lp lock` | Wipe cached keys (re-prompt on next use) |
67
+ | `lp unlock` | Re-cache keys from master password after lock |
68
+ | `lp vault list` | List all vaults |
69
+ | `lp ls` | List credentials in default vault |
70
+ | `lp get <name>` | Show a credential |
71
+ | `lp get <name> --field password` | Print a single field (scriptable) |
72
+ | `lp add` | Create a credential interactively |
73
+ | `lp edit <name>` | Edit a credential |
74
+ | `lp rm <name>` | Delete a credential |
75
+ | `lp otp <name>` | Generate a live TOTP code |
76
+ | `lp generate` | Generate a random password |
77
+ | `lp copy <name>` | Copy password to clipboard (clears in 30s) |
78
+ | `lp status` | Show session status |
79
+ | `lp logout` | Clear saved session |
80
+
81
+ ## Non-interactive / AI agent use
82
+
83
+ The master password can be passed as an argument or environment variable — useful for automation and AI agents:
84
+
85
+ ```bash
86
+ # Argument
87
+ lp login lp.aivault@example.com "$LP_AI_PASSWORD"
88
+
89
+ # Environment variable
90
+ LP_MASTER_PASSWORD="$LP_AI_PASSWORD" lp login lp.aivault@example.com
91
+ ```
92
+
93
+ After login the session is cached — subsequent commands run without any password.
94
+
95
+ See [AGENT.md](AGENT.md) for the full AI agent setup guide.
96
+
97
+ ## Security
98
+
99
+ - **Argon2id** key derivation — only a one-way hash (`auth_verifier`) is sent to the server
100
+ - **X25519 + XSalsa20-Poly1305** (NaCl) for vault key encryption
101
+ - **XSalsa20-Poly1305** for credential data encryption
102
+ - Private key and vault keys never leave your machine in plaintext
103
+ - Session cached with a random local key — wiped on `lp lock`
104
+
105
+ ## License
106
+
107
+ Copyright (c) 2026 Nextcoders LLC. All Rights Reserved. — see [LICENSE](LICENSE)
@@ -0,0 +1,15 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ lockedpass_cli.egg-info/PKG-INFO
5
+ lockedpass_cli.egg-info/SOURCES.txt
6
+ lockedpass_cli.egg-info/dependency_links.txt
7
+ lockedpass_cli.egg-info/entry_points.txt
8
+ lockedpass_cli.egg-info/requires.txt
9
+ lockedpass_cli.egg-info/top_level.txt
10
+ lp/__init__.py
11
+ lp/__main__.py
12
+ lp/api.py
13
+ lp/cli.py
14
+ lp/crypto.py
15
+ lp/session.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ lp = lp.cli:cli
@@ -0,0 +1,6 @@
1
+ click>=8.0
2
+ httpx>=0.28
3
+ pynacl>=1.5
4
+ argon2-cffi>=23.0
5
+ cryptography>=41.0
6
+ pyperclip>=1.8
@@ -0,0 +1,2 @@
1
+ """LockedPass CLI — zero-knowledge password manager."""
2
+ __version__ = "0.1.0"
@@ -0,0 +1,4 @@
1
+ from lp.cli import cli
2
+
3
+ if __name__ == "__main__":
4
+ cli()
@@ -0,0 +1,140 @@
1
+ """HTTP client for the LockedPass API."""
2
+
3
+ import httpx
4
+
5
+ _DEFAULT_TIMEOUT = 15
6
+
7
+
8
+ class APIError(Exception):
9
+ def __init__(self, status: int, detail: str):
10
+ super().__init__(detail)
11
+ self.status = status
12
+
13
+ @classmethod
14
+ def from_response(cls, r: httpx.Response) -> "APIError":
15
+ try:
16
+ d = r.json()
17
+ detail = d.get("detail", f"HTTP {r.status_code}")
18
+ if isinstance(detail, list):
19
+ detail = "; ".join(e.get("msg", str(e)) for e in detail)
20
+ except Exception:
21
+ detail = f"HTTP {r.status_code}"
22
+ return cls(r.status_code, str(detail))
23
+
24
+
25
+ class Client:
26
+ def __init__(self, base_url: str, token: str | None = None):
27
+ self.base_url = base_url.rstrip("/")
28
+ self.token = token
29
+
30
+ def _headers(self) -> dict:
31
+ h = {"Content-Type": "application/json"}
32
+ if self.token:
33
+ h["Authorization"] = f"Bearer {self.token}"
34
+ return h
35
+
36
+ def _check(self, r: httpx.Response) -> httpx.Response:
37
+ if not r.is_success:
38
+ raise APIError.from_response(r)
39
+ return r
40
+
41
+ def get(self, path: str) -> dict:
42
+ r = httpx.get(f"{self.base_url}{path}", headers=self._headers(), timeout=_DEFAULT_TIMEOUT)
43
+ return self._check(r).json()
44
+
45
+ def post(self, path: str, body: dict) -> dict | None:
46
+ r = httpx.post(f"{self.base_url}{path}", json=body, headers=self._headers(), timeout=_DEFAULT_TIMEOUT)
47
+ self._check(r)
48
+ return r.json() if r.status_code != 204 else None
49
+
50
+ def patch(self, path: str, body: dict) -> dict:
51
+ r = httpx.patch(f"{self.base_url}{path}", json=body, headers=self._headers(), timeout=_DEFAULT_TIMEOUT)
52
+ return self._check(r).json()
53
+
54
+ def delete(self, path: str) -> None:
55
+ r = httpx.delete(f"{self.base_url}{path}", headers=self._headers(), timeout=_DEFAULT_TIMEOUT)
56
+ self._check(r)
57
+
58
+ # ── Auth ─────────────────────────────────────────────────────────────────
59
+
60
+ def login_init(self, email: str) -> dict:
61
+ return self.post("/api/v1/auth/login/init", {"email": email})
62
+
63
+ def cli_login(self, email: str, auth_verifier: str) -> dict:
64
+ """Authenticate and get a 30-day CLI token."""
65
+ return self.post("/api/v1/auth/cli/token", {"email": email, "auth_verifier": auth_verifier})
66
+
67
+ def me(self) -> dict:
68
+ return self.get("/api/v1/cli/me")
69
+
70
+ # ── Vaults ───────────────────────────────────────────────────────────────
71
+
72
+ def list_vaults(self) -> list:
73
+ """Returns vaults with embedded members (no extra request needed)."""
74
+ return self.get("/api/v1/cli/vaults")
75
+
76
+ def create_vault(self, name_encrypted: str, vault_type: str, encrypted_vault_key: str) -> dict:
77
+ return self.post("/api/v1/vaults", {
78
+ "name_encrypted": name_encrypted,
79
+ "type": vault_type,
80
+ "encrypted_vault_key": encrypted_vault_key,
81
+ })
82
+
83
+ # ── Credentials ──────────────────────────────────────────────────────────
84
+
85
+ def list_credentials(self, vault_id: str, limit: int = 2000) -> list:
86
+ return self.get(f"/api/v1/cli/vaults/{vault_id}/credentials?limit={limit}")
87
+
88
+ def list_all_credentials(self, vault_id: str) -> list:
89
+ PAGE, skip, all_creds = 2000, 0, []
90
+ while True:
91
+ page = self.get(f"/api/v1/cli/vaults/{vault_id}/credentials?skip={skip}&limit={PAGE}")
92
+ all_creds.extend(page)
93
+ if len(page) < PAGE:
94
+ break
95
+ skip += PAGE
96
+ return all_creds
97
+
98
+ def get_credential_with_key(self, cred_id: str) -> dict:
99
+ """Single request — returns credential + vault_key_encrypted."""
100
+ return self.get(f"/api/v1/cli/credentials/{cred_id}")
101
+
102
+ def create_credential(self, vault_id: str, cred_type: str, name_enc: str, data_enc: str) -> dict:
103
+ return self.post("/api/v1/cli/credentials", {
104
+ "vault_id": vault_id,
105
+ "type": cred_type,
106
+ "name_encrypted": name_enc,
107
+ "encrypted_data": data_enc,
108
+ })
109
+
110
+ def update_credential(self, vault_id: str, cred_id: str, name_enc: str, data_enc: str) -> dict:
111
+ return self.patch(f"/api/v1/vaults/{vault_id}/credentials/{cred_id}", {
112
+ "name_encrypted": name_enc,
113
+ "encrypted_data": data_enc,
114
+ })
115
+
116
+ def delete_credential(self, vault_id: str, cred_id: str) -> None:
117
+ self.delete(f"/api/v1/vaults/{vault_id}/credentials/{cred_id}")
118
+
119
+ def get_otp_secret(self, cred_id: str) -> dict:
120
+ return self.get(f"/api/v1/cli/otps/{cred_id}/secret")
121
+
122
+ def generate_password(self, length: int = 20, upper: bool = True, lower: bool = True,
123
+ numbers: bool = True, symbols: bool = True) -> str:
124
+ r = self.get(
125
+ f"/api/v1/cli/generate-password?length={length}"
126
+ f"&upper={str(upper).lower()}&lower={str(lower).lower()}"
127
+ f"&numbers={str(numbers).lower()}&symbols={str(symbols).lower()}"
128
+ )
129
+ return r["password"]
130
+
131
+ def log_action(self, vault_id: str, cred_id: str, action: str) -> None:
132
+ try:
133
+ self.post(f"/api/v1/vaults/{vault_id}/credentials/{cred_id}/log", {"action": action})
134
+ except Exception:
135
+ pass # non-critical
136
+
137
+ # ── Users ────────────────────────────────────────────────────────────────
138
+
139
+ def lookup_user(self, email: str) -> dict:
140
+ return self.get(f"/api/v1/users/lookup?email={email}")