Skip to content
Merged
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
82 changes: 82 additions & 0 deletions .beads/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Dolt database (managed by Dolt, not git)
dolt/
embeddeddolt/
proxieddb/

# Runtime files
bd.sock
bd.sock.startlock
sync-state.json
last-touched
.exclusive-lock

# Daemon runtime (lock, log, pid)
daemon.*

# Push state (runtime, per-machine)
push-state.json

# Lock files (various runtime locks)
*.lock

# Credential key (encryption key for federation peer auth — never commit)
.beads-credential-key

# Local version tracking (prevents upgrade notification spam after git ops)
.local_version

proxied_server_client_info.json

# Worktree redirect file (contains relative path to main repo's .beads/)
# Must not be committed as paths would be wrong in other clones
redirect

# Sync state (local-only, per-machine)
# These files are machine-specific and should not be shared across clones
.sync.lock

# Workspace operation gate (internal/workspacegate): physical-root gate
# files live beside the guarded root inside .beads (e.g. dolt.gate.lock)
*.gate.lock*
export-state/
export-state.json
last_pull

# Ephemeral store (SQLite - wisps/molecules, intentionally not versioned)
ephemeral.sqlite3
ephemeral.sqlite3-journal
ephemeral.sqlite3-wal
ephemeral.sqlite3-shm

# Dolt server management (auto-started by bd)
dolt-server.pid
dolt-server.log
dolt-server.lock
dolt-server.port
dolt-server.activity
dolt-server-config.yaml

# Debug-mode pprof artifacts (written when dolt.debug: true in config.yaml)
dolt-pprof/

# Corrupt backup directories (created by bd doctor --fix recovery)
*.corrupt.backup/

# Backup data (auto-exported JSONL, local-only)
backup/

# Per-project environment file (Dolt connection config, GH#2520)
.env

# Legacy files (from pre-Dolt versions)
*.db
*.db?*
*.db-journal
*.db-wal
*.db-shm
db.sqlite
bd.db
# NOTE: Do NOT add negation patterns here.
# They would override fork protection in .git/info/exclude.
# Config files (metadata.json, config.yaml) are tracked by git by default
# since no pattern above ignores them.
11 changes: 11 additions & 0 deletions .beads/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Beads-Kontext für userscripts

Diese lokale Beads-Datenbank speichert Aufgaben, Abhängigkeiten und ausdrücklich hinterlegtes Projektwissen. Harness Router lädt ihren Kontext vor jedem Auftrag automatisch; eine Aufgabenauswahl ist optional.

- Kontext prüfen: `bd prime --full --readonly`
- Verfügbare Aufgaben lesen: `bd ready --json --readonly`
- Wissen ausdrücklich hinterlegen: `bd remember "Projektwissen"`

Projektregeln bleiben in `AGENTS.md`. Initialisierung ohne Änderungen an Regeln und Git-Hooks. Aufgaben werden vom Router weder automatisch übernommen noch geschlossen.

Die Datenbank unter `embeddeddolt/` bleibt lokal und wird nicht durch normale Git-Commits gesichert. Versionierte Konfigurationsdateien ersetzen kein Datenbank-Backup; Datenübertragung und Sicherung erfolgen separat über Beads/Dolt.
75 changes: 75 additions & 0 deletions .beads/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Beads Configuration File
# This file configures default behavior for all bd commands in this repository
# All settings can also be set via environment variables (BD_* prefix)
# or overridden with command-line flags

# Issue prefix for this repository (used by bd init)
# If not set, bd init will auto-detect from directory name
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
# issue-prefix: ""

# Use no-db mode: JSONL-only, no Dolt database
# When true, .beads/issues.jsonl is the only local store
# no-db: false

# Enable JSON output by default
# json: false

# Feedback title formatting for mutating commands (create/update/close/dep/edit)
# 0 = hide titles, N > 0 = truncate to N characters
# output:
# title-length: 255

# Default actor for audit trails (overridden by BEADS_ACTOR or --actor)
# actor: ""

# Optional JSONL sidecar for explicit agent/tool interaction audit records.
# Issue history is always recorded in the database and is visible with
# bd history <id> --events; this only controls .beads/interactions.jsonl.
# audit:
# enabled: false

# Export events (audit trail) to .beads/events.jsonl on each flush/sync
# When enabled, new events are appended incrementally using a high-water mark.
# Use 'bd export --events' to trigger manually regardless of this setting.
# events-export: false

