danielmiessler / danielmiessler/LifeOS

Five .env parsers disagree: two return an empty env on CRLF files, three mis-key an export prefix

Open
#2,100 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
19k
Forks
2.5k
Avg merge
8d 17h
Merged PRs (30d)
1

Description

### Version

LifeOS 7.40.4 (verified against `5e2f2e8`)

### What is broken

The install carries five independent `.env` parsers, and they disagree on three inputs. Two of those disagreements are defects. `PULSE/checks/calendar.ts` and `TOOLS/YouTubeApi.ts` parse each line with `^([^#=]+)=(.*)$`, and JavaScript treats a carriage return as a line terminator, so `.` will not match one and `$` will not match before one. Given a `.env` saved with Windows line endings, neither file returns a truncated value: both return an empty object, and every caller then reports its credential as absent. `TOOLS/healthsync/store.ts` splits on `/\r?\n/` and is unaffected, so the same credential file works for the health-sync subsystem and fails for these two. Separately, a `.env` written with `export FOO=bar`, which is what anyone sourcing the file in a shell will have, yields a key named literally `export FOO` in `PULSE/pulse.ts`, `PULSE/checks/calendar.ts` and `TOOLS/YouTubeApi.ts`; `FOO` is never set. `TOOLS/healthsync/store.ts` strips the prefix and is again the only one that behaves.

### Where (file:line)

`LIFEOS/PULSE/checks/calendar.ts:22` and `LIFEOS/TOOLS/YouTubeApi.ts:65` (carriage return); `LIFEOS/PULSE/pulse.ts:30`, `LIFEOS/PULSE/checks/calendar.ts:22`, `LIFEOS/TOOLS/YouTubeApi.ts:65` and `LIFEOS/TOOLS/PangramScore.ts:70` (`export` prefix). Correct behaviour for comparison: `LIFEOS/TOOLS/healthsync/store.ts:149`.

### Repro on a clean tree

```shell
# Fake HOME so nothing touches a real install.
mkdir -p /tmp/lifeos-crlf/.claude

# Same two keys, Windows line endings.
printf 'YOUTUBE_API_KEY=abc123\r\nYOUTUBE_CHANNEL_ID=UC_test\r\n' > /tmp/lifeos-crlf/.claude/.env
HOME=/tmp/lifeos-crlf bun LIFEOS/TOOLS/YouTubeApi.ts
# Error: YOUTUBE_API_KEY not set

# Identical keys, Unix line endings.
printf 'YOUTUBE_API_KEY=abc123\nYOUTUBE_CHANNEL_ID=UC_test\n' > /tmp/lifeos-crlf/.claude/.env
HOME=/tmp/lifeos-crlf bun LIFEOS/TOOLS/YouTubeApi.ts
# prints usage — the key was accepted

# The export prefix, Unix line endings.
printf 'export YOUTUBE_API_KEY=abc123\n' > /tmp/lifeos-crlf/.claude/.env
HOME=/tmp/lifeos-crlf bun LIFEOS/TOOLS/YouTubeApi.ts
# Error: YOUTUBE_API_KEY not set

# Second file, same cause.
printf 'GOOGLE_CALENDAR_REFRESH_TOKEN=rt\r\nGMAIL_CLIENT_ID=cid\r\nGMAIL_CLIENT_SECRET=cs\r\n' > /tmp/lifeos-crlf/.claude/.env
HOME=/tmp/lifeos-crlf bun LIFEOS/PULSE/checks/calendar.ts
# GOOGLE_CALENDAR_REFRESH_TOKEN not set

printf 'GOOGLE_CALENDAR_REFRESH_TOKEN=rt\nGMAIL_CLIENT_ID=cid\nGMAIL_CLIENT_SECRET=cs\n' > /tmp/lifeos-crlf/.claude/.env
HOME=/tmp/lifeos-crlf bun LIFEOS/PULSE/checks/calendar.ts
# Calendar check failed: Token refresh failed — the keys parsed, the fake values were rejected by Google
```

### Negative control

On unpatched 7.40.4, with `YOUTUBE_API_KEY=abc123` present in `~/.claude/.env` and the file saved with CRLF endings, `TOOLS/YouTubeApi.ts` prints `Error: YOUTUBE_API_KEY not set` and exits. The same file with LF endings prints the usage banner. `PULSE/checks/calendar.ts` reports `GOOGLE_CALENDAR_REFRESH_TOKEN not set` on the CRLF file and proceeds to a token refresh on the LF file. With `export ` prefixes and LF endings, `TOOLS/YouTubeApi.ts` reports the key unset while the file plainly contains it.

Behaviour of each parser against the cases that separate them, each run verbatim:

| Input | `pulse.ts` | `calendar.ts` / `YouTubeApi.ts` | `healthsync/store.ts` |
|---|---|---|---|
| `A=1\r\n` | `{"A":"1"}` | `{}` | `{"A":"1"}` |
| `export A=1\n` | `{"export A":"1"}` | `{"export A":"1"}` | `{"A":"1"}` |
| `1BAD=x\nA=1\n` | `{"1BAD":"x","A":"1"}` | `{"1BAD":"x","A":"1"}` | `{"A":"1"}` |

### Suggested fix

The parser in `TOOLS/healthsync/store.ts` already handles all three rows. Promoting it to a shared module and having the other four call it removes both defects and stops the five drifting further apart. Untested as a refactor of this tree, though the same consolidation is running in a fork with the behaviour table above as its test cases, and I am happy to open a PR if that would help.

One caveat on scope: `PULSE/pulse.ts` loads `.env` before the billing guard that strips `ANTHROPIC_API_KEY` and `ANTHROPIC_AUTH_TOKEN`, so any replacement there has to keep that ordering.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with TOOLS/healthsync/store.ts:149, then compare its parser with PULSE/pulse.ts, PULSE/checks/calendar.ts, TOOLS/YouTubeApi.ts, and TOOLS/PangramScore.ts at the lines listed. Use the CRLF, export-prefix, and invalid-key cases in the issue as the initial checks. Done means all five parsers agree on those cases while PULSE/pulse.ts preserves the billing-guard ordering.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.