Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
400 changes: 400 additions & 0 deletions extensions/html-symbol-finder/package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Dispatch, SetStateAction } from "react";
import { useCallback, useEffect, useState } from "react";

import { LocalStorage } from "@vicinae/api";

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down Expand Up @@ -40,7 +39,7 @@ const useStateAndLocalStorage = <T, _ = void>(
const setStateAndLocalStorage = useCallback((updater) => {
setState((state) => {
const newValue = typeof updater === "function" ? updater(state) : updater;
LocalStorage.setItem(key, JSON.stringify(newValue));
LocalStorage.setItem(key, JSON.stringify(newValue)).then(null);
return newValue;
});
}, []);
Expand Down
17 changes: 17 additions & 0 deletions extensions/keepassxc/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
## [1.1.0] - 2026-03-24

### Added

- Support for KeePassXC installed via Flatpak, Snap, and AppImage — the CLI path and arguments are now auto-detected based on the installation type
- Keyboard shortcut `Ctrl+C` for the Copy Password action
- README: installation instructions for Flatpak, Snap, and AppImage

### Fixed

- `cacheCredentials` and `deleteCredentialsCache` are now properly awaited (`LocalStorage` calls were fire-and-forget)
- `showToastCliErrors` now correctly returns `Promise<void>` instead of `void`
- `errorHandler` in `SearchDatabase` is now async so toast errors are awaited
- Replaced `ImageLike` type alias import with inline `Image.ImageLike` to fix a TypeScript error
- Fixed `subtitle` prop type on `List.Item` to match the current API
- Fixed a typo: `chuncks` → `chunks`

## [1.0.0] - 2026-02-03

### Added
Expand Down
46 changes: 40 additions & 6 deletions extensions/keepassxc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,70 @@

<b align="center">Search your passwords, usernames, TOTP codes, and more using KeePassXC directly from Vicinae.</b>

## Requirements
# Requirements

To use this extension, you will need:

- Installed [KeePassXC](https://keepassxc.org)
- The `keepassxc-cli` HAVE TO be in the $PATH (Mostly in `/usr/bin` or in `/usr/local/bin`)
- A `.kdbx` file that contains entries
- The `keepassxc-cli` HAVE TO be in the $PATH (Mostly in `/usr/bin` or in `/usr/local/bin`) if the KeePassXC is not installed from `snap`, `AppImage` or `flatpak`

## Installation
# Installation

The KeePassXC can be installed on linux several ways

#### Fedora
## Fedora

```shell
$ sudo dnf install keepassxc
```

#### Ubuntu and Debian based distros
## Install via Flatpak

[Here is](https://flathub.org/en/apps/org.keepassxc.KeePassXC) the flathub package.

```shell
$ flatpak install flathub org.keepassxc.KeePassXC
```

## Ubuntu and Debian based distros

```shell
$ sudo apt install keepassxc
```

#### Arch based distros
or [with Snap](https://snapcraft.io/keepassxc)

```shell
$ sudo snap install keepassxc
```

## Arch based distros

```shell
$ sudo pacman -Sy keepassxc
```

## AppImage based installation

You can download the latest AppImage from [here](https://github.com/keepassxreboot/keepassxc/releases/latest) and run it.

### Install by hand:

```shell
$ chmod a+x KeePassXC-2.7.12-x86_64.AppImage
```

```shell
$ ./KeePassXC-2.7.12-x86_64.AppImage
```

After this, you **HAVE TO** create a [`.desktop` entry](https://wiki.archlinux.org/title/Desktop_entries) for the AppImage.

> The AppImage could be installed by an AppImage installer too, like [AppManager](https://github.com/kem-a/AppManager).

> The `.desktop` can be created through a UI too: [dedicated apps](https://codeberg.org/libre-menu-editor/libre-menu-editor) for this.

## Security Notes

1. Your credentials required to access your KeePass database, which include a password and an optional key file, are securely stored in [Vicinae's local encrypted database](https://developers.raycast.com/information/security#data-storage). This storage prevents other extensions from accessing the storage of that extension.
Expand Down
2 changes: 1 addition & 1 deletion extensions/keepassxc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"title": "KeePassXC",
"description": "Access a KeePass database through KeePassXC.",
"icon": "keepassxc.png",
"author": "system7",
"author": "7system7",
"pastContributors": [
"pabroux",
"zkytech",
Expand Down
22 changes: 13 additions & 9 deletions extensions/keepassxc/src/components/search-database.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ import {
open,
showHUD,
showToast,
Toast
Toast,
} from "@vicinae/api";
import { getFavicon } from "@raycast/utils";
import { KeePassLoader, showToastCliErrors } from "../utils/keepass-loader";
import { arrayToEntry, processPlaceholders } from "../utils/placeholder-processor";
import { getTOTPCode } from "../utils/totp";
import { isValidUrl } from "../utils/url-checker";
import { useAccessories } from "../utils/use-accessories";
import ImageLike = Image.ImageLike;

// eslint-disable-next-line no-undef
const preferences: ExtensionPreferences = getPreferenceValues();
Expand Down Expand Up @@ -105,16 +104,19 @@ export default function SearchDatabase({ setIsUnlocked }: SearchDatabaseParams):
const [isShowingDetail, setIsShowingDetail] = useState(false);
const accessories = useAccessories();

const errorHandler = (e: { message: string }) => {
const errorHandler = async (e: { message: string }) => {
setIsUnlocked(false);
showToastCliErrors(e);
await showToastCliErrors(e);
};

const entryFavicon = useCallback((icon: string): ImageLike | undefined => {
const entryFavicon = useCallback((icon: string): Image.ImageLike | undefined => {
if (userInterfaceFavicon) {
return isValidUrl(icon)
? getFavicon(icon, { fallback: Icon.QuestionMarkCircle })
: { source: Icon.QuestionMarkCircle, tintColor: Color.SecondaryText };
if (isValidUrl(icon)) {
// @ts-expect-error eslint-disable-next-line @typescript-eslint/ban-ts-comment
return getFavicon(icon, { fallback: Icon.QuestionMarkCircle });
}

return { source: Icon.QuestionMarkCircle, tintColor: Color.SecondaryText };
}

return undefined;
Expand Down Expand Up @@ -156,7 +158,8 @@ export default function SearchDatabase({ setIsUnlocked }: SearchDatabaseParams):
key={i}
title={title}
icon={entryFavicon(url)}
subtitle={{ value: username, tooltip: "Username" }}
subtitle={username}
// @ts-expect-error eslint-disable-next-line @typescript-eslint/ban-ts-comment
accessories={accessories(isShowingDetail, keePassEntry)}
detail={(
<List.Item.Detail
Expand All @@ -183,6 +186,7 @@ export default function SearchDatabase({ setIsUnlocked }: SearchDatabaseParams):
<ActionPanel.Section title="Copy">
<Action
title="Copy Password"
shortcut={{ modifiers: ["ctrl"], key: "c" }}
onAction={async () => {
if ("" === password) {
await showToast(Toast.Style.Failure, "Error", "No Password Set");
Expand Down
19 changes: 5 additions & 14 deletions extensions/keepassxc/src/components/unlock-database.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default function UnlockDatabase({ setIsUnlocked }: UnlockDatabaseProps):

KeePassLoader.checkCredentials(value.password, value.keyFile?.[0] ?? "").then(async () => {
await showToast({ style: Toast.Style.Success, title: "Database Unlocked" });
KeePassLoader.cacheCredentials(value.password, value.keyFile?.[0] ?? "");
await KeePassLoader.cacheCredentials(value.password, value.keyFile?.[0] ?? "");
KeePassLoader.setCredentials(value.password, value.keyFile?.[0] ?? "");
setIsUnlocked(true);
}, showToastCliErrors);
Expand All @@ -49,24 +49,15 @@ export default function UnlockDatabase({ setIsUnlocked }: UnlockDatabaseProps):
<ActionPanel>
<Action.SubmitForm
title="Unlock"
// @ts-expect-error @typescript-eslint/ban-ts-comment
onSubmit={handleSubmit}
/>
</ActionPanel>
)}
>
<Form.Description
text="Your KeePass database is currently locked. Insert your credentials to unlock it."
/>
<Form.PasswordField
title="Database Password"
{...itemProps.password}
onBlur={undefined}
/>
<Form.FilePicker
id="keyFile"
title="Key File"
allowMultipleSelection={false}
/>
<Form.Description text="Your KeePass database is currently locked. Insert your credentials to unlock it." />
<Form.PasswordField title="Database Password" {...itemProps.password} onBlur={undefined} />
<Form.FilePicker id="keyFile" title="Key File" allowMultipleSelection={false} />
<Form.Description
text={"ⓘ Your password and key file path will be stored in your Raycast's local encrypted storage."}
/>
Expand Down
Loading
Loading