# Multi-repo configuration (experimental - bd-307)
# Allows hydrating from multiple repositories and routing writes to the correct database
# repos:
# primary: "." # Primary repo (where this database lives)
# additional: # Additional repos to hydrate from (read-only)
# - ~/beads-planning # Personal planning repo
# - ~/work-planning # Work planning repo

# Dolt-native backup (periodic backup for off-machine recovery)
# This is full database backup only. Cross-machine sync uses Dolt remotes.
# backup:
# enabled: false # Disable auto-backup entirely
# interval: 15m # Minimum time between auto-backups
# git-push: false # Disable git push (backup locally only)
# git-repo: "" # Separate git repo for backups (default: project repo)

# Optional JSONL auto-export for viewers, interchange, and issue-level migration.
# Disabled by default; enable only when an integration needs fresh .beads/issues.jsonl.
# Use relative paths under .beads/ for JSONL import/export filenames.
# export:
# auto: false
# path: issues.jsonl
# interval: 60s
# git-add: false
# import:
# path: issues.jsonl

# Integration settings (access with 'bd config get/set')
# Non-secret keys (stored in the database):
# - jira.url, jira.project
# - linear.team_id
# - github.org, github.repo
#
# Secret keys (stored in this file but prefer env vars to avoid git exposure):
# - linear.api_key → use LINEAR_API_KEY env var instead
# - github.token → use GITHUB_TOKEN env var instead

sync:
remote: "git+https://github.com/ysamjo/userscripts.git"
7 changes: 7 additions & 0 deletions .beads/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"database": "dolt",
"backend": "dolt",
"dolt_mode": "embedded",
"dolt_database": "userscripts",
"project_id": "e17ae08b-405b-4833-9545-2a71288c4f43"
}
44 changes: 44 additions & 0 deletions .github/workflows/suchkuerzel-transfer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Suchkürzel-Transfer App

on:
push:
paths:
- "browser-suchmigration/app/**"
- "browser-suchmigration/Suchkuerzel-Transfer.command"
- ".github/workflows/suchkuerzel-transfer.yml"
pull_request:
paths:
- "browser-suchmigration/app/**"
- "browser-suchmigration/Suchkuerzel-Transfer.command"
- ".github/workflows/suchkuerzel-transfer.yml"
workflow_dispatch:

jobs:
package:
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
defaults:
run:
working-directory: browser-suchmigration/app
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Linux Qt-Laufzeit installieren
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y libegl1 libgl1 libxkbcommon-x11-0 libdbus-1-3 libxcb-cursor0 libxcb-icccm4 libxcb-keysyms1 libxcb-shape0 libxcb-xinerama0 libxcb-xkb1
- run: python -m pip install -r requirements.txt
- name: Core-Selbsttest
run: python main.py --self-test
env:
QT_QPA_PLATFORM: offscreen
- name: Plattformpaket bauen
run: pyinstaller --noconfirm --clean SuchkuerzelTransfer.spec
- uses: actions/upload-artifact@v4
with:
name: SuchkuerzelTransfer-${{ matrix.os }}
path: browser-suchmigration/app/dist/
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Userscripts
.DS_Store
*.log

# Beads / Dolt files (added by bd init)
.dolt/
*.db
.beads-credential-key
.beads/proxieddb/
*.gate.lock*
26 changes: 26 additions & 0 deletions browser-suchmigration/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Browser-Suchmigration

Lokale Werkzeuge zum Übertragen benutzerdefinierter Suchmaschinen und Suchkürzel zwischen Chromium-Profilen. Die Desktop-App in `app/` lässt Quellbrowser, Zielbrowser und bei Bedarf die Profile direkt auswählen; sie nutzt PySide6 und bindet die vorhandene Transferlogik aus `Suchkuerzel-Transfer.command` ein. Die übrigen Skripte sind bestehende macOS-Werkzeuge.

## Grenzen

- Browserprofil-Daten bleiben lokal. Nie ein gesamtes Profil ersetzen.
- Vor jedem Import oder Wiederherstellen in der Desktop-App Browserbeendigung prüfen, Änderungen bestätigen lassen und eine SQLite-Sicherung anlegen.
- Nicht zugängliche Browserprofilordner bei der automatischen Suche überspringen und im UI melden, damit andere Browserprofile weiter nutzbar bleiben.
- Beim Wiederherstellen nur eigene Suchkürzel ändern; Browser- und andere Profiltabellen unverändert lassen.
- Exportformat in der bestehenden Transferdatei kompatibel halten. Standardsuche nur übernehmen, wenn die Quelle eine hat; die Auswahl muss der Nutzer im Browser bestätigen.
- Keine Zugangsdaten oder Browserinhalte außerhalb der Suchmaschinendaten erfassen.

