nemo-cli 0.0.1__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.
- nemo_cli-0.0.1/.claude/skills/new-decision/SKILL.md +59 -0
- nemo_cli-0.0.1/.claude/skills/start-session/SKILL.md +19 -0
- nemo_cli-0.0.1/.claude/skills/status/SKILL.md +27 -0
- nemo_cli-0.0.1/.claude/skills/validate-context/SKILL.md +26 -0
- nemo_cli-0.0.1/.env.example +2 -0
- nemo_cli-0.0.1/.github/workflows/publish.yml +75 -0
- nemo_cli-0.0.1/.gitignore +37 -0
- nemo_cli-0.0.1/CHANGELOG.md +76 -0
- nemo_cli-0.0.1/CLAUDE.md +97 -0
- nemo_cli-0.0.1/LICENSE +21 -0
- nemo_cli-0.0.1/PKG-INFO +311 -0
- nemo_cli-0.0.1/README.md +255 -0
- nemo_cli-0.0.1/context-first-development.md +851 -0
- nemo_cli-0.0.1/docs/ARCHITECTURE.md +105 -0
- nemo_cli-0.0.1/docs/CONVENTIONS.md +125 -0
- nemo_cli-0.0.1/docs/STACK.md +45 -0
- nemo_cli-0.0.1/docs/decisions/001-initial-architecture.md +66 -0
- nemo_cli-0.0.1/docs/decisions/002-tech-stack.md +60 -0
- nemo_cli-0.0.1/docs/decisions/003-token-authentication.md +101 -0
- nemo_cli-0.0.1/docs/decisions/004-switch-to-python-stack.md +71 -0
- nemo_cli-0.0.1/docs/decisions/005-github-flow-branching.md +73 -0
- nemo_cli-0.0.1/docs/decisions/006-instruments-domain.md +113 -0
- nemo_cli-0.0.1/docs/decisions/007-versioning-and-changelog.md +94 -0
- nemo_cli-0.0.1/docs/decisions/008-portfolio-domain.md +120 -0
- nemo_cli-0.0.1/docs/decisions/010-instrument-price-history.md +120 -0
- nemo_cli-0.0.1/docs/decisions/011-portfolio-movements.md +166 -0
- nemo_cli-0.0.1/docs/decisions/012-refresh-token-flow.md +170 -0
- nemo_cli-0.0.1/docs/decisions/_index.md +15 -0
- nemo_cli-0.0.1/pyproject.toml +75 -0
- nemo_cli-0.0.1/scripts/verify_reactive_fallback.py +127 -0
- nemo_cli-0.0.1/scripts/verify_refresh.py +172 -0
- nemo_cli-0.0.1/src/nemo_cli/__init__.py +1 -0
- nemo_cli-0.0.1/src/nemo_cli/__main__.py +4 -0
- nemo_cli-0.0.1/src/nemo_cli/api/__init__.py +0 -0
- nemo_cli-0.0.1/src/nemo_cli/api/client.py +81 -0
- nemo_cli-0.0.1/src/nemo_cli/auth/__init__.py +0 -0
- nemo_cli-0.0.1/src/nemo_cli/auth/jwt.py +47 -0
- nemo_cli-0.0.1/src/nemo_cli/auth/service.py +56 -0
- nemo_cli-0.0.1/src/nemo_cli/auth/token_store.py +37 -0
- nemo_cli-0.0.1/src/nemo_cli/cli.py +46 -0
- nemo_cli-0.0.1/src/nemo_cli/commands/__init__.py +0 -0
- nemo_cli-0.0.1/src/nemo_cli/commands/instruments.py +271 -0
- nemo_cli-0.0.1/src/nemo_cli/commands/login.py +15 -0
- nemo_cli-0.0.1/src/nemo_cli/commands/logout.py +9 -0
- nemo_cli-0.0.1/src/nemo_cli/commands/portfolio.py +275 -0
- nemo_cli-0.0.1/src/nemo_cli/commands/whoami.py +18 -0
- nemo_cli-0.0.1/src/nemo_cli/config.py +24 -0
- nemo_cli-0.0.1/src/nemo_cli/instruments/__init__.py +0 -0
- nemo_cli-0.0.1/src/nemo_cli/instruments/international.py +102 -0
- nemo_cli-0.0.1/src/nemo_cli/instruments/local.py +94 -0
- nemo_cli-0.0.1/src/nemo_cli/instruments/prices.py +139 -0
- nemo_cli-0.0.1/src/nemo_cli/portfolio/__init__.py +0 -0
- nemo_cli-0.0.1/src/nemo_cli/portfolio/movements.py +342 -0
- nemo_cli-0.0.1/src/nemo_cli/portfolio/summary.py +185 -0
- nemo_cli-0.0.1/tests/__init__.py +0 -0
- nemo_cli-0.0.1/tests/api/__init__.py +0 -0
- nemo_cli-0.0.1/tests/api/test_client.py +296 -0
- nemo_cli-0.0.1/tests/auth/__init__.py +0 -0
- nemo_cli-0.0.1/tests/auth/test_jwt.py +89 -0
- nemo_cli-0.0.1/tests/auth/test_service.py +165 -0
- nemo_cli-0.0.1/tests/auth/test_token_store.py +95 -0
- nemo_cli-0.0.1/tests/commands/__init__.py +0 -0
- nemo_cli-0.0.1/tests/commands/test_auth_commands.py +99 -0
- nemo_cli-0.0.1/tests/commands/test_instruments_commands.py +320 -0
- nemo_cli-0.0.1/tests/commands/test_portfolio_commands.py +368 -0
- nemo_cli-0.0.1/tests/conftest.py +42 -0
- nemo_cli-0.0.1/tests/instruments/__init__.py +0 -0
- nemo_cli-0.0.1/tests/instruments/test_international.py +188 -0
- nemo_cli-0.0.1/tests/instruments/test_local.py +216 -0
- nemo_cli-0.0.1/tests/instruments/test_prices.py +245 -0
- nemo_cli-0.0.1/tests/portfolio/__init__.py +0 -0
- nemo_cli-0.0.1/tests/portfolio/test_movements.py +493 -0
- nemo_cli-0.0.1/tests/portfolio/test_summary.py +296 -0
- nemo_cli-0.0.1/tests/test_cli.py +44 -0
- nemo_cli-0.0.1/tests/test_config.py +85 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Capture a new architecture decision as an ADR file in docs/decisions/ before any implementation code is written. Use when the user is about to make a significant technical choice (stack, pattern, library, branching strategy, infra) or asks to "document a decision", "open an ADR", or "record this as an ADR".
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Help the user document a new architecture decision as an ADR. Do **not** write any
|
|
6
|
+
implementation code during this skill — its only output is the ADR file and the
|
|
7
|
+
updated index.
|
|
8
|
+
|
|
9
|
+
Steps:
|
|
10
|
+
|
|
11
|
+
1. **Elicit the decision.** Ask the user, one focused question at a time:
|
|
12
|
+
- What problem is being solved? (the *context*)
|
|
13
|
+
- What is the proposed change? (the *decision*)
|
|
14
|
+
- What other options were considered, and why are they being rejected?
|
|
15
|
+
- What becomes easier and what becomes harder as a result?
|
|
16
|
+
|
|
17
|
+
Do not move on until you have crisp one-paragraph answers for each.
|
|
18
|
+
|
|
19
|
+
2. **Pick the next ADR number.** List `docs/decisions/` and choose the next zero-
|
|
20
|
+
padded integer (e.g. if the highest is `005`, the new ADR is `006`).
|
|
21
|
+
|
|
22
|
+
3. **Write the ADR file** at `docs/decisions/<NNN>-<kebab-case-title>.md` using
|
|
23
|
+
this exact template:
|
|
24
|
+
|
|
25
|
+
````markdown
|
|
26
|
+
# ADR-<NNN>: <Title>
|
|
27
|
+
|
|
28
|
+
## Status
|
|
29
|
+
|
|
30
|
+
Accepted
|
|
31
|
+
|
|
32
|
+
## Date
|
|
33
|
+
|
|
34
|
+
<YYYY-MM-DD — today's date>
|
|
35
|
+
|
|
36
|
+
## Context
|
|
37
|
+
|
|
38
|
+
<One or two paragraphs describing the problem.>
|
|
39
|
+
|
|
40
|
+
## Decision
|
|
41
|
+
|
|
42
|
+
<The decision itself, stated as imperatives.>
|
|
43
|
+
|
|
44
|
+
## Alternatives Considered
|
|
45
|
+
|
|
46
|
+
- **<Option A>.** <Why it was rejected.>
|
|
47
|
+
- **<Option B>.** <Why it was rejected.>
|
|
48
|
+
|
|
49
|
+
## Consequences
|
|
50
|
+
|
|
51
|
+
<Bullets describing what changes — positive and negative — as a result.>
|
|
52
|
+
````
|
|
53
|
+
|
|
54
|
+
4. **Update `docs/decisions/_index.md`** by appending a new row to the table.
|
|
55
|
+
Preserve column alignment.
|
|
56
|
+
|
|
57
|
+
5. **Stop.** Do not modify source code in this skill. Tell the user the ADR is
|
|
58
|
+
ready and that the next step is to implement it (or to invoke a separate task
|
|
59
|
+
to do so).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Begin a CFD session by orienting on the nemo-cli project's current status and recent decisions without scanning source code. Use when the user asks to "start session", "get oriented", or invokes the CFD session-start ritual.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run the Context-First Development session-start ritual. Read **only** the following
|
|
6
|
+
files, in order, and do not scan source code unless a follow-up question requires it:
|
|
7
|
+
|
|
8
|
+
1. `docs/CURRENT_STATUS.md` — what is in progress, what is blocked, what is next.
|
|
9
|
+
2. `docs/decisions/_index.md` — recent decisions that may affect the next change.
|
|
10
|
+
|
|
11
|
+
Then produce a brief (≤ 8 lines) summary covering:
|
|
12
|
+
|
|
13
|
+
- What was being worked on in the previous session.
|
|
14
|
+
- What is currently blocked and why.
|
|
15
|
+
- What the next priority should be, based on `CURRENT_STATUS.md` and any open
|
|
16
|
+
questions noted there.
|
|
17
|
+
|
|
18
|
+
Stop after the summary. Do not begin implementing anything until the user gives you a
|
|
19
|
+
specific task.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Summarise the current nemo-cli project status by reading docs/CURRENT_STATUS.md and the ADR index. Use when the user asks "where are we", "what is the status", "what is in progress", or for a CFD project status read.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Summarise the current state of the project for the user. Read **only**:
|
|
6
|
+
|
|
7
|
+
- `docs/CURRENT_STATUS.md`
|
|
8
|
+
- `docs/decisions/_index.md`
|
|
9
|
+
|
|
10
|
+
Output the summary in this exact shape:
|
|
11
|
+
|
|
12
|
+
````
|
|
13
|
+
In progress:
|
|
14
|
+
- <item> (<short note>)
|
|
15
|
+
|
|
16
|
+
Blocked / open questions:
|
|
17
|
+
- <item> (<why it is blocked>)
|
|
18
|
+
|
|
19
|
+
Recently decided:
|
|
20
|
+
- <ADR id and title>
|
|
21
|
+
|
|
22
|
+
Next priority:
|
|
23
|
+
- <item>
|
|
24
|
+
````
|
|
25
|
+
|
|
26
|
+
Do not read source code. Do not propose changes. The goal is to give the user a
|
|
27
|
+
30-second read of where things stand.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Audit CFD context-file integrity — verify CLAUDE.md size, @-references resolve, ADR index consistency, no duplicated context, and CURRENT_STATUS.md freshness. Use when the user asks to "validate context", "audit docs", or check whether the CFD scaffolding is healthy.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run a CFD context-integrity check. Do not modify files; just report findings.
|
|
6
|
+
|
|
7
|
+
Checks to perform:
|
|
8
|
+
|
|
9
|
+
1. **CLAUDE.md size.** It should be under ~150 lines and consist mostly of
|
|
10
|
+
`@docs/...` references plus the build/run section and critical rules. Flag if
|
|
11
|
+
it has grown into a long-form document.
|
|
12
|
+
2. **`@`-references resolve.** Every `@docs/...` reference in `CLAUDE.md` points to
|
|
13
|
+
a file that exists.
|
|
14
|
+
3. **ADR index integrity.** Every file matching `docs/decisions/[0-9]*.md` is listed
|
|
15
|
+
in `docs/decisions/_index.md`, and every row in the index points to a file that
|
|
16
|
+
exists.
|
|
17
|
+
4. **No duplicated context.** Spot-check that the tech stack is described in
|
|
18
|
+
`docs/STACK.md` only (not also expanded inside `CLAUDE.md` or `ARCHITECTURE.md`),
|
|
19
|
+
and that decision rationale is in the relevant ADR (not duplicated in
|
|
20
|
+
`ARCHITECTURE.md`).
|
|
21
|
+
5. **`CURRENT_STATUS.md` freshness.** Look at the `Last updated:` line. If it is
|
|
22
|
+
more than two working days behind today's date, flag it.
|
|
23
|
+
|
|
24
|
+
Output a short report grouped by check, with `✓` / `✗` and a one-line note for each.
|
|
25
|
+
End with a one-line overall verdict: `Context healthy.` or
|
|
26
|
+
`Context needs attention: <N> issues.`
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
name: Build distribution
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- name: Checkout
|
|
15
|
+
uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: '3.12'
|
|
21
|
+
|
|
22
|
+
- name: Install build backend
|
|
23
|
+
run: python -m pip install --upgrade pip build
|
|
24
|
+
|
|
25
|
+
- name: Build wheel + sdist
|
|
26
|
+
run: python -m build
|
|
27
|
+
|
|
28
|
+
- name: Upload artifacts
|
|
29
|
+
uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: python-package-distributions
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish-to-testpypi:
|
|
35
|
+
name: Publish to TestPyPI
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
environment:
|
|
39
|
+
name: testpypi
|
|
40
|
+
url: https://test.pypi.org/p/nemo-cli
|
|
41
|
+
permissions:
|
|
42
|
+
id-token: write
|
|
43
|
+
steps:
|
|
44
|
+
- name: Download artifacts
|
|
45
|
+
uses: actions/download-artifact@v4
|
|
46
|
+
with:
|
|
47
|
+
name: python-package-distributions
|
|
48
|
+
path: dist/
|
|
49
|
+
|
|
50
|
+
- name: Publish to TestPyPI
|
|
51
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
52
|
+
with:
|
|
53
|
+
repository-url: https://test.pypi.org/legacy/
|
|
54
|
+
skip-existing: true
|
|
55
|
+
|
|
56
|
+
publish-to-pypi:
|
|
57
|
+
name: Publish to PyPI
|
|
58
|
+
needs: publish-to-testpypi
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
environment:
|
|
61
|
+
name: pypi
|
|
62
|
+
url: https://pypi.org/p/nemo-cli
|
|
63
|
+
permissions:
|
|
64
|
+
id-token: write
|
|
65
|
+
steps:
|
|
66
|
+
- name: Download artifacts
|
|
67
|
+
uses: actions/download-artifact@v4
|
|
68
|
+
with:
|
|
69
|
+
name: python-package-distributions
|
|
70
|
+
path: dist/
|
|
71
|
+
|
|
72
|
+
- name: Publish to PyPI
|
|
73
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
74
|
+
with:
|
|
75
|
+
skip-existing: true
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
env/
|
|
13
|
+
|
|
14
|
+
# Tooling caches
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.pyright/
|
|
18
|
+
.mypy_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
htmlcov/
|
|
21
|
+
|
|
22
|
+
# Secrets
|
|
23
|
+
.env
|
|
24
|
+
.env.local
|
|
25
|
+
.env.*.local
|
|
26
|
+
|
|
27
|
+
# OS / editors
|
|
28
|
+
*.log
|
|
29
|
+
.DS_Store
|
|
30
|
+
.idea/
|
|
31
|
+
.vscode/
|
|
32
|
+
|
|
33
|
+
# Claude Code local-only settings (per-user permissions, etc.)
|
|
34
|
+
.claude/settings.local.json
|
|
35
|
+
|
|
36
|
+
# CFD current project status — managed locally, not shared in the repo
|
|
37
|
+
docs/CURRENT_STATUS.md
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
Versioning policy and release process: [ADR-007](docs/decisions/007-versioning-and-changelog.md).
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
## [0.0.1] - 2026-06-04
|
|
12
|
+
|
|
13
|
+
Initial public release on TestPyPI. The CLI is functional but versioned
|
|
14
|
+
under `0.0.x` to signal that the public surface may still change without
|
|
15
|
+
notice until `0.1.0` (see ADR-007).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Authentication.** `nemo login` / `nemo logout` / `nemo whoami`.
|
|
20
|
+
Credentials read from `NEMO_USERNAME` / `NEMO_PASSWORD` (env vars only,
|
|
21
|
+
never persisted by this CLI). Bearer token cached as JSON via
|
|
22
|
+
`platformdirs`. Proactive refresh when the cached JWT expires within
|
|
23
|
+
60s; reactive `RefreshToken → SignIn` ladder on `401`. Credentials
|
|
24
|
+
touch the wire only on bootstrap and as a last resort. (ADR-003,
|
|
25
|
+
ADR-012)
|
|
26
|
+
- **Instruments listing.**
|
|
27
|
+
- `nemo instruments local` — Chilean instruments via
|
|
28
|
+
`GET /api/shared/Instrumentos/FiltrarInstrumentos`. Filters:
|
|
29
|
+
`--search`, `--classes`, `--page`, `--limit`.
|
|
30
|
+
- `nemo instruments international` — US-listed assets via
|
|
31
|
+
`GET /api/frontoffice/shared/Asset`. Filters: `--search`,
|
|
32
|
+
`--exchange`, `--page`, `--page-size`.
|
|
33
|
+
- Both commands accept `--json` for a machine-readable payload of the
|
|
34
|
+
form `{ market, page, page_size, total, items: [...] }`. (ADR-006)
|
|
35
|
+
- **Instrument price history.** `nemo instruments prices --id <ID>`
|
|
36
|
+
returns ~1 year of daily prices for a local Chilean instrument
|
|
37
|
+
(`GET /api/frontoffice/shared/PublicadorPrecio/GetPreciosInstrumento`),
|
|
38
|
+
with computed stats (first/last, min/max with dates, mean, total
|
|
39
|
+
return %, daily-return σ) and an ASCII sparkline. `--json` emits the
|
|
40
|
+
full point series plus stats. **Local instruments only**: the upstream
|
|
41
|
+
endpoint does not serve international assets. (ADR-010)
|
|
42
|
+
- **Portfolio summary.** `nemo portfolio summary` queries
|
|
43
|
+
`GET /api/frontoffice/shared/cartera/CierreCarteraResumidaOnline` and
|
|
44
|
+
returns each holding plus computed P&L and totals (per classification
|
|
45
|
+
+ grand total). Flags: `--account-id`, `--currency`,
|
|
46
|
+
`--with-dividends/--no-dividends`, `--json`. (ADR-008)
|
|
47
|
+
- **Portfolio movements with classification.** `nemo portfolio movements
|
|
48
|
+
--desde <YYYY-MM-DD> --hasta <YYYY-MM-DD>` queries
|
|
49
|
+
`GET /api/frontoffice/shared/MovimientosCajas/Movimientos` and parses
|
|
50
|
+
each movement description into a structured `kind` (`dividend`, `buy`,
|
|
51
|
+
`sell`, `commission`, `cash_in`, `cash_out`, `other`) plus, when
|
|
52
|
+
applicable, a typed `DividendInfo` (ex-date, nemotécnico, per-unit
|
|
53
|
+
amount) or `TradeInfo` (nemotécnico, side). The service computes
|
|
54
|
+
per-nemotécnico aggregates (`by_dividend`, `by_trade`) and global
|
|
55
|
+
totals at the boundary. Endpoint is slow; the call uses a **180s
|
|
56
|
+
timeout** documented in `docs/CONVENTIONS.md`. (ADR-011)
|
|
57
|
+
- **Authenticated HTTP client** at `nemo_cli.api.client.api_request` —
|
|
58
|
+
the single point for portal HTTP, owns token injection and the
|
|
59
|
+
refresh ladder.
|
|
60
|
+
- **Distribution.** `pipx install nemo-cli` (TestPyPI for now);
|
|
61
|
+
`pip install -e .[dev]` for development. `nemo --version` / `-V`
|
|
62
|
+
prints the CLI version from `nemo_cli.__version__`.
|
|
63
|
+
- **Unit-test suite** — 203 tests, ~98% line coverage, mirrors the
|
|
64
|
+
package tree under `tests/`. `respx` mocks `httpx` at the transport
|
|
65
|
+
layer (no real network calls); `typer.testing.CliRunner` drives the
|
|
66
|
+
CLI. No CI/CD wired yet; tests run locally with `pytest`.
|
|
67
|
+
- **Context-First Development scaffolding** — `CLAUDE.md`,
|
|
68
|
+
`docs/ARCHITECTURE.md`, `docs/STACK.md`, `docs/CONVENTIONS.md`,
|
|
69
|
+
`docs/decisions/` (ADRs 001–012 minus 009), and the four CFD skills
|
|
70
|
+
under `.claude/skills/` (`start-session`, `status`, `new-decision`,
|
|
71
|
+
`validate-context`).
|
|
72
|
+
- **GitHub Flow** as the project branching strategy. (ADR-005)
|
|
73
|
+
- **Versioning policy** — SemVer + Keep a Changelog. (ADR-007)
|
|
74
|
+
|
|
75
|
+
[Unreleased]: https://github.com/albertomarturelo/nemo-cli/compare/v0.0.1...HEAD
|
|
76
|
+
[0.0.1]: https://github.com/albertomarturelo/nemo-cli/releases/tag/v0.0.1
|
nemo_cli-0.0.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What This Project Does
|
|
6
|
+
|
|
7
|
+
`nemo-cli` is a personal command-line tool to inspect holdings on Chilean
|
|
8
|
+
stockbroker portals. Currently compatible with the Vector Capital client portal
|
|
9
|
+
at `https://portalclientes.vectorcapital.cl/api`, which exposes three sub-
|
|
10
|
+
prefixes the CLI calls into: `/publicapi` (auth), `/shared` (local Chilean
|
|
11
|
+
instruments), and `/frontoffice` (international assets and portfolio summary).
|
|
12
|
+
The CLI authenticates with the public `SignIn` endpoint using the user's own
|
|
13
|
+
credentials provided via environment variables, caches the bearer token
|
|
14
|
+
locally, and never redistributes data.
|
|
15
|
+
|
|
16
|
+
> **Non-affiliation.** This project is not affiliated, endorsed, or sponsored
|
|
17
|
+
> by Vector Capital S.A. Corredores de Bolsa or any other broker. The README
|
|
18
|
+
> carries the user-facing version of this disclaimer.
|
|
19
|
+
|
|
20
|
+
## Methodology
|
|
21
|
+
|
|
22
|
+
This project follows **Context-First Development (CFD)**. The methodology itself lives
|
|
23
|
+
in `context-first-development.md` at the repo root and is the source of truth for *how*
|
|
24
|
+
context, decisions, and sessions are managed here. Read it once if you are new to the
|
|
25
|
+
project; do not re-read it every session.
|
|
26
|
+
|
|
27
|
+
## Architecture
|
|
28
|
+
|
|
29
|
+
@docs/ARCHITECTURE.md
|
|
30
|
+
|
|
31
|
+
## Tech Stack
|
|
32
|
+
|
|
33
|
+
@docs/STACK.md
|
|
34
|
+
|
|
35
|
+
## Conventions
|
|
36
|
+
|
|
37
|
+
@docs/CONVENTIONS.md
|
|
38
|
+
|
|
39
|
+
## Current Status
|
|
40
|
+
|
|
41
|
+
Tracked locally only — `docs/CURRENT_STATUS.md` is gitignored, so each clone
|
|
42
|
+
maintains its own working notes. Not loaded automatically; the CFD skills
|
|
43
|
+
(`/start-session`, `/status`) read it from disk when present.
|
|
44
|
+
|
|
45
|
+
## Key Decisions
|
|
46
|
+
|
|
47
|
+
@docs/decisions/_index.md
|
|
48
|
+
|
|
49
|
+
## Build & Run
|
|
50
|
+
|
|
51
|
+
- Install for everyday use (recommended): `pipx install .`
|
|
52
|
+
- Reinstall after local changes: `pipx install --force .`
|
|
53
|
+
- Install editable with dev tools: `pip install -e .[dev]`
|
|
54
|
+
- Run without installing: `python -m nemo_cli <command>`
|
|
55
|
+
- Run after install: `nemo <command>`
|
|
56
|
+
- Typecheck: `pyright`
|
|
57
|
+
- Lint: `ruff check .`
|
|
58
|
+
- Tests: `pytest`
|
|
59
|
+
- Run a single test file: `pytest tests/test_<file>.py`
|
|
60
|
+
|
|
61
|
+
## Environment
|
|
62
|
+
|
|
63
|
+
Credentials are loaded from environment variables (via `python-dotenv`). See
|
|
64
|
+
`.env.example`.
|
|
65
|
+
|
|
66
|
+
| Variable | Required | Purpose |
|
|
67
|
+
|--------------------|----------|----------------------------------|
|
|
68
|
+
| `NEMO_USERNAME` | yes | Email used to sign in |
|
|
69
|
+
| `NEMO_PASSWORD` | yes | Password used to sign in |
|
|
70
|
+
|
|
71
|
+
The Vector API base URL is hardcoded in `nemo_cli.config.API_BASE_URL` — there is
|
|
72
|
+
no env override (see ADR-004). Reintroduce one via a new ADR if a staging environment
|
|
73
|
+
appears.
|
|
74
|
+
|
|
75
|
+
## Critical Rules
|
|
76
|
+
|
|
77
|
+
- **All HTTP traffic to the Vector API must go through `api_request()` in
|
|
78
|
+
`src/nemo_cli/api/client.py`.** That function owns token retrieval, caching, and
|
|
79
|
+
the 401-retry-after-refresh flow. Calling `httpx.request(...)` directly from a
|
|
80
|
+
command bypasses re-authentication and will cause silent failures when tokens
|
|
81
|
+
expire. The only allowed exception is `nemo_cli.auth.service.sign_in`, which is
|
|
82
|
+
the bootstrap call. See ADR-003.
|
|
83
|
+
- **Never commit `.env` or any real credential.** `.env.example` is the only template
|
|
84
|
+
in version control.
|
|
85
|
+
- **Document significant decisions as ADRs *before* writing the code that implements
|
|
86
|
+
them.** Use the `/new-decision` skill. Update `docs/decisions/_index.md` in the
|
|
87
|
+
same change.
|
|
88
|
+
See ADR-001 for the rationale.
|
|
89
|
+
- **English for all model-facing context** (CLAUDE.md, docs/, ADRs, slash commands,
|
|
90
|
+
code identifiers, code comments). PR descriptions and chat with the user can be in
|
|
91
|
+
Spanish — the user works in Spanish.
|
|
92
|
+
- **Update `docs/CURRENT_STATUS.md` before closing every session.** This is how the
|
|
93
|
+
next session knows what was in flight. CFD treats this as non-negotiable.
|
|
94
|
+
- **The Vector API response shapes are not yet officially typed.** When integrating a
|
|
95
|
+
new endpoint, capture a real response (redacted), then add a typed dataclass /
|
|
96
|
+
`TypedDict` in the module that owns the call. Do not assume field names from
|
|
97
|
+
external documentation without verification.
|
nemo_cli-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alberto Marturelo Lorenzo
|
|
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.
|