Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
34 changes: 34 additions & 0 deletions .beads/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# SQLite databases
*.db
*.db?*
*.db-journal
*.db-wal
*.db-shm

# Daemon runtime files
daemon.lock
daemon.log
daemon.pid
bd.sock
sync-state.json

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

# Legacy database files
db.sqlite
bd.db

# Merge artifacts (temporary files from 3-way merge)
beads.base.jsonl
beads.base.meta.json
beads.left.jsonl
beads.left.meta.json
beads.right.jsonl
beads.right.meta.json

# Keep JSONL exports and config (source of truth for git)
!issues.jsonl
!interactions.jsonl
!metadata.json
!config.json
81 changes: 81 additions & 0 deletions .beads/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Beads - AI-Native Issue Tracking

Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code.

## What is Beads?

Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git.

**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads)

## Quick Start

### Essential Commands

```bash
# Create new issues
bd create "Add user authentication"

# View all issues
bd list

# View issue details
bd show <issue-id>

# Update issue status
bd update <issue-id> --status in_progress
bd update <issue-id> --status done

# Sync with git remote
bd sync
```

### Working with Issues

Issues in Beads are:
- **Git-native**: Stored in `.beads/issues.jsonl` and synced like code
- **AI-friendly**: CLI-first design works perfectly with AI coding agents
- **Branch-aware**: Issues can follow your branch workflow
- **Always in sync**: Auto-syncs with your commits

## Why Beads?

**AI-Native Design**
- Built specifically for AI-assisted development workflows
- CLI-first interface works seamlessly with AI coding agents
- No context switching to web UIs

🚀 **Developer Focused**
- Issues live in your repo, right next to your code
- Works offline, syncs when you push
- Fast, lightweight, and stays out of your way

🔧 **Git Integration**
- Automatic sync with git commits
- Branch-aware issue tracking
- Intelligent JSONL merge resolution

## Get Started with Beads

Try Beads in your own projects:

```bash
# Install Beads
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash

# Initialize in your repo
bd init

# Create your first issue
bd create "Try out Beads"
```

## Learn More

- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs)
- **Quick Start Guide**: Run `bd quickstart`
- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples)

---

*Beads: Issue tracking that moves at the speed of thought*
62 changes: 62 additions & 0 deletions .beads/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# 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: load from JSONL, no SQLite, write back after each command
# When true, bd will use .beads/issues.jsonl as the source of truth
# instead of SQLite database
# no-db: false

# Disable daemon for RPC communication (forces direct database access)
# no-daemon: false

# Disable auto-flush of database to JSONL after mutations
# no-auto-flush: false

# Disable auto-import from JSONL when it's newer than database
# no-auto-import: false

# Enable JSON output by default
# json: false

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

# Path to database (overridden by BEADS_DB or --db)
# db: ""

# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON)
# auto-start-daemon: true

# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE)
# flush-debounce: "5s"

# Git branch for beads commits (bd sync will commit to this branch)
# IMPORTANT: Set this for team projects so all clones use the same sync branch.
# This setting persists across clones (unlike database config which is gitignored).
# Can also use BEADS_SYNC_BRANCH env var for local override.
# If not set, bd sync will require you to run 'bd config set sync.branch <branch>'.
# sync-branch: "beads-sync"

# Multi-repo configuration (experimental - bd-307)
# Allows hydrating from multiple repositories and routing writes to the correct JSONL
# 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