## App-Befehle

Im Verzeichnis `app/`:

```bash
python -m venv .venv
python -m pip install -r requirements.txt
python main.py
python main.py --self-test
pyinstaller --noconfirm --clean SuchkuerzelTransfer.spec
```

Pakete für Windows, macOS und Linux jeweils auf dem Zielsystem bauen. Der GitHub-Workflow erledigt das für alle drei Systeme und führt den Kern-Selbsttest aus.
11 changes: 11 additions & 0 deletions browser-suchmigration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Browser-Suchmigration

Werkzeuge zum lokalen Übertragen und Sichern eigener Browser-Suchkürzel.

- [Suchkürzel-Transfer Desktop-App](app/README.md): Windows, macOS und Linux
- `Suchkuerzel-Transfer.command`: bisheriges macOS-Einzeldateiwerkzeug
- `Sicheres-Migrationsskript/`: bisherige macOS-GUI und CLI

Die neue Desktop-App verwendet dasselbe XML-Format wie `Suchkuerzel-Transfer.command`. Sie zeigt Änderungen vor dem Import an, erstellt vor dem Schreiben eine SQLite-Sicherung und ändert nur Suchkürzel. Änderungen an der Standardsuche müssen anschließend in den Browser-Einstellungen bestätigt werden.

Entwicklung und plattformspezifische Paketierung sind in [app/README.md](app/README.md) beschrieben. Das CI baut unter Windows, macOS und Ubuntu.
Binary file not shown.
Binary file not shown.
30 changes: 23 additions & 7 deletions browser-suchmigration/Suchkuerzel-Transfer.command
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ MAX_XML_SIZE = 750_000
MAX_FIREFOX_HTML_SIZE = 1_500_000
MAX_SHORTCUTS = 1_000
BACKUP_DIR = Path.home() / "Documents" / "Suchkuerzel-Backups"
DISCOVERY_WARNINGS: list[str] = []
BROWSERS = {
"chrome": {
"label": "Google Chrome",
Expand Down Expand Up @@ -251,8 +252,11 @@ def with_read_db(path: Path, operation):
if connection is not None:
connection.close()
with stable_snapshot(path) as snapshot:
with open_db(snapshot, read_only=True) as connection:
connection = open_db(snapshot, read_only=True)
try:
return operation(connection)
finally:
connection.close()


def custom_conditions(existing_columns: set[str]) -> list[str]:
Expand Down Expand Up @@ -378,14 +382,22 @@ def choose_default_search(profile: dict[str, Any]) -> dict[str, str]:

def discover_profiles() -> list[dict[str, Any]]:
result = []
DISCOVERY_WARNINGS.clear()
for browser_key, browser in BROWSERS.items():
root = browser["root"]
if not root.is_dir():
try:
if not root.is_dir():
continue
candidates = sorted(
(item for item in root.iterdir() if item.is_dir() and (item / "Web Data").is_file()),
key=profile_sort_key,
)
except PermissionError as error:
DISCOVERY_WARNINGS.append(f"{browser['label']}: kein Zugriff auf {root} ({error})")
continue
except OSError as error:
DISCOVERY_WARNINGS.append(f"{browser['label']}: Profilordner nicht lesbar: {error}")
continue
candidates = sorted(
(item for item in root.iterdir() if item.is_dir() and (item / "Web Data").is_file()),
key=profile_sort_key,
)
for directory in candidates:
try:
count = len(read_shortcuts(directory / "Web Data"))
Expand Down Expand Up @@ -846,11 +858,15 @@ def self_test() -> None:
enforced_by_policy INTEGER DEFAULT 0, featured_by_policy INTEGER DEFAULT 0, url_hash BLOB
);
"""
with sqlite3.connect(db_path) as connection:
connection = sqlite3.connect(db_path)
try:
connection.executescript(schema)
connection.execute(
"INSERT INTO keywords (short_name,keyword,favicon_url,url,input_encodings,is_active,sync_guid) VALUES ('Test','t','','https://example.test/?q={searchTerms}','UTF-8',1,'test-guid')"
)
connection.commit()
finally:
connection.close()
(profile_dir / "Preferences").write_text(
json.dumps({"default_search_provider": {"guid": "test-guid"}}), encoding="utf-8"
)
Expand Down
5 changes: 5 additions & 0 deletions browser-suchmigration/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.venv/
build/
dist/
__pycache__/
*.py[cod]
Loading
Loading