heyarchie-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.
- heyarchie_cli-0.1.0/.gitignore +217 -0
- heyarchie_cli-0.1.0/PKG-INFO +101 -0
- heyarchie_cli-0.1.0/README.md +75 -0
- heyarchie_cli-0.1.0/pyproject.toml +52 -0
- heyarchie_cli-0.1.0/src/archie_cli/__init__.py +12 -0
- heyarchie_cli-0.1.0/src/archie_cli/__main__.py +35 -0
- heyarchie_cli-0.1.0/src/archie_cli/auth.py +101 -0
- heyarchie_cli-0.1.0/src/archie_cli/client.py +179 -0
- heyarchie_cli-0.1.0/src/archie_cli/cmds/__init__.py +1 -0
- heyarchie_cli-0.1.0/src/archie_cli/cmds/login.py +46 -0
- heyarchie_cli-0.1.0/src/archie_cli/cmds/skills.py +233 -0
- heyarchie_cli-0.1.0/src/archie_cli/cmds/workstreams.py +298 -0
- heyarchie_cli-0.1.0/tests/test_auth.py +89 -0
- heyarchie_cli-0.1.0/tests/test_skills.py +76 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Agent 365 CLI generated config — contains plaintext client secret on non-Windows
|
|
2
|
+
a365.generated.config.json
|
|
3
|
+
# Root-level a365.config.json auto-created by CLI; canonical config lives at apps/api/a365.config.json
|
|
4
|
+
/a365.config.json
|
|
5
|
+
|
|
6
|
+
# Node.js dependencies
|
|
7
|
+
node_modules/
|
|
8
|
+
**/node_modules/
|
|
9
|
+
|
|
10
|
+
# pnpm
|
|
11
|
+
.pnpm-store/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Linear Integration
|
|
15
|
+
.env
|
|
16
|
+
.env.*
|
|
17
|
+
!.env.example
|
|
18
|
+
!.env.vault.example
|
|
19
|
+
!.env.test
|
|
20
|
+
!.env.observability.example
|
|
21
|
+
linear-tickets.json
|
|
22
|
+
linear-issue-mapping.json
|
|
23
|
+
*.tickets.json
|
|
24
|
+
.cloudflare_credentials
|
|
25
|
+
|
|
26
|
+
# Deleted orchestrator — V2 killed, V3 renamed to orchestrator/. Never re-add.
|
|
27
|
+
**/orchestrator_v3/
|
|
28
|
+
**/orchestrator_v2/
|
|
29
|
+
|
|
30
|
+
# Workstream Studio build artifacts + Playwright run output. Never commit.
|
|
31
|
+
apps/workstream-studio/dist/
|
|
32
|
+
apps/workstream-studio/e2e/screenshots/
|
|
33
|
+
apps/workstream-studio/e2e/test-results/
|
|
34
|
+
apps/workstream-studio/playwright-report/
|
|
35
|
+
apps/workstream-studio/test-results/
|
|
36
|
+
|
|
37
|
+
# Python Environment (UV + Ruff)
|
|
38
|
+
.venv/
|
|
39
|
+
venv/
|
|
40
|
+
__pycache__/
|
|
41
|
+
*.pyc
|
|
42
|
+
*.pyo
|
|
43
|
+
*.pyd
|
|
44
|
+
.Python
|
|
45
|
+
pip-log.txt
|
|
46
|
+
pip-delete-this-directory.txt
|
|
47
|
+
.pytest_cache/
|
|
48
|
+
.mypy_cache/
|
|
49
|
+
.ruff_cache/
|
|
50
|
+
htmlcov/
|
|
51
|
+
.coverage
|
|
52
|
+
.coverage.*
|
|
53
|
+
coverage.xml
|
|
54
|
+
*.cover
|
|
55
|
+
.hypothesis/
|
|
56
|
+
|
|
57
|
+
# File Ingestion Service - Test files and uploads
|
|
58
|
+
src/services/file-ingestion/test_*.py
|
|
59
|
+
src/services/file-ingestion/test_*.json
|
|
60
|
+
src/services/file-ingestion/data/uploads/
|
|
61
|
+
src/services/file-ingestion/seeds/
|
|
62
|
+
src/services/file-ingestion/examples/
|
|
63
|
+
|
|
64
|
+
# Test scripts and temporary files (root level only, not in tests/ directories)
|
|
65
|
+
/test_*.py
|
|
66
|
+
/test-*.sh
|
|
67
|
+
/start-*.sh
|
|
68
|
+
/stop-*.sh
|
|
69
|
+
|
|
70
|
+
# macOS
|
|
71
|
+
.DS_Store
|
|
72
|
+
|
|
73
|
+
# Vite build artifacts
|
|
74
|
+
**/node_modules/.vite/
|
|
75
|
+
**/node_modules/.vite/deps_temp_*
|
|
76
|
+
|
|
77
|
+
# Build artifacts
|
|
78
|
+
/dist
|
|
79
|
+
apps/teams/dist/
|
|
80
|
+
|
|
81
|
+
# .NET build output
|
|
82
|
+
**/bin/
|
|
83
|
+
**/obj/
|
|
84
|
+
|
|
85
|
+
# Terraform local environments
|
|
86
|
+
/terraform/environments/dev
|
|
87
|
+
|
|
88
|
+
# Playwright test results and reports
|
|
89
|
+
test-results/
|
|
90
|
+
playwright-report/
|
|
91
|
+
|
|
92
|
+
# Claude Flow generated files
|
|
93
|
+
.claude/settings.local.json
|
|
94
|
+
.mcp.json
|
|
95
|
+
claude-flow.config.json
|
|
96
|
+
.swarm/
|
|
97
|
+
.hive-mind/
|
|
98
|
+
.claude-flow/
|
|
99
|
+
memory/
|
|
100
|
+
coordination/
|
|
101
|
+
# Allow the orchestrator memory module (Python package, not claude-flow data)
|
|
102
|
+
!apps/api/src/orchestrator/memory/
|
|
103
|
+
# Same module after the V4 consolidation move (Epic 14 issue #3517).
|
|
104
|
+
!apps/api/src/orchestrator/v4/memory/
|
|
105
|
+
# Allow the scoped memory services module (Epic aemm00l)
|
|
106
|
+
!apps/api/src/services/memory/
|
|
107
|
+
# Allow memory unit tests
|
|
108
|
+
!tests/unit/memory/
|
|
109
|
+
!apps/api/tests/orchestrator/memory/
|
|
110
|
+
memory/claude-flow-data.json
|
|
111
|
+
memory/sessions/*
|
|
112
|
+
!memory/sessions/README.md
|
|
113
|
+
memory/agents/*
|
|
114
|
+
!memory/agents/README.md
|
|
115
|
+
coordination/memory_bank/*
|
|
116
|
+
coordination/subtasks/*
|
|
117
|
+
coordination/orchestration/*
|
|
118
|
+
*.db
|
|
119
|
+
*.db-journal
|
|
120
|
+
*.db-wal
|
|
121
|
+
*.sqlite
|
|
122
|
+
*.sqlite-journal
|
|
123
|
+
*.sqlite-wal
|
|
124
|
+
claude-flow
|
|
125
|
+
# Removed Windows wrapper files per user request
|
|
126
|
+
hive-mind-prompt-*.txt
|
|
127
|
+
|
|
128
|
+
# Infrastructure files with secrets (do not commit)
|
|
129
|
+
infrastructure/docker/migration-job.yaml
|
|
130
|
+
|
|
131
|
+
# Playwright auth state (generated at runtime, contains session tokens)
|
|
132
|
+
tests/e2e/.auth/user.json
|
|
133
|
+
tests/smoke/.auth/user.json
|
|
134
|
+
|
|
135
|
+
# Frontend lock file
|
|
136
|
+
apps/frontend/package-lock.json
|
|
137
|
+
|
|
138
|
+
# Martha test workflow tracker
|
|
139
|
+
.test-tracker.json
|
|
140
|
+
|
|
141
|
+
# Worktree-specific configuration
|
|
142
|
+
.worktree-config.json
|
|
143
|
+
|
|
144
|
+
# Test reports (generated by pytest)
|
|
145
|
+
apps/api/reports/
|
|
146
|
+
**/reports/*.xml
|
|
147
|
+
**/reports/*.html
|
|
148
|
+
.env.copilot-tests
|
|
149
|
+
|
|
150
|
+
# Sidebar v2 sample files (do not commit)
|
|
151
|
+
.archie-sidebar-v2-samples/
|
|
152
|
+
~/.archie-sidebar-v2-samples/
|
|
153
|
+
|
|
154
|
+
# GitHub Actions local secrets
|
|
155
|
+
.act.secrets
|
|
156
|
+
|
|
157
|
+
# CEA manifest packages (built from manifest source files)
|
|
158
|
+
apps/archie-m365/manifest/archie-cea-*.zip
|
|
159
|
+
apps/archie-m365/manifest-da/archie-da-*.zip
|
|
160
|
+
apps/api/static/archie-cea-*.zip
|
|
161
|
+
|
|
162
|
+
# OpenAPI Generator CLI config (tool-specific)
|
|
163
|
+
openapitools.json
|
|
164
|
+
|
|
165
|
+
# Smoke test tracking
|
|
166
|
+
.smoke-tracker.json
|
|
167
|
+
|
|
168
|
+
# Render environment file (contains secrets - DO NOT COMMIT)
|
|
169
|
+
env.render
|
|
170
|
+
*.render.env
|
|
171
|
+
|
|
172
|
+
# UI library build output
|
|
173
|
+
packages/ui/dist/
|
|
174
|
+
packages/ui/storybook-static/
|
|
175
|
+
|
|
176
|
+
# Windows desktop app build artifacts (Inno Setup installer + staging)
|
|
177
|
+
apps/archie-desktop-win/dist/
|
|
178
|
+
apps/archie-desktop-win/ArchieDesktop/bin/
|
|
179
|
+
apps/archie-desktop-win/ArchieDesktop/obj/
|
|
180
|
+
|
|
181
|
+
# Script output (locale comparisons, debug exports)
|
|
182
|
+
scripts/output/
|
|
183
|
+
|
|
184
|
+
# Rust/Tauri build artifacts
|
|
185
|
+
**/target/
|
|
186
|
+
**/src-tauri/target/
|
|
187
|
+
Cargo.lock
|
|
188
|
+
!apps/workstreams-studio/src-tauri/Cargo.lock
|
|
189
|
+
|
|
190
|
+
# Auto-generated by sprite executor
|
|
191
|
+
.claude-task-*
|
|
192
|
+
.claude/worktrees/
|
|
193
|
+
|
|
194
|
+
# Deleted standalone orchestrator service — do not re-add
|
|
195
|
+
services/orchestrator/
|
|
196
|
+
.claude/plans/
|
|
197
|
+
.claude/scheduled_tasks.lock
|
|
198
|
+
# Playwright MCP browser test artifacts
|
|
199
|
+
.playwright-mcp/
|
|
200
|
+
apps/developers-portal/.next
|
|
201
|
+
tsconfig.tsbuildinfo
|
|
202
|
+
apps/developers-portal/next-env.d.ts
|
|
203
|
+
|
|
204
|
+
# Martha active-issue marker (per-session, never tracked)
|
|
205
|
+
.claude/active-issue
|
|
206
|
+
.claude/.turn-needs-martha
|
|
207
|
+
.claude/.last-martha-update
|
|
208
|
+
|
|
209
|
+
# Orchestrator V4 autonomous build loop — append-only journal + pause flag
|
|
210
|
+
# Journal lives at worktree root (not .claude/) so it bypasses Claude Code's
|
|
211
|
+
# .claude/ sensitivity prompts.
|
|
212
|
+
orchv4-build-journal.md
|
|
213
|
+
orchv4-interior-journal.md
|
|
214
|
+
.claude/orchv4-PAUSE
|
|
215
|
+
.claude/orchv4-interior-PAUSE
|
|
216
|
+
.env.test
|
|
217
|
+
.alpha-deploy-state/
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: heyarchie-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Command-line interface for the Archie Connect platform — workstreams, cycles, skills.
|
|
5
|
+
Project-URL: Homepage, https://developers.heyarchie.ai
|
|
6
|
+
Project-URL: Documentation, https://developers.heyarchie.ai/docs/cli
|
|
7
|
+
Project-URL: Source, https://github.com/heyarchie-ai/archie-platform-v2/tree/alpha/apps/cli
|
|
8
|
+
Author-email: Archie <hey@archie.ai>
|
|
9
|
+
License: Proprietary
|
|
10
|
+
Keywords: archie,cli,connect,workstreams
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Requires-Dist: click<9.0,>=8.1
|
|
19
|
+
Requires-Dist: httpx<1.0,>=0.27
|
|
20
|
+
Requires-Dist: rich<14.0,>=13.7
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# archie CLI
|
|
28
|
+
|
|
29
|
+
Command-line interface for the Archie Connect platform.
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# from PyPI (when published)
|
|
35
|
+
pipx install heyarchie-cli
|
|
36
|
+
|
|
37
|
+
# or from this repo for development
|
|
38
|
+
pip install -e apps/cli
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`pipx` is recommended; it installs `archie` as a self-contained executable on
|
|
42
|
+
your PATH without touching system Python packages.
|
|
43
|
+
|
|
44
|
+
## Authenticate
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
archie login --api-url https://api.heyarchie.ai
|
|
48
|
+
# Then paste your bearer token at the prompt (input is hidden).
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This writes `~/.archie/credentials.toml` (chmod 600) under the `[default]`
|
|
52
|
+
profile. Override per-call with `--profile`, `--api-key`, or env vars
|
|
53
|
+
`ARCHIE_API_KEY` / `ARCHIE_API_URL`.
|
|
54
|
+
|
|
55
|
+
> Today the bearer must be an **Archie session JWT** or **Archie OAuth JWT**.
|
|
56
|
+
> WorkOS-issued `sk_*` API keys are not yet validated server-side — see
|
|
57
|
+
> [`docs/connect/api-keys-flow.md`](../../docs/connect/api-keys-flow.md) for
|
|
58
|
+
> the architectural decision pending.
|
|
59
|
+
|
|
60
|
+
## Commands
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
archie login Save bearer credentials.
|
|
64
|
+
archie workstreams list [--scope ...] List visible workstreams.
|
|
65
|
+
archie workstreams describe <id> Show metadata + step graph.
|
|
66
|
+
archie workstreams run <id> [--var k=v] Start a cycle.
|
|
67
|
+
archie workstreams status <cycle_id> Show cycle progress.
|
|
68
|
+
archie workstreams cancel <cycle_id> Cancel a running cycle.
|
|
69
|
+
archie workstreams logs <cycle_id> Stream SSE events live.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`workstream_id` accepts a UUID, a workstream slug, or a 7-char permakey;
|
|
73
|
+
the API resolves all three.
|
|
74
|
+
|
|
75
|
+
## Examples
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# List workstreams
|
|
79
|
+
archie workstreams list
|
|
80
|
+
|
|
81
|
+
# JSON output (pipe-friendly)
|
|
82
|
+
archie workstreams list --json | jq '.items[].permakey'
|
|
83
|
+
|
|
84
|
+
# Start a cycle and watch it run
|
|
85
|
+
CYCLE=$(archie workstreams run abc1234 --period 2026-Q1 --json | jq -r .cycle_id)
|
|
86
|
+
archie workstreams logs "$CYCLE"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Environment variables
|
|
90
|
+
|
|
91
|
+
| Variable | Purpose | Default |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| `ARCHIE_API_URL` | API base URL | `https://api.heyarchie.ai` |
|
|
94
|
+
| `ARCHIE_API_KEY` | Bearer token | (none) |
|
|
95
|
+
|
|
96
|
+
CLI flags take precedence over env, which takes precedence over the
|
|
97
|
+
on-disk credentials file.
|
|
98
|
+
|
|
99
|
+
## Where this lives
|
|
100
|
+
|
|
101
|
+
`apps/cli/` in the `archie-platform-v2` monorepo. PRs welcome.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# archie CLI
|
|
2
|
+
|
|
3
|
+
Command-line interface for the Archie Connect platform.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# from PyPI (when published)
|
|
9
|
+
pipx install heyarchie-cli
|
|
10
|
+
|
|
11
|
+
# or from this repo for development
|
|
12
|
+
pip install -e apps/cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`pipx` is recommended; it installs `archie` as a self-contained executable on
|
|
16
|
+
your PATH without touching system Python packages.
|
|
17
|
+
|
|
18
|
+
## Authenticate
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
archie login --api-url https://api.heyarchie.ai
|
|
22
|
+
# Then paste your bearer token at the prompt (input is hidden).
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This writes `~/.archie/credentials.toml` (chmod 600) under the `[default]`
|
|
26
|
+
profile. Override per-call with `--profile`, `--api-key`, or env vars
|
|
27
|
+
`ARCHIE_API_KEY` / `ARCHIE_API_URL`.
|
|
28
|
+
|
|
29
|
+
> Today the bearer must be an **Archie session JWT** or **Archie OAuth JWT**.
|
|
30
|
+
> WorkOS-issued `sk_*` API keys are not yet validated server-side — see
|
|
31
|
+
> [`docs/connect/api-keys-flow.md`](../../docs/connect/api-keys-flow.md) for
|
|
32
|
+
> the architectural decision pending.
|
|
33
|
+
|
|
34
|
+
## Commands
|
|
35
|
+
|
|
36
|
+
```text
|
|
37
|
+
archie login Save bearer credentials.
|
|
38
|
+
archie workstreams list [--scope ...] List visible workstreams.
|
|
39
|
+
archie workstreams describe <id> Show metadata + step graph.
|
|
40
|
+
archie workstreams run <id> [--var k=v] Start a cycle.
|
|
41
|
+
archie workstreams status <cycle_id> Show cycle progress.
|
|
42
|
+
archie workstreams cancel <cycle_id> Cancel a running cycle.
|
|
43
|
+
archie workstreams logs <cycle_id> Stream SSE events live.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`workstream_id` accepts a UUID, a workstream slug, or a 7-char permakey;
|
|
47
|
+
the API resolves all three.
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# List workstreams
|
|
53
|
+
archie workstreams list
|
|
54
|
+
|
|
55
|
+
# JSON output (pipe-friendly)
|
|
56
|
+
archie workstreams list --json | jq '.items[].permakey'
|
|
57
|
+
|
|
58
|
+
# Start a cycle and watch it run
|
|
59
|
+
CYCLE=$(archie workstreams run abc1234 --period 2026-Q1 --json | jq -r .cycle_id)
|
|
60
|
+
archie workstreams logs "$CYCLE"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Environment variables
|
|
64
|
+
|
|
65
|
+
| Variable | Purpose | Default |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `ARCHIE_API_URL` | API base URL | `https://api.heyarchie.ai` |
|
|
68
|
+
| `ARCHIE_API_KEY` | Bearer token | (none) |
|
|
69
|
+
|
|
70
|
+
CLI flags take precedence over env, which takes precedence over the
|
|
71
|
+
on-disk credentials file.
|
|
72
|
+
|
|
73
|
+
## Where this lives
|
|
74
|
+
|
|
75
|
+
`apps/cli/` in the `archie-platform-v2` monorepo. PRs welcome.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "heyarchie-cli"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Command-line interface for the Archie Connect platform — workstreams, cycles, skills."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = { text = "Proprietary" }
|
|
8
|
+
authors = [{ name = "Archie", email = "hey@archie.ai" }]
|
|
9
|
+
keywords = ["archie", "connect", "cli", "workstreams"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Environment :: Console",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"Programming Language :: Python :: 3.11",
|
|
15
|
+
"Programming Language :: Python :: 3.12",
|
|
16
|
+
"Topic :: Office/Business :: Financial :: Accounting",
|
|
17
|
+
]
|
|
18
|
+
dependencies = [
|
|
19
|
+
"click>=8.1,<9.0",
|
|
20
|
+
"httpx>=0.27,<1.0",
|
|
21
|
+
"rich>=13.7,<14.0",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
dev = [
|
|
26
|
+
"pytest>=8.0",
|
|
27
|
+
"pytest-asyncio>=0.23",
|
|
28
|
+
"ruff>=0.6",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://developers.heyarchie.ai"
|
|
33
|
+
Documentation = "https://developers.heyarchie.ai/docs/cli"
|
|
34
|
+
Source = "https://github.com/heyarchie-ai/archie-platform-v2/tree/alpha/apps/cli"
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
archie = "archie_cli.__main__:main"
|
|
38
|
+
|
|
39
|
+
[build-system]
|
|
40
|
+
requires = ["hatchling"]
|
|
41
|
+
build-backend = "hatchling.build"
|
|
42
|
+
|
|
43
|
+
[tool.hatch.build.targets.wheel]
|
|
44
|
+
packages = ["src/archie_cli"]
|
|
45
|
+
|
|
46
|
+
[tool.ruff]
|
|
47
|
+
line-length = 100
|
|
48
|
+
target-version = "py311"
|
|
49
|
+
|
|
50
|
+
[tool.ruff.lint]
|
|
51
|
+
select = ["E", "F", "I", "B", "UP", "RUF"]
|
|
52
|
+
ignore = ["E501"]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Archie Connect CLI — `archie` console script.
|
|
2
|
+
|
|
3
|
+
Surfaces the Connect platform as terminal commands. Read-friendly when
|
|
4
|
+
attached to a TTY (rich-rendered tables, colors); machine-friendly when
|
|
5
|
+
piped (`--json`).
|
|
6
|
+
|
|
7
|
+
Auth is bearer-only today: an Archie session JWT or an Archie OAuth JWT.
|
|
8
|
+
WorkOS-managed `sk_*` API keys are not yet validated server-side — see
|
|
9
|
+
`docs/connect/api-keys-flow.md` for the architectural decision pending.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""``archie`` console-script entry point."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from archie_cli import __version__
|
|
8
|
+
from archie_cli.cmds.login import login_cmd
|
|
9
|
+
from archie_cli.cmds.skills import skills_group
|
|
10
|
+
from archie_cli.cmds.workstreams import workstreams_group
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.group(
|
|
14
|
+
help=(
|
|
15
|
+
"Archie Connect CLI.\n\n"
|
|
16
|
+
"Read-friendly when attached to a TTY; pipe-friendly with --json.\n"
|
|
17
|
+
"Auth: bearer token via --api-key, env ARCHIE_API_KEY, or `archie login`."
|
|
18
|
+
)
|
|
19
|
+
)
|
|
20
|
+
@click.version_option(__version__, prog_name="archie")
|
|
21
|
+
def cli() -> None:
|
|
22
|
+
"""archie — Connect CLI."""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
cli.add_command(login_cmd)
|
|
26
|
+
cli.add_command(skills_group)
|
|
27
|
+
cli.add_command(workstreams_group)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def main() -> None:
|
|
31
|
+
cli()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == "__main__": # pragma: no cover
|
|
35
|
+
main()
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Credential storage for the `archie` CLI.
|
|
2
|
+
|
|
3
|
+
Lookup order: explicit flag → env var → on-disk credentials → prompt the
|
|
4
|
+
user. The on-disk file at ``~/.archie/credentials.toml`` is chmod 600.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import stat
|
|
11
|
+
import sys
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
import tomllib # py311+
|
|
17
|
+
except ImportError: # pragma: no cover
|
|
18
|
+
import tomli as tomllib # type: ignore[no-redef]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
CREDENTIALS_PATH = Path.home() / ".archie" / "credentials.toml"
|
|
22
|
+
DEFAULT_PROFILE = "default"
|
|
23
|
+
DEFAULT_API_URL = "https://api.heyarchie.ai"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class Credentials:
|
|
28
|
+
"""Resolved CLI credentials."""
|
|
29
|
+
|
|
30
|
+
api_url: str
|
|
31
|
+
api_key: str
|
|
32
|
+
profile: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class CredentialError(Exception):
|
|
36
|
+
"""Raised when credentials are missing or unreadable."""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def load_credentials(
|
|
40
|
+
*,
|
|
41
|
+
profile: str = DEFAULT_PROFILE,
|
|
42
|
+
api_url_override: str | None = None,
|
|
43
|
+
api_key_override: str | None = None,
|
|
44
|
+
) -> Credentials:
|
|
45
|
+
"""Resolve credentials, preferring explicit overrides → env → on-disk."""
|
|
46
|
+
api_url = (
|
|
47
|
+
api_url_override
|
|
48
|
+
or os.environ.get("ARCHIE_API_URL")
|
|
49
|
+
or _from_disk(profile, "api_url")
|
|
50
|
+
or DEFAULT_API_URL
|
|
51
|
+
)
|
|
52
|
+
api_key = api_key_override or os.environ.get("ARCHIE_API_KEY") or _from_disk(profile, "api_key")
|
|
53
|
+
if not api_key:
|
|
54
|
+
raise CredentialError(
|
|
55
|
+
"No API key found. Set ARCHIE_API_KEY, run `archie login`, or pass --api-key."
|
|
56
|
+
)
|
|
57
|
+
return Credentials(api_url=api_url.rstrip("/"), api_key=api_key, profile=profile)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def save_credentials(api_url: str, api_key: str, *, profile: str = DEFAULT_PROFILE) -> Path:
|
|
61
|
+
"""Persist credentials to ``~/.archie/credentials.toml`` (chmod 600)."""
|
|
62
|
+
CREDENTIALS_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
63
|
+
existing: dict[str, dict[str, str]] = {}
|
|
64
|
+
if CREDENTIALS_PATH.exists():
|
|
65
|
+
try:
|
|
66
|
+
with CREDENTIALS_PATH.open("rb") as fh:
|
|
67
|
+
existing = tomllib.load(fh) # type: ignore[assignment]
|
|
68
|
+
except Exception: # pragma: no cover — corrupt file → overwrite
|
|
69
|
+
existing = {}
|
|
70
|
+
existing[profile] = {"api_url": api_url.rstrip("/"), "api_key": api_key}
|
|
71
|
+
text = _render_toml(existing)
|
|
72
|
+
CREDENTIALS_PATH.write_text(text)
|
|
73
|
+
os.chmod(CREDENTIALS_PATH, stat.S_IRUSR | stat.S_IWUSR)
|
|
74
|
+
return CREDENTIALS_PATH
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _from_disk(profile: str, key: str) -> str | None:
|
|
78
|
+
if not CREDENTIALS_PATH.exists():
|
|
79
|
+
return None
|
|
80
|
+
try:
|
|
81
|
+
with CREDENTIALS_PATH.open("rb") as fh:
|
|
82
|
+
data = tomllib.load(fh)
|
|
83
|
+
except Exception as exc: # pragma: no cover
|
|
84
|
+
print(f"warning: failed to read {CREDENTIALS_PATH}: {exc}", file=sys.stderr)
|
|
85
|
+
return None
|
|
86
|
+
section = data.get(profile)
|
|
87
|
+
if not isinstance(section, dict):
|
|
88
|
+
return None
|
|
89
|
+
value = section.get(key)
|
|
90
|
+
return str(value) if value else None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _render_toml(data: dict[str, dict[str, str]]) -> str:
|
|
94
|
+
out: list[str] = []
|
|
95
|
+
for profile, fields in sorted(data.items()):
|
|
96
|
+
out.append(f"[{profile}]")
|
|
97
|
+
for k in sorted(fields):
|
|
98
|
+
v = fields[k].replace('"', '\\"')
|
|
99
|
+
out.append(f'{k} = "{v}"')
|
|
100
|
+
out.append("")
|
|
101
|
+
return "\n".join(out)
|