Use user config directory for runtime state

This commit is contained in:
2026-06-09 05:31:19 +00:00
parent 6d04f20de1
commit 9f29755f0a
16 changed files with 158 additions and 73 deletions
+35 -19
View File
@@ -370,7 +370,7 @@
| Key | Type | Meaning |
| --- | --- | --- |
| `namespace` | string | `.openstock` 아래 최상위 디렉터리 이름입니다. 예: `universe`, `opendart`. |
| `namespace` | string | cache root 아래 최상위 디렉터리 이름입니다. 예: `universe`, `opendart`. |
| `files` | number | namespace 안의 파일 수입니다. |
| `bytes` | number | namespace 안의 총 파일 크기입니다. |
@@ -397,7 +397,23 @@
## Environment Variables
`.env` 파일에서 읽고, 일부 값은 명령 실행 중 갱신됩니다.
설정 파일은 기본적으로 `~/.config/openstock/.env`에서 읽고, 일부 값은 명령 실행 중 갱신됩니다. `OPENSTOCK_CONFIG_DIR`를 설정하면 이 루트 디렉터리를 바꿀 수 있습니다. 예를 들어 `OPENSTOCK_CONFIG_DIR=/tmp/openstock-test`이면 env 파일은 `/tmp/openstock-test/.env`, 캐시는 `/tmp/openstock-test/cache` 아래에 생성됩니다.
바이너리로 빌드해 어느 디렉터리에서 실행하더라도 기본 설정/캐시 위치는 동일합니다.
```bash
mkdir -p ~/.config/openstock
cp .env.example ~/.config/openstock/.env
```
이전 개발 버전에서 프로젝트 루트의 `.env``.openstock`을 사용했다면 다음처럼 옮길 수 있습니다.
```bash
mkdir -p ~/.config/openstock
cp .env ~/.config/openstock/.env
mkdir -p ~/.config/openstock/cache
cp -R .openstock/* ~/.config/openstock/cache/
```
| Name | Required For | Direction | Description |
| --- | --- | --- | --- |
@@ -410,20 +426,20 @@
| `KIS_ACCOUNT` | `account status`, `order buy`, `order sell`, `order status` | read | `CANO-ACNT_PRDT_CD` 형식 계좌입니다. 예: `12345678-01`. |
| `OPENDART_API_KEY` | `dart *` | read | OpenDART API 인증키입니다. |
`.env``.gitignore` 대상입니다. 토큰과 계좌번호를 커밋하지 마십시오.
프로젝트 루트의 `.env`더 이상 런타임 기본 경로가 아닙니다. 토큰과 계좌번호를 커밋하지 마십시오.
## Cache and File IO
로컬 캐시는 `.openstock` 아래에 생성되며 `.gitignore` 대상입니다.
로컬 캐시는 기본적으로 `~/.config/openstock/cache` 아래에 생성됩니다. `OPENSTOCK_CONFIG_DIR`를 사용하면 `{OPENSTOCK_CONFIG_DIR}/cache` 아래에 생성됩니다.
| Path | Writer | Reader | Retention | Description |
| --- | --- | --- | --- | --- |
| `.openstock/universe/kind/latest.json` | `universe sync` | `universe status/list/chunks/validate` | protected | KIND 상장법인목록 최신 normalized stock list입니다. |
| `.openstock/universe/kind/meta.json` | `universe sync` | `universe status/*` | protected | universe cache metadata입니다. |
| `.openstock/universe/kind/YYYY-MM-DD.json` | `universe sync` | audit/manual use | max 7 files or 25MB | 날짜별 universe snapshot입니다. |
| `.openstock/opendart/corp_codes.json` | `dart sync`, `dart corp/disclosures/show` on cache miss | `dart corp/disclosures/show` | latest only | 상장사 `stock_code` to `corp_code` 매핑입니다. |
| `.openstock/opendart/corp_codes_meta.json` | `dart sync` | `dart status` | latest only | OpenDART corp code cache metadata입니다. |
| `.openstock/opendart/documents/{rcept_no}.zip` | `dart document`, `dart show` | `dart document`, `dart show` | max 100 files or 200MB | 공시서류 원본 ZIP cache입니다. |
| `~/.config/openstock/cache/universe/kind/latest.json` | `universe sync` | `universe status/list/chunks/validate` | protected | KIND 상장법인목록 최신 normalized stock list입니다. |
| `~/.config/openstock/cache/universe/kind/meta.json` | `universe sync` | `universe status/*` | protected | universe cache metadata입니다. |
| `~/.config/openstock/cache/universe/kind/YYYY-MM-DD.json` | `universe sync` | audit/manual use | max 7 files or 25MB | 날짜별 universe snapshot입니다. |
| `~/.config/openstock/cache/opendart/corp_codes.json` | `dart sync`, `dart corp/disclosures/show` on cache miss | `dart corp/disclosures/show` | latest only | 상장사 `stock_code` to `corp_code` 매핑입니다. |
| `~/.config/openstock/cache/opendart/corp_codes_meta.json` | `dart sync` | `dart status` | latest only | OpenDART corp code cache metadata입니다. |
| `~/.config/openstock/cache/opendart/documents/{rcept_no}.zip` | `dart document`, `dart show` | `dart document`, `dart show` | max 100 files or 200MB | 공시서류 원본 ZIP cache입니다. |
캐시 상태와 정리는 다음 명령으로 수행합니다.
@@ -466,10 +482,10 @@ KIS 실전 API 접근 토큰을 발급하거나 유효한 기존 토큰을 재
| --- | --- |
| Input | `--appkey`, `--appsecret`, `--force` |
| Env read | `KIS_APPKEY`, `KIS_APPSECRET`, `KIS_ACCESS_TOKEN`, `KIS_ACCESS_TOKEN_EXPIRED_AT` |
| Env write | `KIS_APPKEY`, `KIS_APPSECRET`, `KIS_ACCESS_TOKEN`, `KIS_ACCESS_TOKEN_EXPIRED_AT`, `KIS_TOKEN_TYPE`, `KIS_ACCESS_TOKEN_EXPIRES_IN` |
| Config write | `~/.config/openstock/.env` `KIS_APPKEY`, `KIS_APPSECRET`, `KIS_ACCESS_TOKEN`, `KIS_ACCESS_TOKEN_EXPIRED_AT`, `KIS_TOKEN_TYPE`, `KIS_ACCESS_TOKEN_EXPIRES_IN` |
| External IO | `POST https://openapi.koreainvestment.com:9443/oauth2/tokenP` only when token is missing/expired or `--force` is used |
| Output fields | `broker`, `status`, `force`, `credential_source`, `token_storage`, `side_effect` |
| Side effect | writes auth state to `.env` |
| Side effect | writes auth state to `~/.config/openstock/.env` |
### `openstock api call <endpoint> --param KEY=VALUE`
@@ -480,7 +496,7 @@ KIS endpoint를 직접 GET 호출합니다. `tr_id` 파라미터는 HTTP header
| Input | `endpoint`, repeated `--param KEY=VALUE` |
| Env read | `KIS_ACCESS_TOKEN`, `KIS_APPKEY`, `KIS_APPSECRET` |
| External IO | KIS endpoint GET |
| File IO | `.env` read |
| File IO | `~/.config/openstock/.env` read |
| Output fields | `broker`, `endpoint`, `params`, `request_semantics`, `response`, `response_semantics` |
| Raw | parsed KIS response |
| Side effect | endpoint에 따라 다름. typed command 사용 권장 |
@@ -508,7 +524,7 @@ KIND 상장법인목록을 받아 stock universe cache를 갱신합니다.
| --- | --- |
| Input | `--force` |
| External IO | `GET https://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13` |
| File write | `.openstock/universe/kind/latest.json`, `meta.json`, `YYYY-MM-DD.json` |
| File write | `~/.config/openstock/cache/universe/kind/latest.json`, `meta.json`, `YYYY-MM-DD.json` |
| Output fields | `source`, `cache_date`, `refreshed_at`, `refreshed`, `stock_count`, `counts_by_market` |
| Raw | universe metadata |
| Side effect | writes/updates local cache; prunes old snapshots |
@@ -518,7 +534,7 @@ KIND 상장법인목록을 받아 stock universe cache를 갱신합니다.
| Direction | Data |
| --- | --- |
| Input | 없음 |
| File read | `.openstock/universe/kind/latest.json`, `meta.json` |
| File read | `~/.config/openstock/cache/universe/kind/latest.json`, `meta.json` |
| Output fields | `source`, `cache_date`, `refreshed_at`, `refreshed`, `stock_count`, `counts_by_market` |
| Side effect | 없음 |
@@ -592,7 +608,7 @@ OpenDART 고유번호 ZIP/XML을 받아 상장사 `stock_code` to `corp_code` ca
| Input | `--force` |
| Env read | `OPENDART_API_KEY` |
| External IO | `GET https://opendart.fss.or.kr/api/corpCode.xml` |
| File write | `.openstock/opendart/corp_codes.json`, `corp_codes_meta.json` |
| File write | `~/.config/openstock/cache/opendart/corp_codes.json`, `corp_codes_meta.json` |
| Output fields | `source`, `cache_date`, `refreshed_at`, `refreshed`, `total_count`, `listed_count` |
| Side effect | writes/updates local cache |
@@ -642,7 +658,7 @@ KRX 종목코드를 OpenDART 고유번호로 변환합니다.
| Input | `rcept_no`: 14자리 접수번호, `--force`, `--max-chars` |
| Env read | `OPENDART_API_KEY` |
| External IO | `GET https://opendart.fss.or.kr/api/document.xml` |
| File read/write | `.openstock/opendart/documents/{rcept_no}.zip` |
| File read/write | `~/.config/openstock/cache/opendart/documents/{rcept_no}.zip` |
| Output fields | `rcept_no`, `source`, `viewer_url`, `cached`, `zip_path`, `zip_bytes`, `files`, `text`, `text_chars`, `truncated` |
| Raw | same document object |
| Side effect | writes ZIP cache; prunes old document ZIP files |
@@ -720,7 +736,7 @@ KIS 계좌 잔고와 보유종목을 조회합니다.
| Direction | Data |
| --- | --- |
| Input | 없음 |
| File read | `.openstock` recursively |
| File read | `~/.config/openstock/cache` recursively |
| Output fields | `root`, `exists`, `total_files`, `total_bytes`, `namespaces` |
| Side effect | 없음 |
@@ -731,7 +747,7 @@ KIS 계좌 잔고와 보유종목을 조회합니다.
| Direction | Data |
| --- | --- |
| Input | `--dry-run` |
| File read | `.openstock` cache directories |
| File read | `~/.config/openstock/cache` directories |
| File delete | old universe snapshots, old OpenDART document ZIPs unless `--dry-run` |
| Output fields | `dry_run`, `deleted_files`, `deleted_bytes`, `reports` |
| Side effect | deletes local cache files unless dry-run |