diff --git a/.env.example b/.env.example
index 29f14914a..0a489f10e 100644
--- a/.env.example
+++ b/.env.example
@@ -13,3 +13,7 @@ ANTHROPIC_API_KEY=your-anthropic-api-key
# Rev.ai token for imported audio transcription (optional)
# Sign up: https://www.rev.ai/ then get token at https://www.rev.ai/access_token
REVAI_ACCESS_TOKEN=your-revai-token
+
+# Plaud access token for importing Plaud recordings (optional)
+# Log into the Plaud web portal and extract token from browser console
+PLAUD_ACCESS_TOKEN=your-plaud-token
diff --git a/apps/settings/routes.py b/apps/settings/routes.py
index 0f4bcc2c4..ac148bbb4 100644
--- a/apps/settings/routes.py
+++ b/apps/settings/routes.py
@@ -30,6 +30,7 @@ API_KEY_ENV_VARS = [
"ANTHROPIC_API_KEY",
"OPENAI_API_KEY",
"REVAI_ACCESS_TOKEN",
+ "PLAUD_ACCESS_TOKEN",
]
@@ -66,7 +67,7 @@ def update_config() -> Any:
- identity: User profile (name, preferred, bio, pronouns, aliases, etc.)
- transcribe: Transcription settings (device, model, compute_type)
- convey: Web app settings (password)
- - env: API keys (GOOGLE_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, REVAI_ACCESS_TOKEN)
+ - env: API keys (GOOGLE_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, REVAI_ACCESS_TOKEN, PLAUD_ACCESS_TOKEN)
Note: Model/provider configuration is done via the 'providers' section in
journal.json. See docs/JOURNAL.md for the providers config format.
diff --git a/apps/settings/workspace.html b/apps/settings/workspace.html
index 42e892457..c2e5109cf 100644
--- a/apps/settings/workspace.html
+++ b/apps/settings/workspace.html
@@ -1761,6 +1761,16 @@ input:checked + .slider:before {
Audio transcription for imported files. Get token
+
+
+
+
+
+
+
Import audio from Plaud recorder. Log into the web portal and extract token from browser console.
+
@@ -2342,6 +2352,7 @@ function populateFields(config) {
updateEnvStatus('field-env-openai', env.OPENAI_API_KEY, sysEnv.OPENAI_API_KEY);
updateEnvStatus('field-env-anthropic', env.ANTHROPIC_API_KEY, sysEnv.ANTHROPIC_API_KEY);
updateEnvStatus('field-env-revai', env.REVAI_ACCESS_TOKEN, sysEnv.REVAI_ACCESS_TOKEN);
+ updateEnvStatus('field-env-plaud', env.PLAUD_ACCESS_TOKEN, sysEnv.PLAUD_ACCESS_TOKEN);
}
function updateEnvStatus(fieldId, isJournalConfigured, isSystemConfigured) {
diff --git a/docs/JOURNAL.md b/docs/JOURNAL.md
index 578ef5b5b..7741268d8 100644
--- a/docs/JOURNAL.md
+++ b/docs/JOURNAL.md
@@ -159,7 +159,8 @@ The `env` block provides fallback values for environment variables. These are lo
"GOOGLE_API_KEY": "your-google-api-key",
"ANTHROPIC_API_KEY": "your-anthropic-api-key",
"OPENAI_API_KEY": "your-openai-api-key",
- "REVAI_ACCESS_TOKEN": "your-revai-token"
+ "REVAI_ACCESS_TOKEN": "your-revai-token",
+ "PLAUD_ACCESS_TOKEN": "your-plaud-token"
}
}
```
diff --git a/tests/test_importer_sync.py b/tests/test_importer_sync.py
index ec46bb64c..09566b8c7 100644
--- a/tests/test_importer_sync.py
+++ b/tests/test_importer_sync.py
@@ -75,14 +75,24 @@ def test_plaud_protocol_conformance():
assert isinstance(PlaudBackend(), SyncableBackend)
-def test_plaud_sync_not_implemented(tmp_path):
- """PlaudBackend.sync() raises NotImplementedError."""
+def test_plaud_sync_not_implemented(tmp_path, monkeypatch):
+ """With token configured, PlaudBackend.sync() raises NotImplementedError."""
from think.importers.plaud import PlaudBackend
+ monkeypatch.setenv("PLAUD_ACCESS_TOKEN", "test-token")
with pytest.raises(NotImplementedError):
PlaudBackend().sync(tmp_path)
+def test_plaud_sync_requires_token(tmp_path, monkeypatch):
+ """Without token configured, PlaudBackend.sync() raises ValueError."""
+ from think.importers.plaud import PlaudBackend
+
+ monkeypatch.delenv("PLAUD_ACCESS_TOKEN", raising=False)
+ with pytest.raises(ValueError, match="PLAUD_ACCESS_TOKEN"):
+ PlaudBackend().sync(tmp_path)
+
+
def test_backends_cli_flag(capsys, monkeypatch):
"""sol import --backends lists plaud."""
import sys
diff --git a/think/importers/plaud.py b/think/importers/plaud.py
index 268796b2e..97a100eab 100644
--- a/think/importers/plaud.py
+++ b/think/importers/plaud.py
@@ -282,6 +282,11 @@ class PlaudBackend:
Not yet implemented — Phase 2 will wire up actual sync.
"""
+ token = os.getenv("PLAUD_ACCESS_TOKEN")
+ if not token:
+ raise ValueError(
+ "PLAUD_ACCESS_TOKEN not configured — set in Settings > API Keys"
+ )
raise NotImplementedError("Plaud sync execution is not yet implemented")