# Integration settings (access with 'bd config get/set')
# These are stored in the database, not in this file:
# - jira.url
# - jira.project
# - linear.url
# - linear.api-key
# - github.org
# - github.repo
Empty file added .beads/interactions.jsonl
Empty file.
16 changes: 16 additions & 0 deletions .beads/issues.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{"id":"damus-1aq","title":"NIP-07: Add Safari extension setup UI in Damus settings","description":"Add settings section to guide users to enable extension in Safari settings.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T22:49:03.243728-06:00","created_by":"e","updated_at":"2026-01-05T23:28:04.327943-06:00","closed_at":"2026-01-05T23:28:04.327943-06:00","close_reason":"Added SafariExtensionSettingsView with setup instructions and Open Settings button. Added route and navigation link in ConfigView.","labels":["nip-07"]}
{"id":"damus-1ri","title":"Comingle: Support read-only mode with external signer","description":"When using external signer, user doesn't have local keypair. Support login with just npub, then delegate all signing to external signer. Update SignInView to allow npub-only login when external signer is configured.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T23:33:14.609065-06:00","created_by":"e","updated_at":"2026-01-05T23:58:31.7734-06:00","closed_at":"2026-01-05T23:58:31.7734-06:00","close_reason":"Updated SignInView to show appropriate footer when using npub with external signer. Added @AppStorage for useExternalSigner preference.","labels":["comingle","dip-05"]}
{"id":"damus-399","title":"NIP-07: Align Damoose App Group with main app (group.com.damus)","description":"Ensure Damoose extension uses same App Group as main app for shared UserDefaults access.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T22:48:56.894774-06:00","created_by":"e","updated_at":"2026-01-05T22:56:27.895164-06:00","closed_at":"2026-01-05T22:56:27.895164-06:00","close_reason":"Closed","labels":["nip-07"]}
{"id":"damus-5vq","title":"NIP-07: Wire popup approval UI to SigningPolicyManager","description":"signEvent now works directly in extension. Popup approval UI is functional. TODO: Integrate with SigningPolicyManager for remembered permissions and kind-based policies.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T22:48:56.800249-06:00","created_by":"e","updated_at":"2026-01-05T23:25:45.012115-06:00","closed_at":"2026-01-05T23:25:45.012115-06:00","close_reason":"Implemented permission storage and remember checkbox. Popup now checks saved permissions before showing. JS and Swift handlers updated.","labels":["nip-07"]}
{"id":"damus-624","title":"NIP-07: Restore jb55's Damoose extension from origin/extension branch","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T22:48:45.202461-06:00","created_by":"e","updated_at":"2026-01-05T22:51:55.963827-06:00","closed_at":"2026-01-05T22:51:55.963827-06:00","close_reason":"Restored Damoose extension from origin/extension, added target to Xcode project, fixed Info.plist","labels":["nip-07"]}
{"id":"damus-77k","title":"Comingle: Register callback URL scheme for signer responses","description":"Register comingle:// (or similar) URL scheme in Info.plist to receive signed event callbacks from Damus signer. Handle incoming URL and complete pending signing requests.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T23:33:14.510039-06:00","created_by":"e","updated_at":"2026-01-05T23:56:54.669006-06:00","closed_at":"2026-01-05T23:56:54.669006-06:00","close_reason":"Registered comingle:// URL scheme in Info.plist CFBundleURLTypes. Added handleCallback in ExternalSigner and onOpenURL handler in ComingleApp.","labels":["comingle","dip-05"]}
{"id":"damus-81o","title":"Comingle: Add external signer selection UI in settings","description":"Add settings screen for users to choose between local signing (keypair in keychain) vs external signer (Damus via NIP-55). Store preference in UserDefaults.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T23:33:14.305841-06:00","created_by":"e","updated_at":"2026-01-05T23:57:48.881982-06:00","closed_at":"2026-01-05T23:57:48.881982-06:00","close_reason":"Created SignerSettingsView with toggle for external signer and status display. Added navigation link in SettingsView. Uses @AppStorage for persistence.","labels":["comingle","dip-05"]}
{"id":"damus-964","title":"Comingle: Refactor CreateProfileView for external signing","description":"Apply the external signing pattern to CreateProfileView. Add UnsignedEventBuilder methods for metadata and followList events. Use ExternalSigner when no local keypair.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T00:01:45.288429-06:00","created_by":"e","updated_at":"2026-01-06T00:13:08.364447-06:00","closed_at":"2026-01-06T00:13:08.364447-06:00","close_reason":"Added UnsignedEventBuilder.metadataEvent and followListEvent for completeness. CreateProfileView is for local keypair creation - external signer users should use SignInView with their npub since they already have keys in Damus.","labels":["comingle","dip-05"]}
{"id":"damus-gtf","title":"NIP-07: Implement signEvent in native handler","description":"signEvent stores request in shared storage for main app to process. Requires JS-side updates to open nostrsigner:// URL and poll via checkResult. Native handler checkResult implemented for polling.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T22:48:56.706037-06:00","created_by":"e","updated_at":"2026-01-05T23:00:49.517762-06:00","closed_at":"2026-01-05T23:00:49.517762-06:00","close_reason":"Closed","labels":["nip-07"]}
{"id":"damus-h5x","title":"Comingle: Refactor EventCreating to support async external signing","description":"Current signing is synchronous via signedBy: keypair. Refactor to support async flow: build unsigned event, call nostrsigner://, await callback with signed event. Affects CreateOrModifyCalendarView, CreateOrModifyEventView, EventView, CreateProfileView.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T23:33:14.409777-06:00","created_by":"e","updated_at":"2026-01-06T00:00:16.588338-06:00","closed_at":"2026-01-06T00:00:16.588338-06:00","close_reason":"Created EventSigningService and UnsignedEventBuilder utilities. Refactored EventView.createOrUpdateRSVP to support both local and external signing. External signing uses ExternalSigner.requestSignEvent with callback handling.","labels":["comingle","dip-05"]}
{"id":"damus-i7r","title":"Examine Comingle iOS app for gaps against Damus signer interaction","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T22:53:43.645549-06:00","created_by":"e","updated_at":"2026-01-05T23:32:12.099974-06:00","closed_at":"2026-01-05T23:32:12.099974-06:00","close_reason":"Analyzed Comingle iOS app. Gaps: No NIP-55 support (nostrsigner://), no external signer UI, hard-coded local signing via NostrSDK EventCreating protocol, no read-only mode for signing operations."}
{"id":"damus-mfz","title":"Comingle: Refactor CreateOrModifyCalendarView for external signing","description":"Apply the external signing pattern to CreateOrModifyCalendarView. Add UnsignedEventBuilder.calendarList and use ExternalSigner for calendar creation when no local keypair.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T00:01:45.188278-06:00","created_by":"e","updated_at":"2026-01-06T00:12:17.083002-06:00","closed_at":"2026-01-06T00:12:17.083002-06:00","close_reason":"Added UnsignedEventBuilder.calendarListEvent. Refactored ViewModel with canSign, isSaving, saveError, onSaveSuccess. Updated save to support local and external signing.","labels":["comingle","dip-05"]}
{"id":"damus-qtm","title":"Comingle: Refactor CreateOrModifyEventView for external signing","description":"Apply the external signing pattern from EventView to CreateOrModifyEventView. Use UnsignedEventBuilder.timeBasedCalendarEvent and ExternalSigner for event creation when no local keypair.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T00:01:45.075757-06:00","created_by":"e","updated_at":"2026-01-06T00:10:55.545802-06:00","closed_at":"2026-01-06T00:10:55.545802-06:00","close_reason":"Added canSign check, refactored saveEvent to support local and external signing, added isSaving state and error handling, updated toolbar with progress indicator.","labels":["comingle","dip-05"]}
{"id":"damus-qz8","title":"Update Damoose JS to handle signEvent delegation (open URL, poll checkResult)","description":"The native handler now stores signEvent requests. JS side needs to: 1) Detect nil response from signEvent, 2) Open nostrsigner:// URL, 3) Poll checkResult for signed event","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T23:01:00.455983-06:00","created_by":"e","updated_at":"2026-01-05T23:17:31.404215-06:00","closed_at":"2026-01-05T23:17:31.404215-06:00","close_reason":"Closed"}
{"id":"damus-s9o","title":"Comingle: Add DIP-05 nostrsigner:// URL scheme handler","description":"Implement nostrsigner:// URL scheme handling to delegate signing to external apps like Damus. Register URL scheme in Info.plist and handle incoming callbacks.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T23:32:44.114107-06:00","created_by":"e","updated_at":"2026-01-05T23:56:54.588949-06:00","closed_at":"2026-01-05T23:56:54.588949-06:00","close_reason":"Created ExternalSigner.swift with buildSignEventURL, buildGetPublicKeyURL, requestSignEvent, requestPublicKey methods. Added nostrsigner to LSApplicationQueriesSchemes.","labels":["comingle","dip-05"]}
{"id":"damus-ydw","title":"NIP-07: Wire native handler to SharedKeychainStorage for getPublicKey","description":"Replace hardcoded pubkey in SafariWebExtensionHandler with SharedKeychainStorage.getPublicKey()","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T22:48:56.611017-06:00","created_by":"e","updated_at":"2026-01-05T22:56:27.865697-06:00","closed_at":"2026-01-05T22:56:27.865697-06:00","close_reason":"Closed","labels":["nip-07"]}
4 changes: 4 additions & 0 deletions .beads/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"database": "beads.db",
"jsonl_export": "issues.jsonl"
}
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads
Comment on lines +1 to +3

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Verify merge driver configuration and PR scope.

