> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nora.my/llms.txt
> Use this file to discover all available pages before exploring further.

# 파이핑·시크릿

> 시크릿 값, 파일 본문, stdin을 CLI에 안전하게 공급하는 방법

많은 CLI 명령이 이런 콘텐츠를 받음:

* 민감한 것(API 키, 토큰, DB URL).
* 큰 것(멀티라인 프롬프트, 마크다운 노트, JSON 페이로드).
* 다른 프로세스에서 온 것(이전 명령의 출력).

CLI가 모든 서브커맨드에서 일관된 입력 문법을 지원.

## 입력 모드 셋

CLI가 시크릿·파일·파이프가 될 수 있는 값을 받는 곳에서 이렇게 인식:

* `?` **인터랙티브 프롬프트**. 시크릿 필드는 가려서, 아니면 그대로 입력.
* `-` **stdin에서 한 줄 읽기**. 파이프에 좋음.
* `@<path>` **파일에서 읽기**. 전체 파일 내용이 값이 됨.
* 그 밖의 값 **리터럴로 사용**. 시크릿 필드면 셸 히스토리 경고.

예:

```bash theme={null}
# 인터랙티브 프롬프트
nora tools headers add t_api --name Authorization --value ?

# 이전 명령에서 파이프
echo -n "$MY_TOKEN" | nora providers set openai --stdin

# 파일에서
nora agents update ag_1 --set-prompt-file prompts/support.md

# 리터럴 (시크릿엔 피할 것)
nora tools headers add t_api --name Authorization --value "Bearer sk-..."
```

## 어느 필드가 어느 모드를 받나

시크릿이 아닌 필드 대부분(이름, 설명, 프롬프트)이 파일 입력에 `@<path>`를 받음. 시크릿에 민감한 필드(`--api-key`, `--auth-value`, 헤더 값, DB URL)도 가림 프롬프트에 `?`, stdin에 `-`를 받음.

애매하면 `<command> --help`가 플래그마다 입력 계약을 표시.

## 다른 CLI에서 값 읽기

리터럴을 넘길 수 있는 곳이면 서브셸도 넘길 수 있음:

```bash theme={null}
nora providers set openai --stdin <<< "$(vault read -field=key secret/nora/openai)"

nora tools headers add t_api \
  --name Authorization \
  --value "Bearer $(aws secretsmanager get-secret-value --secret-id nora/api --query SecretString --output text)"
```

## 멀티라인 콘텐츠 넘기기

멀티라인이면 무엇이든 `@file`로. 프롬프트, 노트 본문, JSON 페이로드:

```bash theme={null}
nora agents update ag_1 --set-prompt-file prompts/support-v3.md

nora memory notes upsert sp_wiki \
  --path playbooks/refunds.md \
  --body @refunds.md
```

또는 heredoc + stdin:

```bash theme={null}
cat <<'PROMPT' | nora agents update ag_1 --set-prompt -
너는 지원 어시스턴트야.
결제·환불·계정 이슈 질문에 답해.

확신이 없으면 분명히 말해.
PROMPT
```

주의: 모든 명령이 그 플래그에 `-`를 지원하는 건 아님. `--help`로 확인.

## 시크릿과 셸 히스토리

명령줄에 시크릿을 리터럴로 넘기면 셸 히스토리에 남음. 위험할 뿐 아니라 보안 정책 위반일 때가 많음.

증상:

```bash theme={null}
# 나쁨: 이게 ~/.bash_history / ~/.zsh_history에 남음
nora providers set openai sk-abc123...
```

해결:

```bash theme={null}
# 좋음 (아무거나):
nora providers set openai --env OPENAI_API_KEY       # env var
nora providers set openai --stdin < ~/.nora/openai   # 파일 (0600 권한)
echo "$OPENAI_API_KEY" | nora providers set openai --stdin
nora providers set openai --stdin                    # 인터랙티브 프롬프트 (붙여넣기)
```

CLI가 시크릿 모양 리터럴을 감지하면 경고하지만 거절하진 않음. 이유가 있으면 그냥 진행 가능.

## nora 명령 사이 파이핑

많은 명령이 `--json`을 지원하므로 조합 가능:

```bash theme={null}
# superseded 문서 전부 삭제 (확인과 함께)
nora documents list --json | \
  jq -r '.[] | select(.superseded) | .id' | \
  xargs -n1 nora documents delete
```

```bash theme={null}
# 아직 배포 안 한 draft가 있는 Flow 전부 배포
nora flows list --json | \
  jq -r '.[] | select(.draft_differs_from_published) | .slug' | \
  while read slug; do
    nora flows publish "$slug" --note "배치 배포 $(date +%Y-%m-%d)"
  done
```

## jq로 복잡한 구조 읽기

`--json` 출력 대부분이 배열이나 객체. 흔한 패턴:

```bash theme={null}
# 첫 agent 블록의 ID
nora flows get support | jq -r '.blocks[] | select(.kind=="agent") | .id' | head -n1

# 트레이스 비용 합
nora traces list --from 2026-07-01 --json | jq '[.[].cost_cents] | add / 100'

# 중첩 필드로 필터
nora agents sources list ag_1 --json | jq '.[] | select(.preset=="high-precision")'
```

## CI 용 환경변수

CLI가 auth와 워크스페이스 맥락용 env var를 읽음:

```yaml theme={null}
env:
  NORA_TOKEN: ${{ secrets.NORA_TOKEN }}
  NORA_TENANT: ${{ vars.NORA_WORKSPACE }}
  OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
```

그다음 명령은:

```bash theme={null}
nora providers set openai --env OPENAI_API_KEY
nora flows publish support --note "$GIT_COMMIT_MSG"
```

명령줄에 자격증명이 없고, 디스크에 상태를 안 씀.

## 인용 룰

Bash와 zsh가 셸 값의 특수 문자를 다르게 처리. 값에 공백·`$`·`!`·`#`가 있으면:

```bash theme={null}
# 안전: 작은따옴표가 모든 걸 리터럴로 보존
nora agents update ag_1 --set-prompt '너는 $friendly 야.'

# 또는 인용을 아예 피하려면 --set-prompt-file 사용
nora agents update ag_1 --set-prompt-file prompt.md
```

보간이 많은 JSON 페이로드는 `jq -c`로 JSON 파일을 한 줄로 압축:

```bash theme={null}
nora retrieval presets upsert my-preset \
  --name "내 프리셋" \
  --config "$(jq -c . preset.json)"
```

## Exit 코드

CLI가 표준 Unix exit 코드를 따름:

* `0` 성공.
* `1` 일반 에러.
* `2` 오용(잘못된 플래그, 필수 인자 누락).
* `4` 인증 안 됨.
* `8` 권한 거부(auth는 됐지만 역할 부족).
* `16` 서버 에러(플랫폼의 5xx).
* `64` 명령 없음 또는 형식 잘못.

CI가 exit 코드로 막을 수 있음:

```bash theme={null}
if ! nora flows publish support --note "$MSG"; then
  echo "배포 실패"
  exit 1
fi
```

## 뭔가 안 될 때

* 전체 요청/응답을 보려면 `--verbose`.
* 워크스페이스와 토큰을 확인하려면 `nora auth status`.
* 고정된 Flow 확인: `nora flows current`.
* CI에서 exit 코드 echo: `nora flows publish support; echo "Exit: $?"`.
