docs: Step 7 rename/hygiene pass

- package.json homepage: github.com/avi/Keynctr -> git.atitlan.io/avi/Keynctr
- README: title 'Nostr Feed Manager' -> 'Keynctr', resolve all
  [YOUR_FORGEJO_INSTANCE_URL]/<OWNER>/<REPO> placeholders with the real
  Forgejo URL, fix clone dir and packaged-binary name (nost-feed-manager
  -> keynectr), data dir default ~/.local/share/keynectr, refresh test
  counts (cargo 225+6 e2e, npm 139/19 files) and project layout
  (audit/bunker/feed/updates modules, signer/ dir, Feed+SignerMode screens)
- PRODUCT.md: data dir corrected with migration note
This commit is contained in:
Avi 2026-09-30 11:57:49 -05:00
commit 7891ccce1a
3 changed files with 28 additions and 22 deletions

View file

@ -19,7 +19,7 @@ Nostr Keynctr (Nostr Feed Manager) pairs a hardened Rust core with an Electron +
## Operating Context ## Operating Context
Workflows: create/switch/delete/undo profiles, compose (Write/Preview, character count, up to 3 link previews, image pick → nostr.build upload with NIP-92 imeta), publish with per-relay receipts, feed aggregation (all vs. My contacts, 24h window), relay add/remove/enable/disable/test, NIP-05 assignment, secret reveal after unlock, vault backup, lock/unlock. Workflows: create/switch/delete/undo profiles, compose (Write/Preview, character count, up to 3 link previews, image pick → nostr.build upload with NIP-92 imeta), publish with per-relay receipts, feed aggregation (all vs. My contacts, 24h window), relay add/remove/enable/disable/test, NIP-05 assignment, secret reveal after unlock, vault backup, lock/unlock.
Environments: Linux desktop (Electron 33), Rust release backend (`target/release/keynectr serve` via stdio), Vite dev server optionally via `NOSTR_GUI_DEV_URL`. Data directory `~/.local/share/nost-feed-manager` (override `XDG_DATA_HOME`), vault `profiles_vault.json` (migrated from legacy Python CLI with timestamped backup), settings file alongside. Environments: Linux desktop (Electron 33), Rust release backend (`target/release/keynectr serve` via stdio), Vite dev server optionally via `NOSTR_GUI_DEV_URL`. Data directory `~/.local/share/keynectr` (auto-migrated from the legacy `nost-feed-manager` dir; override `XDG_DATA_HOME`), vault `profiles_vault.json` (migrated from legacy Python CLI with timestamped backup), settings file alongside.
Rituals: single-click Approve/Reject for NIP-46 requests; explicit `window.confirm` for delete; 5s themed undo bar; publish confirmation toggle; per-relay status dots. Rituals: single-click Approve/Reject for NIP-46 requests; explicit `window.confirm` for delete; 5s themed undo bar; publish confirmation toggle; per-relay status dots.

View file