Two concerns:

  1. Missing setup documentation: The custom merge driver merge=beads requires git configuration (git config merge.beads.driver '...') which is not documented in this PR. Users will encounter merge failures without this setup.

  2. Scope concern: This file and other Beads-related changes (.beads/.gitignore, .beads/README.md, AGENTS.md bd sync workflow) introduce an issue-tracking system completely unrelated to the stated PR objectives (Damoose NIP-07/DIP-05 signing solution). Consider splitting infrastructure changes into a separate PR for clearer review and rollback capability.

📋 Suggested verification
#!/bin/bash
# Check if beads merge driver setup is documented anywhere in the PR
rg -i "merge.*beads.*driver" --type md
rg -i "git config.*beads" --type md
🤖 Prompt for AI Agents
In @.gitattributes around lines 1-3, The .gitattributes entry adds a custom
merge driver (merge=beads) but the PR lacks any git configuration or
documentation for that driver and also mixes unrelated Beads infra changes into
a feature PR; add explicit setup docs showing the required git config (e.g., the
merge.beads.driver command and any helper script usage) in .beads/README.md or a
CONTRIBUTING/AGENTS.md section, and split the Beads-specific files
(.gitattributes, .beads/, .beads/README.md, .beads/.gitignore, AGENTS.md bd sync
workflow) into a separate infrastructure PR so the Damoose NIP-07/DIP-05 signing
solution PR only contains signing-related changes.

