A long value in the details pane (a ref, a note, a vault's detail, an error) was coloured, then wrapped: the colour's reset only came on the last line, and each line is drawn on its own, so the lines after the first lost the colour. Each wrapped line now starts with the styles still on at the end of the one before.
Reviewed-on: #69
Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
Go now stamps local builds with a module pseudo-version (v0.1.3-0.20261014174204-1c31a75d0507+dirty), so the version showed that instead of dev-<commit> as the docs say. The update check also took it for a pre-release of 0.1.3, a version that doesn't exist, rather than a development build. A pseudo-version is now dev-<its commit>, -dirty with uncommitted changes; real versions are unchanged.
Reviewed-on: #68
Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
fzf's become hands lazysecrets its /dev/tty still non-blocking. Go can't poll /dev/tty on macOS, so it reads it directly, and the TUI's first read failed with "resource temporarily unavailable" (EAGAIN). lazysecrets now makes a terminal on stdin blocking before the TUI starts (Unix; nothing on Windows).
Reviewed-on: #67
Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
Changes that would break configs or links once people use lazysecrets, made while nobody does yet.
- **Repo key names**: a dot or bracket inside a key is escaped (`app\.name`), so links to it resolve to that key and not to `app` → `name`. Dotenv files are flat, so their names stay as they are.
- **Config**: `updates.updateSources` is now `updates.sources`. A negative provider timeout, or `--timeout` of 0 or less, is an error instead of making every request fail.
- **Keybindings**: `lists.share` is now `lists.copyLink`, `lists.search` is `lists.goTo` and `lists.enter` is `lists.open`, matching what they do.
- **Version skew**, e.g. a lazysecrets.nvim theme file made for a newer lazysecrets:
- an unknown theme role is skipped with a warning instead of stopping startup;
- a state file from a newer version is read but not saved to, with a warning;
- a link with an unknown provider suggests `lazysecrets update`.
Reviewed-on: #66
Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
SECURITY.md asks for vulnerabilities to be reported privately, through GitHub's private vulnerability reporting or by email to karl-einarb@outlook.com.
docs/development.md: the "Pull requests" heading is now "How changes land". The section covers squash merges, PR titles and branch protection, not how to send one.
Reviewed-on: #65
Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
Latest reads the last 10 releases in one request instead of only the
newest, so U and lazysecrets update --check show the changes of every
release since the running version, each under its version. Drafts and
pre-releases are skipped. A changelog taller than the screen is cut
with a pointer to the release pages.
Reviewed-on: #61
Regroups the config, while there are no users to migrate:
- `ui`: icons, sourcesView, collapseGroups, loadDelay, expiryWarningDays
- `values`: revealTimeout, hideOnBlur, clipboardClear
- `storage`: cache, history
- `updates`: autoCheck (was updateCheck), autoCheckInterval (new, 24h by default), updateSources (was releases)
- `providers.timeout` (was timeout), plus `timeout` on azure, databricks and repos overriding it for that provider; `--timeout` still sets them all
- `sharing` (was share), in the config and in a repo's `.lazysecrets.yaml`
docs/config.md and the pages naming these keys are updated.
Reviewed-on: #60
Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
Without roots in the config, repos are found under whichever of ~/git,
~/repo, ~/repos, ~/projects, ~/code, ~/source and ~/src exist. Missing
ones cost a stat each. A root that's a symlink to another is scanned
once, and a repo under two roots keeps the first one's name.
Reviewed-on: #57
Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
Share `.env` files as an encrypted `lazysecrets://share/…` link. The files are encrypted with a secret's value, so anyone who can read that secret can open the link.
**Sharing:** `S` → `f` on a repo (all its plain env files), an env file, or a key in one (its file).
- **The key** is `share.key` from the repo's `.lazysecrets.yaml`, else from the config. It can be a `lazysecrets://` link, a Key Vault URL or an `@Microsoft.KeyVault(...)` reference.
- **Without `share.key`,** a picker built on Go to opens, titled "Share .env", with "Pick a secret to encrypt with" in its own border. It lists only secrets, leaving out values from plain `.env` files. Pasting a reference picks it. Picking shares at once, and the picker stays open until the link is copied. If the secret can't be used, the reason shows in red in the picker: it can't be read, or it doesn't meet `share.keyRules` (which rule failed is named). `esc` cancels.
- **`share.keyRules`** (defaults `minLength: 32`, `minClasses: 2`; never under 16) applies when sharing, not when opening.
- **On Azure,** the link pins the key's version, so rotating the key doesn't break old links, and disabling a version revokes them.
- **The command line:** `lazysecrets share [--key <secret>] <env files>`.
**Opening** works by paste, `ctrl+o`, the clipboard offer, the link handler or `lazysecrets <link>`.
1. It first says which repo the link is from, how many files it holds and which key it uses, and decrypts only after `o`.
2. It saves into the repo's clone, found by its remote, showing which files are new, which would replace one there, and which git doesn't ignore.
3. Without a clone, it asks for a folder and saves straight away. The prompt stays open, with the reason in red, until the files are written.
4. If decryption fails, a popup says why: the first line of the reason, `r` for the whole message, `g` to go to the key's secret. A key that has changed is named by where it lives: a Databricks or SOPS value changed in place, an Azure current version that isn't the one the link was made with, or a pinned version, meaning the link may be damaged.
**Format** (`internal/share`): a version byte, then a JSON header with the key, the repo and the file count, then an age file (scrypt 2^15, with the key's value as passphrase) holding the files as deflated JSON, all as unpadded base64url. Links are capped at 16 KB. A future format gets a new version, and old ones stay readable.
**Safety:**
- A link can only write env files, inside the folder: never in `.git`, never through a symlink.
- New files are created with mode 0600.
- Opening accepts an scrypt work factor of at most 2^20, and unpacks at most 1 MB.
**Along the way:**
- Opening a link to a secret ends on its details, as `enter` would.
- `o` on an Azure secret opens its portal page, and in the versions view, that version's page.
- The details pane follows its secret's list when it reloads in the background. Before, it kept what it showed first, including an old portal address.
- `ref.Read` is shared by `get` and sharing, with Azure `VersionedValue` for pinning.
- `provider.Contents` lets the demo repos share their env files. `--demo` has a share key (`kv-shared-prod / env-share`), so the whole flow works there.
- New dependency: `filippo.io/age`.
Tested end to end in the TUI and the demo, the CLI, and the `share` package. In a real vault: version pinning, opening into a clone, and revocation by disabling the version.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: #54
`e` on the status pane (`0`) opens your config file, as in lazygit's status panel. The status footer shows it as `e edit config`. There's no global key. It opens the config the same way `e` opens a local file:
- inside nvim, in that nvim (lazysecrets quits);
- otherwise in `$VISUAL` or `$EDITOR`, coming back after;
- otherwise in the system's default app.
It opens the first config file: your own, also when `--config` layers several. A config that doesn't exist yet is created with a comment linking to its docs. Closing the editor says "restart lazysecrets to use it", since the config is read at startup.
Docs: keys.md (status pane) and config.md. Tested: the default app with a new config, nvim with an existing one left unchanged, the restart message, and the footer.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: #55
Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
github.com/charmbracelet/x/exp/golden is pinned to a commit with no releases, so Renovate can't look it up and warned on every run.
---------
Co-authored-by: Karl-Einar Bergstrøm <karl-einarb@outlook.com>
Reviewed-on: #34
Welcome to [Renovate](https://github.com/renovatebot/renovate)! This is an onboarding PR to help you understand and configure settings before regular Pull Requests begin.
🚦 To activate Renovate, merge this Pull Request. To disable Renovate, simply close this Pull Request unmerged.
📚 See our [Reading List](https://docs.renovatebot.com/reading-list/) for relevant documentation you may be interested in reading.
🔡 Do you want to change how Renovate upgrades your dependencies? Add your custom config to `renovate.json` in this branch. Renovate will update the Pull Request description the next time it runs.
---
### Detected Package Files
* `.gitea/workflows/ci.yml` (github-actions)
* `.gitea/workflows/pr-title.yml` (github-actions)
* `.gitea/workflows/release.yml` (github-actions)
* `go.mod` (gomod)
* `renovate.json` (renovate-config)
* `.gitea/workflows/release.yml` (regex)
* `.gitea/workflows/ci.yml` (regex)
### Configuration Summary
Based on the default config's presets, Renovate will:
- Start dependency updates only once this onboarding PR is merged
- Enable Renovate Dependency Dashboard creation.
- Use semantic commit type `fix` for dependencies and `chore` for all others if semantic commits are in use.
- Ignore `node_modules`, `bower_components`, `vendor` and various test/tests (except for nuget) directories.
- Group known monorepo packages together.
- Use curated list of recommended non-monorepo package groupings.
- Show only the Age and Confidence Merge Confidence badges for pull requests.
- Apply crowd-sourced package replacement rules.
- Apply crowd-sourced workarounds for known problems with packages.
- Ensure that every dependency pinned by digest and sourced from Forgejo contains a link to the commit-to-commit diff
- Ensure that every dependency pinned by digest and sourced from Gitea contains a link to the commit-to-commit diff
- Ensure that every dependency pinned by digest and sourced from GitHub.com and Github enterprise contains a link to the commit-to-commit diff
- Ensure that every dependency pinned by digest and sourced from GitLab.com contains a link to the commit-to-commit diff
- Correctly link to the source code for golang.org/x packages
- Link to pkg.go.dev/... for golang.org/x packages' title
- Provide a link to octochangelog's improved breakdown for Renovate's changelogs
- Use semantic prefixes for commit messages and PR titles.
- If Renovate detects semantic commits, it will use semantic commit type `chore` for all commits.
- The shared Renovate policy: repos extend it with local>keb/renovate.
- Run Renovate on following schedule: before 6am on monday
---
### What to Expect
With your current configuration, Renovate will create 3 Pull Requests:
<details>
<summary>chore(deps): update 0.x minor</summary>
- Schedule: ["before 6am on monday"]
- Branch name: `renovate/0.x-minor`
- Merge into: `main`
- Upgrade [golang.org/x/mod](https://go.googlesource.com/mod) to `v0.41.0`
- Upgrade [golang.org/x/term](https://go.googlesource.com/term) to `v0.47.0`
</details>
<details>
<summary>chore(deps): update non-major</summary>
- Schedule: ["before 6am on monday"]
- Branch name: `renovate/non-major`
- Merge into: `main`
- Upgrade [charm.land/bubbletea/v2](https://github.com/charmbracelet/bubbletea) to `v2.1.0`
- Upgrade [github.com/Azure/azure-sdk-for-go/sdk/azcore](https://github.com/Azure/azure-sdk-for-go) to `v1.23.3`
- Upgrade [github.com/charmbracelet/x/ansi](https://github.com/charmbracelet/x) to `v0.11.9`
- Upgrade [gopkg.in/ini.v1](https://gopkg.in/ini.v1) to `v1.67.3`
</details>
<details>
<summary>chore(deps): update azure-sdk-for-go monorepo to v2</summary>
- Schedule: ["before 6am on monday"]
- Branch name: `renovate/major-azure-sdk-for-go-monorepo`
- Merge into: `main`
- Upgrade [github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault](https://github.com/Azure/azure-sdk-for-go) to `v2.1.0`
- Upgrade [github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions](https://github.com/Azure/azure-sdk-for-go) to `v2.0.0`
</details>
🚸 PR creation will be limited to maximum 2 per hour, so it doesn't swamp any CI resources or overwhelm the project. See [docs for `prHourlyLimit`](https://docs.renovatebot.com/configuration-options/#prhourlylimit) for details.
---
>
> ⚠️ **Warning**
>
> Please correct - or verify that you can safely ignore - these dependency lookup failures before you merge this PR.
>
> - `Could not determine new digest for update (go package github.com/charmbracelet/x/exp/golden)`
>
> Files affected: `go.mod`
---
❓ Got questions? Check out Renovate's [Docs](https://docs.renovatebot.com/), particularly the Getting Started section.
If you need any further assistance then you can also [request help here](https://github.com/renovatebot/renovate/discussions).
---
This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-config-hash:42b8771e0e792cb00b73533dcfa07b6c34d2c882632e57c0db725713586c855e-->
Reviewed-on: #32
Co-authored-by: Renovate Bot <renovate-bot@noreply.git.kebcloud.no>