@ -1,4 +1,4 @@
# Nostr Feed Manager # Keynctr
> A friendly Linux desktop app for managing Nostr profiles, publishing notes, and acting as a > A friendly Linux desktop app for managing Nostr profiles, publishing notes, and acting as a
> **NIP-46 remote signer** — your private keys stay under your control: encrypted in a local > **NIP-46 remote signer** — your private keys stay under your control: encrypted in a local
@ -13,18 +13,17 @@
<!-- <!--
Forgejo CI badge — enable once a workflow exists in `.forgejo/workflows/ci.yml`: Forgejo CI badge — enable once a workflow exists in `.forgejo/workflows/ci.yml`:
[![CI]([YOUR_FORGEJO_INSTANCE_URL]/<OWNER>/<REPO>/actions/workflows/ci.yml/badge.svg)]([YOUR_FORGEJO_INSTANCE_URL]/<OWNER>/<REPO>/actions/workflows/ci.yml) [![CI](https://git.atitlan.io/avi/Keynctr/actions/workflows/ci.yml/badge.svg)](https://git.atitlan.io/avi/Keynctr/actions/workflows/ci.yml)
--> -->
> **Hosting note:** this project is hosted on **Forgejo**. Throughout this document, > **Hosting note:** this project is hosted on **Forgejo** at
> replace `[YOUR_FORGEJO_INSTANCE_URL]` with your instance's base URL (e.g. `https://codeberg.org`) > [`https://git.atitlan.io/avi/Keynctr`](https://git.atitlan.io/avi/Keynctr).
> and `<OWNER>/<REPO>` with the actual repository path.
--- ---
## 📖 Introduction ## 📖 Introduction
Nostr Feed Manager pairs a hardened **Rust core** (the same engine behind the original CLI) with a Keynctr pairs a hardened **Rust core** (the same engine behind the original CLI) with a
polished **Electron + React** desktop interface. All Nostr work — key generation, event signing, polished **Electron + React** desktop interface. All Nostr work — key generation, event signing,
relay communication, encryption — happens inside the Rust backend. The GUI talks to it over a relay communication, encryption — happens inside the Rust backend. The GUI talks to it over a
secure JSON-lines IPC channel and **never sees your secret keys**. secure JSON-lines IPC channel and **never sees your secret keys**.
@ -135,8 +134,8 @@ No Docker, database, or account setup is required.
### 1. Clone and build ### 1. Clone and build
```sh ```sh
git clone [YOUR_FORGEJO_INSTANCE_URL]/<OWNER>/<REPO>.git git clone https://git.atitlan.io/avi/Keynctr.git
cd nost-feed-manager cd Keynctr
# Build the Rust backend (release) # Build the Rust backend (release)
cargo build --release cargo build --release
@ -167,7 +166,7 @@ directly, but you can export these from your shell or source an `.env` before la
| --- | --- | --- | | --- | --- | --- |
| `NFM_PASSWORD` | Vault password for non-interactive CLI use (create / publish / show-secret) | _prompt_ | | `NFM_PASSWORD` | Vault password for non-interactive CLI use (create / publish / show-secret) | _prompt_ |
| `NOSTR_GUI_DEV_URL` | Renderer dev-server URL for hot reload (development only) | — | | `NOSTR_GUI_DEV_URL` | Renderer dev-server URL for hot reload (development only) | — |
| `XDG_DATA_HOME` | Override the data directory | `~/.local/share/nost-feed-manager` | | `XDG_DATA_HOME` | Override the data directory | `~/.local/share/keynectr` |
**`.env.example`** — copy to `.env` and adjust: **`.env.example`** — copy to `.env` and adjust:
@ -180,7 +179,7 @@ NFM_PASSWORD=
# Renderer dev-server URL for hot reload (development only) # Renderer dev-server URL for hot reload (development only)
NOSTR_GUI_DEV_URL=http://localhost:5173 NOSTR_GUI_DEV_URL=http://localhost:5173
# Override the data directory (defaults to ~/.local/share/nost-feed-manager) # Override the data directory (defaults to ~/.local/share/keynectr)
XDG_DATA_HOME= XDG_DATA_HOME=
``` ```
@ -194,13 +193,13 @@ cd frontend
npm run dist # builds renderer + backend and runs electron-builder npm run dist # builds renderer + backend and runs electron-builder
``` ```
The unpacked app lands in `frontend/release/linux-unpacked/`; run it with `./nost-feed-manager`. The unpacked app lands in `frontend/release/linux-unpacked/`; run it with `./keynectr`.
## 🧑‍💻 Usage guide ## 🧑‍💻 Usage guide
### Desktop app ### Desktop app
Tabs cover **Compose**, **Home**, **Profiles**, **Relays**, **Settings**, and **Signer**. Connect Tabs cover **Compose**, **Home**, **Feed**, **Profiles**, **Relays**, **Settings**, and **Signer**. Connect
a relay by entering its `wss://` URL, then compose a note, attach an image, and publish to see a a relay by entering its `wss://` URL, then compose a note, attach an image, and publish to see a
per-relay report. per-relay report.
@ -288,11 +287,11 @@ npm run dev
NOSTR_GUI_DEV_URL=http://localhost:5173 npm start NOSTR_GUI_DEV_URL=http://localhost:5173 npm start
``` ```
### Verify (all green — `cargo 75`, `npm 71`, clippy/fmt/typecheck/lint/format clean) ### Verify (all green — `cargo 225 + 6 e2e`, `npm 139`, clippy/fmt/typecheck/lint/format clean)
```sh ```sh
# Rust # Rust
cargo test # 75 unit tests cargo test # 225 unit tests (+ 6 e2e in tests/)
cargo fmt --check # rustfmt cargo fmt --check # rustfmt
cargo clippy --all-targets cargo clippy --all-targets
@ -301,7 +300,7 @@ cd frontend
npm run typecheck # TypeScript (renderer + electron) npm run typecheck # TypeScript (renderer + electron)
npm run lint # ESLint npm run lint # ESLint
npm run format:check # Prettier npm run format:check # Prettier
npm test # Vitest (jsdom) — 71 tests across 13 files npm test # Vitest (jsdom) — 139 tests across 19 files
``` ```
The test suites exercise the real IPC protocol against a fake backend, so features are tested at The test suites exercise the real IPC protocol against a fake backend, so features are tested at
@ -312,22 +311,29 @@ the protocol boundary rather than in isolation.
``` ```
src/ Rust library + CLI + IPC server src/ Rust library + CLI + IPC server
app.rs app state, vault password/unlock lifecycle app.rs app state, vault password/unlock lifecycle
audit.rs key-export audit log (fail-closed)
bunker.rs NIP-46 bunker (signer server) mode
crypto.rs Argon2id derivation + AES-256-GCM encryption crypto.rs Argon2id derivation + AES-256-GCM encryption
errors.rs structured AppError errors.rs structured AppError
feed.rs feed aggregation (all / contacts, 24h window)
ipc.rs JSON-lines serve() loop and request/reply envelope ipc.rs JSON-lines serve() loop and request/reply envelope
main.rs CLI entry point main.rs CLI entry point
profiles.rs profile create/list/select, secret recovery profiles.rs profile create/list/select, secret recovery, auto-naming
publish.rs note publishing with receipts, images and imeta tags publish.rs note publishing with receipts, images and imeta tags
relays.rs default relays, validation, connection tests relays.rs default relays, validation, connection tests
settings.rs theme and preferences settings.rs theme and preferences
signer.rs NIP-46 remote signer + approval gate updates.rs no-restart self-updater
uploads.rs NIP-98 auth for image-host uploads uploads.rs NIP-98 auth for image-host uploads
vault.rs vault storage (plaintext or password-encrypted) vault.rs vault storage (plaintext or password-encrypted)
signer/ external NIP-46 signer client
backend.rs signer backend dispatch (embedded / external)
nip46_client.rs NIP-46 client: pairing, sessions, park/switch
permissions.rs per-remote per-kind permission grants
frontend/ frontend/
electron/ Electron main + preload (backend spawn, dialogs, clipboard) electron/ Electron main + preload (backend spawn, dialogs, clipboard)
src/ src/
screens/ Compose, Home, Profiles, Relays, Settings, Signer screens/ Compose, Home, Feed, Profiles, Relays, Settings, Signer, SignerMode
lib/ types, api bridge, media helpers lib/ types, api bridge, media helpers, theme tokens
state/ React context (AppProvider) state/ React context (AppProvider)
test/ Vitest suite over a fake backend test/ Vitest suite over a fake backend
package.json scripts + electron-builder config package.json scripts + electron-builder config
@ -341,7 +347,7 @@ respectful and constructive; everyone is expected to follow the
### Reporting bugs ### Reporting bugs
Open an issue on the [issue tracker]([YOUR_FORGEJO_INSTANCE_URL]/<OWNER>/<REPO>/issues) and include: Open an issue on the [issue tracker](https://git.atitlan.io/avi/Keynctr/issues) and include:
- A clear title and description of expected vs. actual behavior - A clear title and description of expected vs. actual behavior
- Steps to reproduce - Steps to reproduce

View file

@ -7,7 +7,7 @@
"name": "Keynectr", "name": "Keynectr",
"email": "maintainers@keynectr.local" "email": "maintainers@keynectr.local"
}, },
"homepage": "https://github.com/avi/Keynctr", "homepage": "https://git.atitlan.io/avi/Keynctr",
"private": true, "private": true,
"main": "dist-electron/main.js", "main": "dist-electron/main.js",
"scripts": { "scripts": {