Conversation
Explains how to use `fnox sync` to cache remote provider secrets (e.g., 1Password) locally with an encryption provider (age, YubiKey) in fnox.local.toml for instant, offline secret loading. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces comprehensive documentation for the Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Greptile SummaryThis PR adds a new guide page (
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Dev as Developer
participant fnox
participant OP as 1Password (remote)
participant age as age (local)
participant Local as fnox.local.toml
Note over Dev,Local: fnox sync --provider age --config fnox.local.toml
Dev->>fnox: fnox sync
fnox->>OP: Fetch plaintext secret values
OP-->>fnox: DATABASE_URL, STRIPE_KEY, SENDGRID_KEY
loop For each secret
fnox->>age: Encrypt with age public key
age-->>fnox: Encrypted ciphertext
fnox->>Local: Write sync = {provider="age", value="..."}
end
Note over Dev,Local: Subsequent cd into project
Dev->>fnox: Resolve secrets
fnox->>Local: Read sync field (age ciphertext)
fnox->>age: Decrypt locally
age-->>fnox: Plaintext value
fnox-->>Dev: Secrets injected (no remote call)
Last reviewed commit: 1c5611f |
Remove examples without --config since that's the primary use case. Drop the global config section to keep the guide focused. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request adds a new documentation page for the fnox sync command, which is a great addition. The guide is well-structured and comprehensive. I've found a couple of minor issues in the examples that could confuse users and have provided suggestions to correct them. One is a small typo in a secret path, and the other is a potentially confusing instruction in the full workflow example where a user might not use their own generated key.
I am having trouble creating individual review comments. Click here to see my feedback.
docs/guide/sync.md (18)
There seems to be a copy-paste error in this example. The SENDGRID_KEY is configured to use a path from Stripe (Stripe/api-key). This is likely a typo and could be confusing. It should probably be SendGrid/api-key, which is what is used in a later example in this same document.
SENDGRID_KEY = { provider = "op", value = "SendGrid/api-key" }
docs/guide/sync.md (163-172)
The 'Full Workflow Example' is very helpful, but it could be confusing for users. In step 3, a new age key is generated, but in step 4, a hardcoded public key is used in the configuration. A user following this guide verbatim would not be able to decrypt secrets because the public key in the config doesn't match their private key.
To prevent this confusion, I suggest updating the instructions to explicitly tell the user to use the public key they just generated.
# 3. Set up your age key (one-time). The public key will be printed to your terminal.
age-keygen -o ~/.config/fnox/age.txt
export FNOX_AGE_KEY=$(grep "AGE-SECRET-KEY" ~/.config/fnox/age.txt)
# 4. Add age provider to your config.
# IMPORTANT: Replace the placeholder recipient below with your public key from step 3.
cat >> fnox.toml << 'EOF'
[providers.age]
type = "age"
recipients = ["age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"] # <-- PASTE YOUR PUBLIC KEY HERE
EOF
Instead of a hardcoded placeholder, extract the public key from the age key file so users can follow the example verbatim. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| echo "fnox.local.toml" >> .gitignore | ||
|
|
||
| # 3. Set up your age key (one-time) — note the public key printed to your terminal | ||
| age-keygen -o ~/.config/fnox/age.txt |
There was a problem hiding this comment.
Missing mkdir -p before age-keygen
age-keygen -o ~/.config/fnox/age.txt will fail with a "no such file or directory" error on any system where ~/.config/fnox/ doesn't already exist (i.e., a fresh setup, which is exactly the scenario this guide targets). The directory needs to be created first.
| age-keygen -o ~/.config/fnox/age.txt | |
| mkdir -p ~/.config/fnox && age-keygen -o ~/.config/fnox/age.txt |
### 🚀 Features - **(cloudflare)** add Cloudflare API token lease backend by [@jdx](https://github.com/jdx) in [#335](#335) - **(fido2)** bump demand to v2, mask PIN during typing by [@jdx](https://github.com/jdx) in [#334](#334) - **(init)** add -f as short alias for --force by [@jdx](https://github.com/jdx) in [#329](#329) - **(lease)** add --all flag, default to creating all leases by [@jdx](https://github.com/jdx) in [#337](#337) - **(lease)** add GitHub App installation token lease backend by [@jdx](https://github.com/jdx) in [#342](#342) ### 🐛 Bug Fixes - **(config)** fix directory locations to follow XDG spec by [@jdx](https://github.com/jdx) in [#336](#336) - **(exec)** use unix exec and exit silently on subprocess failure by [@jdx](https://github.com/jdx) in [#339](#339) - **(fido2)** remove duplicate touch prompt by [@jdx](https://github.com/jdx) in [#332](#332) - **(set)** write to lowest-priority existing config file by [@jdx](https://github.com/jdx) in [#331](#331) - **(tui)** skip providers requiring interactive auth by [@jdx](https://github.com/jdx) in [#333](#333) ### 🛡️ Security - **(ci)** retry lint step to handle transient pkl fetch failures by [@jdx](https://github.com/jdx) in [#341](#341) - **(mcp)** add MCP server for secret-gated AI agent access by [@jdx](https://github.com/jdx) in [#343](#343) - add guide for fnox sync by [@jdx](https://github.com/jdx) in [#328](#328) ### 🔍 Other Changes - share Rust cache across CI jobs by [@jdx](https://github.com/jdx) in [#340](#340)
Summary
fnox syncfor caching remote provider secrets locallyfnox.local.tomlwith age/YubiKey encryption for instant, offline accessTest plan
mise run docs:dev)🤖 Generated with Claude Code
Note
Low Risk
Documentation-only changes (new page + sidebar link) with no impact on runtime behavior or security-sensitive code.
Overview
Adds a new Guide page (
docs/guide/sync.md) documentingfnox syncfor caching secrets fetched from remote providers into a gitignoredfnox.local.toml, including usage patterns (dry-run, filtering, source selection), thesyncfield format, YubiKey/age examples, and cache refresh workflow.Updates the VitePress sidebar (
docs/.vitepress/config.mjs) to include a new “Syncing Secrets Locally” entry under Features.Written by Cursor Bugbot for commit 1c5611f. This will update automatically on new commits. Configure here.