26 changes: 26 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,29 @@ Damus is an iOS client built around a local relay model ([damus-io/damus#3204](h
7. Review and follow `pull_request_template.md` when creating PRs for iOS Damus.
8. Ensure nevernesting: favor early returns and guard clauses over deeply nested conditionals; simplify control flow by exiting early instead of wrapping logic in multiple layers of `if` statements.
9. Before proposing changes, please **review and analyze if a change or upgrade to nostrdb** is beneficial to the change at hand.

## Landing the Plane (Session Completion)

**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.

**MANDATORY WORKFLOW:**

1. **File issues for remaining work** - Create issues for anything that needs follow-up
2. **Run quality gates** (if code changed) - Tests, linters, builds
3. **Update issue status** - Close finished work, update in-progress items
4. **PUSH TO REMOTE** - This is MANDATORY:
```bash
git pull --rebase
bd sync
git push
git status # MUST show "up to date with origin"
```
5. **Clean up** - Clear stashes, prune remote branches
6. **Verify** - All changes committed AND pushed
7. **Hand off** - Provide context for next session

**CRITICAL RULES:**
- Work is NOT complete until `git push` succeeds
- NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds
18 changes: 18 additions & 0 deletions Damoose/Damoose.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<false/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.damus</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.jb55.damus2</string>
</array>
</dict>
</plist>
31 changes: 31 additions & 0 deletions Damoose/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>Damoose</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.Safari.web-extension</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).SafariWebExtensionHandler</string>
</dict>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2024 Damus. All rights reserved.</string>
</dict>
</plist>
14 changes: 14 additions & 0 deletions Damoose/Resources/_locales/en/messages.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extension_name": {
"message": "Damoose",
"description": "The display name for the extension."
},
"extension_description": {
"message": "The Damus nostr safari companion. Protect your key and create web highlights.",
"description": "Description of what the extension does."
},
"menuHighlight": {
"message": "Highlight",
"description": "The context menu item for the highlight action"
}
}
Loading