{"_id":"@bluenotelogic/harness","name":"@bluenotelogic/harness","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@bluenotelogic/harness","version":"0.1.0","description":"One command to point a machine at Blue Note Memory (mem.bnlgit.com). Writes a TOKENLESS MCP config — OAuth-capable hosts hold their own credentials, so nothing secret lands in a repo file.","type":"module","bin":{"bnl-harness":"dist/index.js"},"main":"./dist/index.js","scripts":{"build":"tsc","lint":"tsc --noEmit","test":"node --test test/*.test.js","pretest":"npm run build","prepublishOnly":"npm run build && npm test"},"engines":{"node":">=20"},"devDependencies":{"@types/node":"^22.0.0","typescript":"^5.6.0"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"https://git.bluenotelogic.com/bnl/bnlgit-harness"},"keywords":["mcp","model-context-protocol","oauth","claude-code","codex","bnlgit"],"license":"Apache-2.0","author":{"name":"Blue Note Logic"},"gitHead":"7b48279d785e78f9d5f5fdc98faca5c849dcdfae","types":"./dist/index.d.ts","_id":"@bluenotelogic/harness@0.1.0","_nodeVersion":"24.13.1","_npmVersion":"11.8.0","dist":{"integrity":"sha512-4Gd2iYQUnpFZTbaQ9FoZ0lCHjgCIjRTF06vGcDgKPAJUjXVSCnaAq0wkGCmsbbjtJZ3Ca6WxHrojMtoWA27r2w==","shasum":"64dd49edaddc9dd1d28895b3725cc51345f6e056","tarball":"https://registry.npmjs.org/@bluenotelogic/harness/-/harness-0.1.0.tgz","fileCount":15,"unpackedSize":103409,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDJ8wmQkv8YigmOgKU7xq1pSp2UZgTMFm3Jc1ebbbe42AIgIm5ASM1IPUV2PTvQDilvtux2CwqKQEJEB0L+zNhPLhY="}]},"_npmUser":{"name":"bluenotelogic","email":"dave@bluenotelogic.com"},"directories":{},"maintainers":[{"name":"bluenotelogic","email":"dave@bluenotelogic.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/harness_0.1.0_1786590290524_0.10861544753547903"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-13T03:04:50.318Z","0.1.0":"2026-08-13T03:04:50.677Z","modified":"2026-08-13T03:04:50.913Z"},"maintainers":[{"name":"bluenotelogic","email":"dave@bluenotelogic.com"}],"description":"One command to point a machine at Blue Note Memory (mem.bnlgit.com). Writes a TOKENLESS MCP config — OAuth-capable hosts hold their own credentials, so nothing secret lands in a repo file.","keywords":["mcp","model-context-protocol","oauth","claude-code","codex","bnlgit"],"repository":{"type":"git","url":"https://git.bluenotelogic.com/bnl/bnlgit-harness"},"author":{"name":"Blue Note Logic"},"license":"Apache-2.0","readme":"# @bluenotelogic/harness\n\nPoint a machine at [Blue Note Memory](https://mem.bnlgit.com) in one command.\n\n```bash\nnpx @bluenotelogic/harness init\n```\n\nThat's it. A browser opens, you sign in with your Blue Note Account, and the CLI writes a\nworking MCP config into the current repo.\n\n## What it writes — and what it deliberately does not\n\n```json\n{ \"mcpServers\": { \"mem\": { \"type\": \"http\", \"url\": \"https://mem.bnlgit.com/mcp\" } } }\n```\n\n**There is no token in that file.** Claude Code and VS Code discover authentication from the\nendpoint's `401 + WWW-Authenticate`, run the OAuth flow themselves, and store their own\ncredentials in their own keychain. So the file is safe to commit, safe to share with a\nteammate, and there is nothing in it to rotate.\n\nThat is the entire point of this tool. The setup it replaces meant pasting a bearer token by\nhand into `.mcp.json`, `~/.claude.json`, `~/.codex/config.toml` and a VS Code roaming\nprofile — and rotating anything meant editing every one of them again.\n\n## Codex and CI\n\nThose hosts cannot do OAuth yet, so they need a real credential:\n\n```bash\nnpx @bluenotelogic/harness init --codex\n```\n\nThe minted token goes to `~/.codex/.env` and is referenced from `config.toml` by name\n(`bearer_token_env_var`), so the config file stays safe to read over someone's shoulder — and\nthe token still never touches the repo. Minting is opt-in: without `--codex` or\n`--mint-token`, this CLI creates no credential and no database row.\n\nFor CI, skip the browser entirely with a token you already hold:\n\n```bash\nnpx @bluenotelogic/harness init --token \"$BNL_MEMORY_MCP_TOKEN\"\n```\n\n## Headless machines\n\n```bash\nnpx @bluenotelogic/harness init --device\n```\n\nPrints a short code and a URL to open on any other device. Standard RFC 8628 device flow.\n\n## Options\n\n| Flag | Effect |\n|---|---|\n| `--dry-run` | Show every file that would change, write nothing |\n| `--url <base>` | Point at a self-hosted deployment (default `https://mem.bnlgit.com`) |\n| `--dir <path>` | Repo to configure (default: current directory) |\n| `--device` | Device-code login for headless boxes and SSH sessions |\n| `--token <token>` | Use an existing token instead of logging in |\n| `--mint-token` | Also mint a token for hosts that cannot do OAuth |\n| `--codex` | Configure Codex too (implies `--mint-token`) |\n| `--harness-home <dir>` | Materialize hosted model routing into `<dir>/state/routing/` |\n| `--server-name <name>` | Override the MCP server key written into `.mcp.json` |\n| `--no-browser` | Print the login URL instead of opening a browser |\n\nRun `--dry-run` first if you like seeing before you commit. It prints the full contents of\nevery file it would touch.\n\n## It will not clobber your config\n\nEvery write reads what is already on disk and replaces **only** the keys it owns. An\nunrelated MCP server in your `.mcp.json` survives untouched; so do unrelated top-level keys,\nyour Codex settings, and any hooks in `.claude/settings.local.json`.\n\nIf a file is not valid JSON, the CLI reports it and **leaves it exactly as it found it** —\n\"it looked broken\" is precisely when someone's half-finished hand edit is sitting in it.\n\nThis is not theoretical caution. The shell script this replaces once overwrote three\n`.mcp.json` files that defined unrelated servers; two were recoverable from git and one was\nnot. `test/writers.test.js` pins that behaviour so it cannot happen again.\n\n## How it works\n\n```\n  OAuth 2.1 + PKCE  ──▶  Blue Note ID          (identity: who are you)\n         │\n         ▼\n  POST /api/oidc_exchange.php                  (product: do you have a subscription)\n         │\n         ▼\n  GET  /api/harness_bootstrap.php              (config: what should this machine use)\n         │\n         ▼\n  .mcp.json, routing YAML, optional Codex config\n```\n\nIdentity and entitlement are separate on purpose. A Blue Note Account authenticates a person;\nit does not by itself grant memory access. If you sign in successfully but hold no\nsubscription you get a clear message saying exactly that, rather than a login error that\nsends you looking in the wrong place.\n\n## Requirements\n\nNode 20 or newer. **No runtime dependencies** — PKCE, the loopback listener and the HTTP\nclient are all Node built-ins, so `npx` is fast and there is no dependency tree to audit.\n\n## Development\n\n```bash\nnpm install\nnpm test          # builds, then runs the suite\nnpm run lint      # tsc --noEmit\n```\n\n## Licence\n\nApache-2.0 — © 2026 Blue Note Logic Inc. See [LICENSE](LICENSE).\n\nThis CLI is free and open source. It configures a machine to talk to Blue Note\nMemory; a Blue Note Memory subscription is a separate commercial product.\n","readmeFilename":"README.md","_rev":"1-ec988d50f66284a6d5fff119c974fc6a"}