@ramarivera/opencode-fnox-sync
v0.1.4
Published
OpenCode plugin that syncs auth.json through fnox
Downloads
143
Maintainers
Readme
opencode-fnox-sync
OpenCode plugin that keeps auth.json synchronized through fnox.
fnox is a hard dependency by design. The plugin does not decide how secrets are stored; users configure that in fnox itself with age, 1password, vault, cloud secret stores, or any other supported provider strategy.
Setup wizard
Run the setup wizard to generate opencode-fnox-sync.json:
bunx opencode-fnox-sync-setupThe wizard is built with @clack/prompts, so it installs with the package and does not require an external TUI binary.
For non-interactive setup, you can generate a config file directly:
bunx opencode-fnox-sync-setup --yes --project-localFor locally encrypted workflows such as fnox + age or fnox + sops, the wizard can also configure an optional managed git transport so the plugin handles the pull/commit/push loop around fnox automatically.
When managed git sync is enabled, the wizard can also write a starter fnox.toml.example into the managed repo path so you have an age-based template to start from.
What it does
- pulls a remote auth blob from
fnoxwhen OpenCode starts - optionally restores that blob into the local OpenCode auth file
- watches the local auth file for token refreshes
- pushes the updated auth blob back into
fnox - avoids re-pushing the same content by hashing the auth file
Install
Install fnox first. The upstream project recommends installing it with mise:
mise use -g [email protected]Add the package to your OpenCode config:
{
"plugin": [
"@ramarivera/opencode-fnox-sync"
]
}Plugin config
The plugin reads config from one of these files:
<project>/opencode-fnox-sync.json~/.config/opencode/opencode-fnox-sync.json
On all platforms, the default OpenCode auth path matches OpenCode's own XDG-style storage layout:
- Linux:
~/.local/share/opencode/auth.json - macOS:
~/.local/share/opencode/auth.json - Windows:
%USERPROFILE%\.local\share\opencode\auth.json
Example:
{
"$schema": "https://raw.githubusercontent.com/ramarivera/opencode-fnox-sync/main/schema.json",
"enabled": true,
"secretName": "OPENCODE_AUTH",
"workingDirectory": "/path/to/project-with-fnox-toml",
"profile": "dev",
"startupSync": "prefer-remote",
"watchAuthFile": true,
"debounceMs": 1000,
"managedSync": {
"type": "git",
"repositoryPath": "/path/to/private-fnox-secrets-repo",
"pullOnStartup": true,
"pullBeforeSet": true,
"pushOnSet": true
}
}fnox model
The plugin always shells out to fnox. Users choose the storage model in fnox, not in the plugin.
When managedSync.type = "git", fnox still remains the core secret abstraction. The plugin only automates transport for locally encrypted backends by:
- pulling the git-backed
fnoxrepo on startup - optionally pulling again before
fnox set - committing only tracked
fnox*.tomlfiles after updates - optionally pushing the encrypted changes upstream
Example fnox.toml using age for low-friction cross-device sync:
[providers.age]
type = "age"
recipients = [
"age1exampledeviceone...",
"age1exampledevicetwo..."
]
[secrets]
OPENCODE_AUTH = { provider = "age" }If you want to bootstrap from 1password but avoid repeated prompts later, use fnox sync or caching patterns so the hot path is not the password manager itself.
Choosing a fnox backend
Given your earlier goal of cross-device sync without constant biometric prompts, the most convenient backend is usually:
ageas the steady-state storage backend- one recipient per device
- optional
1passwordonly for bootstrap or recovery
Why age is the best fit here:
- no repeated Touch ID or Windows Hello prompt during normal OpenCode use
- easy to share one encrypted secret across multiple devices
- works well with git-backed
fnox.tomlworkflows - keeps the plugin simple because
fnox getstays the hot path
Good alternatives only if you already run them everywhere:
- Vault / cloud secret managers: best for existing infra-heavy setups
- 1Password direct provider: okay for occasional/manual use, less ideal for frequent auth refresh sync
Logging
The plugin writes runtime logs to a file under the XDG state directory rather than using console output:
- Linux/macOS default:
~/.local/state/opencode-fnox-sync/opencode-fnox-sync.log - Windows default:
%USERPROFILE%\.local\state\opencode-fnox-sync\opencode-fnox-sync.log
This keeps plugin logs near the canonical state/config area without polluting the OpenCode TUI.
Publishing prep
The package now includes npm metadata and a prepublishOnly gate that runs:
bun run typecheckbun testbun run build
Release automation is defined in:
.github/workflows/ci.yml.github/workflows/release.ymlPUBLISHING.md
The intended release model is:
- first publish manually with
npm login+npm publish - later publishes via GitHub Actions trusted publishing from
release.yml
I also checked npm availability during development and @ramarivera/opencode-fnox-sync was not present in the registry at the time of checking.
Behavior
startupSync controls first-run conflict handling:
prefer-remote: restore remote into the local file when the hashes differprefer-local: push the local file intofnoxwhen the hashes differremote-if-missing: only restore if the local file is absent
Development
bun install
bun test
bun run typecheck
bun run build