Skip to content

[FEATURE] Per-item field choice (password/username/TOTP) when activating a /bw launcher result #53

Description

@tellur1an

Feature type

Configuration / customization

Feature summary

In the Bitwarden plugin's /bw launcher, pressing Enter on a vault item always copies whichever single field is configured globally via copy_field (password/username/totp/uri). There's no way to pick a different field per-item without changing the plugin setting each time. I'd like a way to choose the field (at minimum password vs. username) at activation time, without leaving the launcher.

Motivation / use case

Most logins need the password copied, but some need the username instead (e.g. numeric account IDs, or sites where I paste username then switch apps to grab the password separately). Right now the only way to get the username is:

  1. Open plugin settings
  2. Change Copy field from password to username
  3. Run /bw, search, activate
  4. Switch it back to password afterward

That's a lot of friction for something that should be a single keypress in a launcher.

Proposed solution

Looking at the current source (bitwarden/launcher.luau and bitwarden/service.luau in this repo), each vault match currently becomes one launcher row:

-- launcher.luau, itemRows()
table.insert(rows, {
    id = "item:" .. item.id,
    title = item.name,
    subtitle = itemSubtitle(item),
    glyph = itemGlyph(item),
})

and activation just forwards the id with no field info:

-- launcher.luau, onActivate()
if id:sub(1, 5) == "item:" then
    local itemId = id:sub(6)
    if itemId ~= "" then
        noctalia.state.set("command", { action = "copy", id = itemId })
    end
end
-- service.luau, copyItemField()
local field = cfg("copy_field")
if type(field) ~= "string" or field == "" then
    field = "password"
end

Since the launcher API's onActivate(id) doesn't expose a modifier key (no way to distinguish Enter from Ctrl+Enter), a modifier-based shortcut isn't possible without a launcher API change. A workaround that stays entirely within the existing plugin API: emit one row per copyable field per matched item (e.g. "GitHub — Password" / "GitHub — Username"), and encode the chosen field in the row id so onActivate can pass it through to service.luau:

-- launcher.luau
if id:sub(1, 14) == "item:password:" then
    noctalia.state.set("command", { action = "copy", id = id:sub(15), field = "password" })
elseif id:sub(1, 14) == "item:username:" then
    noctalia.state.set("command", { action = "copy", id = id:sub(15), field = "username" })
end
-- service.luau
local function copyItemField(itemId, fieldOverride)
  ...
  local field = fieldOverride
  if type(field) ~= "string" or field == "" then
    field = cfg("copy_field")
  end
  if type(field) ~= "string" or field == "" then
    field = "password"
  end
  ...
-- service.luau, onIpc()
elseif event == "copy" then
    local id = payload
    local field = nil
    if type(payload) == "table" then
        id = payload.id
        field = payload.field
    end
    copyItemField(id, field)

copy_field in settings would keep working as the default for whichever generic action still uses it, and this only adds explicit password/username rows alongside it. Whether to also add totp/uri rows, or make the set of generated fields configurable, is open — happy to adjust based on what maintainers prefer. RESULT_LIMIT (currently 100) would need to account for the row multiplier so vault searches don't get truncated to half as many items.

Alternatives considered

  • Keybinding for "copy alternate field" (e.g. Ctrl+Enter): blocked today because the launcher's onActivate(id) callback has no modifier-key parameter, so the plugin can't distinguish Enter from Ctrl+Enter. This would need a launcher API change upstream in the shell itself, not just the plugin.
  • Leaving copy_field as the only control: works but requires reopening plugin settings every time you need the other field, which isn't practical for daily use.

References / related projects

N/A

Additional context

Happy to open a PR for the launcher/service.luau changes above if this direction is welcome — wanted to check in on the general approach (extra rows vs. a launcher API change vs. something else) first since it touches the result-list shape.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions