I’m having fun experimenting with different extensions, but the extension settings functionality doesn’t seem to work for me.
I used Claude Code to create a minimal reproducible example, and I see the setting checkbox in the Extension Settings panel, but checking/unchecking the setting doesn’t seem to do anything.
Also, I’m finding the Logs Explorer helpful, but I don’t see any logs coming from the DOM file Settings.tsx
Please see below for a bug report created via Claude Code.
Bug report: bike.defaults.set() in DOM context not visible to app context
Summary
When an extension’s settings UI (DOM context) calls bike.defaults.set(key, value), the change is not visible to bike.defaults.get(key) in the app context, and bike.defaults.observe(key, ...) in the app context never fires. Restarting Bike does not resolve the issue.
The app context continues to return the value registered via bike.defaults.registerDefaults(), as if the DOM’s write never happened.
Environment
- Bike version: 273
@bike-outliner/extension-kit version: 0.7.1
- macOS: Tahoe
Minimum reproducible example
Three files, scaffolded from npx bike-ext new test-settings:
manifest.json
{
"$schema": "../../node_modules/@bike-outliner/extension-kit/schemas/manifest.schema.json",
"version": "0.1.0",
"api_version": "0.0.0",
"permissions": [],
"host_permissions": []
}
app/main.ts
import { AppExtensionContext, CommandContext } from 'bike/app'
export async function activate(context: AppExtensionContext) {
console.log('[test-settings app] activate start, get(mySetting) =', bike.defaults.get('mySetting'))
bike.defaults.registerDefaults({ 'mySetting': true })
console.log('[test-settings app] after registerDefaults, get(mySetting) =', bike.defaults.get('mySetting'))
bike.defaults.observe('mySetting', (v) => {
console.log('[test-settings app] observe(mySetting) fired =', v)
})
bike.settings.addItem({
label: 'Test Settings',
script: 'Settings.js',
})
bike.commands.addCommands({
commands: {
'test-settings:show': showCommand,
},
})
}
function showCommand(context: CommandContext): boolean {
const value = bike.defaults.get('mySetting')
console.log('[test-settings app] showCommand read =', value)
if (context.editor) {
context.editor.showStatusMessage(`mySetting = ${String(value)}`, 3000)
}
return true
}
dom/Settings.tsx
import { DOMExtensionContext } from 'bike/dom'
import { Checkbox, Disclosure } from 'bike/components'
import { createRoot } from 'react-dom/client'
import { useState } from 'react'
export function activate(context: DOMExtensionContext) {
console.log('[test-settings dom] activate, get(mySetting) =', bike.defaults.get('mySetting'))
createRoot(context.element).render(<SettingsPanel />)
}
function SettingsPanel() {
const [checked, setChecked] = useState(
() => bike.defaults.get('mySetting') !== false
)
function onChange(value: boolean) {
setChecked(value)
console.log('[test-settings dom] set(mySetting) =', value)
bike.defaults.set('mySetting', value)
console.log('[test-settings dom] after set, get(mySetting) =', bike.defaults.get('mySetting'))
}
return (
<Disclosure label="Test Settings" defaultExpanded>
<Checkbox checked={checked} onChange={(e) => onChange(e.target.checked)}>
My test setting
</Checkbox>
</Disclosure>
)
}
Steps to reproduce
- Build and install the extension:
npx bike-ext build test-settings --install
- Launch Bike
- Open Settings > Extensions > Test Settings
- Uncheck the “My test setting” checkbox
- Run the
test-settings:show command via the command palette
- Quit and relaunch Bike; run the command again
Expected behavior
- After unchecking the checkbox, the app context’s
bike.defaults.observe('mySetting', ...) callback should fire with false
- Running
test-settings:show should display mySetting = false in the status bar
- After a restart, the setting should remain
false
Actual behavior
- The
observe() callback in the app context never fires when the DOM checkbox is toggled
- Running
test-settings:show always displays mySetting = true (the registered default)
- Restarting Bike does not change this — the app context always sees the default, as if the DOM’s
set() was never persisted to or visible to the app side
Logs
Bike’s [notice] channel shows only the app-context logs:
[notice] bike/app/test-settings: [test-settings app] activate start, get(mySetting) = undefined
[notice] bike/app/test-settings: [test-settings app] after registerDefaults, get(mySetting) = true
[notice] bike/app/test-settings: [test-settings app] showCommand read = true
Notably:
- No
[test-settings app] observe(mySetting) fired = ... log ever appears, even after toggling the checkbox multiple times
showCommand reads true both before and after the checkbox is unchecked, including across full Bike restarts
- (DOM-context
console.log output from Settings.tsx was not visible in the notice log stream, so I can’t confirm whether the DOM-side bike.defaults.set() is even being invoked — but the React checkbox state does update visually, so onChange is firing.)
Notes
- The calendar extension in
core-extensions uses the same pattern (DOM writes to bike.defaults, app reads from it), but its effects are only observable when creating new date rows with format strings — so a silent fallback to defaults there would be easy to miss.
- Per
api/dom/globals.d.ts and api/app/bike.d.ts, both bike.defaults stores are documented as “backed by UserDefaults with the prefix bike.ext.<extensionId>.” — so they should be the same underlying store.