garlic-cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. garlic_cli-0.1.0/.beads/.gitignore +49 -0
  2. garlic_cli-0.1.0/.beads/.local_version +1 -0
  3. garlic_cli-0.1.0/.beads/README.md +81 -0
  4. garlic_cli-0.1.0/.beads/backup/backup_state.json +13 -0
  5. garlic_cli-0.1.0/.beads/backup/comments.jsonl +0 -0
  6. garlic_cli-0.1.0/.beads/backup/config.jsonl +11 -0
  7. garlic_cli-0.1.0/.beads/backup/dependencies.jsonl +15 -0
  8. garlic_cli-0.1.0/.beads/backup/events.jsonl +20 -0
  9. garlic_cli-0.1.0/.beads/backup/issues.jsonl +10 -0
  10. garlic_cli-0.1.0/.beads/backup/labels.jsonl +0 -0
  11. garlic_cli-0.1.0/.beads/config.yaml +54 -0
  12. garlic_cli-0.1.0/.beads/dolt/.bd-dolt-ok +1 -0
  13. garlic_cli-0.1.0/.beads/dolt/.beads-credential-key +1 -0
  14. garlic_cli-0.1.0/.beads/dolt/config.yaml +96 -0
  15. garlic_cli-0.1.0/.beads/dolt-server.lock +0 -0
  16. garlic_cli-0.1.0/.beads/dolt-server.log +464 -0
  17. garlic_cli-0.1.0/.beads/dolt-server.pid +1 -0
  18. garlic_cli-0.1.0/.beads/dolt-server.port +1 -0
  19. garlic_cli-0.1.0/.beads/hooks/post-checkout +24 -0
  20. garlic_cli-0.1.0/.beads/hooks/post-merge +24 -0
  21. garlic_cli-0.1.0/.beads/hooks/pre-commit +24 -0
  22. garlic_cli-0.1.0/.beads/hooks/pre-push +24 -0
  23. garlic_cli-0.1.0/.beads/hooks/prepare-commit-msg +24 -0
  24. garlic_cli-0.1.0/.beads/interactions.jsonl +0 -0
  25. garlic_cli-0.1.0/.beads/last-touched +1 -0
  26. garlic_cli-0.1.0/.beads/metadata.json +7 -0
  27. garlic_cli-0.1.0/.claude/settings.local.json +16 -0
  28. garlic_cli-0.1.0/.gitignore +11 -0
  29. garlic_cli-0.1.0/CLAUDE.md +105 -0
  30. garlic_cli-0.1.0/LICENSE +21 -0
  31. garlic_cli-0.1.0/PKG-INFO +94 -0
  32. garlic_cli-0.1.0/README.md +80 -0
  33. garlic_cli-0.1.0/pyproject.toml +35 -0
  34. garlic_cli-0.1.0/src/garlic/__init__.py +1 -0
  35. garlic_cli-0.1.0/src/garlic/cli.py +102 -0
  36. garlic_cli-0.1.0/src/garlic/config.py +51 -0
  37. garlic_cli-0.1.0/src/garlic/engine.py +52 -0
  38. garlic_cli-0.1.0/src/garlic/hooks.py +46 -0
  39. garlic_cli-0.1.0/src/garlic/nudges.py +52 -0
  40. garlic_cli-0.1.0/src/garlic/setup.py +76 -0
  41. garlic_cli-0.1.0/src/garlic/state.py +90 -0
  42. garlic_cli-0.1.0/tests/__init__.py +0 -0
  43. garlic_cli-0.1.0/tests/test_cli.py +29 -0
  44. garlic_cli-0.1.0/tests/test_config.py +86 -0
  45. garlic_cli-0.1.0/tests/test_engine.py +143 -0
  46. garlic_cli-0.1.0/tests/test_hooks.py +152 -0
  47. garlic_cli-0.1.0/tests/test_nudges.py +39 -0
  48. garlic_cli-0.1.0/tests/test_setup.py +67 -0
  49. garlic_cli-0.1.0/tests/test_state.py +112 -0
  50. garlic_cli-0.1.0/uv.lock +593 -0
@@ -0,0 +1,49 @@
1
+ # Dolt database (managed by Dolt, not git)
2
+ dolt/
3
+ dolt-access.lock
4
+
5
+ # Runtime files
6
+ bd.sock
7
+ bd.sock.startlock
8
+ sync-state.json
9
+ last-touched
10
+
11
+ # Local version tracking (prevents upgrade notification spam after git ops)
12
+ .local_version
13
+
14
+ # Worktree redirect file (contains relative path to main repo's .beads/)
15
+ # Must not be committed as paths would be wrong in other clones
16
+ redirect
17
+
18
+ # Sync state (local-only, per-machine)
19
+ # These files are machine-specific and should not be shared across clones
20
+ .sync.lock
21
+ export-state/
22
+
23
+ # Ephemeral store (SQLite - wisps/molecules, intentionally not versioned)
24
+ ephemeral.sqlite3
25
+ ephemeral.sqlite3-journal
26
+ ephemeral.sqlite3-wal
27
+ ephemeral.sqlite3-shm
28
+
29
+ # Dolt server management (auto-started by bd)
30
+ dolt-server.pid
31
+ dolt-server.log
32
+ dolt-server.lock
33
+ dolt-server.port
34
+
35
+ # Backup data (auto-exported JSONL, local-only)
36
+ backup/
37
+
38
+ # Legacy files (from pre-Dolt versions)
39
+ *.db
40
+ *.db?*
41
+ *.db-journal
42
+ *.db-wal
43
+ *.db-shm
44
+ db.sqlite
45
+ bd.db
46
+ # NOTE: Do NOT add negation patterns here.
47
+ # They would override fork protection in .git/info/exclude.
48
+ # Config files (metadata.json, config.yaml) are tracked by git by default
49
+ # since no pattern above ignores them.
@@ -0,0 +1 @@
1
+ 0.60.0
@@ -0,0 +1,81 @@
1
+ # Beads - AI-Native Issue Tracking
2
+
3
+ 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.
4
+
5
+ ## What is Beads?
6
+
7
+ 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.
8
+
9
+ **Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads)
10
+
11
+ ## Quick Start
12
+
13
+ ### Essential Commands
14
+
15
+ ```bash
16
+ # Create new issues
17
+ bd create "Add user authentication"
18
+
19
+ # View all issues
20
+ bd list
21
+
22
+ # View issue details
23
+ bd show <issue-id>
24
+
25
+ # Update issue status
26
+ bd update <issue-id> --claim
27
+ bd update <issue-id> --status done
28
+
29
+ # Sync with Dolt remote
30
+ bd dolt push
31
+ ```
32
+
33
+ ### Working with Issues
34
+
35
+ Issues in Beads are:
36
+ - **Git-native**: Stored in Dolt database with version control and branching
37
+ - **AI-friendly**: CLI-first design works perfectly with AI coding agents
38
+ - **Branch-aware**: Issues can follow your branch workflow
39
+ - **Always in sync**: Auto-syncs with your commits
40
+
41
+ ## Why Beads?
42
+
43
+ ✨ **AI-Native Design**
44
+ - Built specifically for AI-assisted development workflows
45
+ - CLI-first interface works seamlessly with AI coding agents
46
+ - No context switching to web UIs
47
+
48
+ 🚀 **Developer Focused**
49
+ - Issues live in your repo, right next to your code
50
+ - Works offline, syncs when you push
51
+ - Fast, lightweight, and stays out of your way
52
+
53
+ 🔧 **Git Integration**
54
+ - Automatic sync with git commits
55
+ - Branch-aware issue tracking
56
+ - Dolt-native three-way merge resolution
57
+
58
+ ## Get Started with Beads
59
+
60
+ Try Beads in your own projects:
61
+
62
+ ```bash
63
+ # Install Beads
64
+ curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
65
+
66
+ # Initialize in your repo
67
+ bd init
68
+
69
+ # Create your first issue
70
+ bd create "Try out Beads"
71
+ ```
72
+
73
+ ## Learn More
74
+
75
+ - **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs)
76
+ - **Quick Start Guide**: Run `bd quickstart`
77
+ - **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples)
78
+
79
+ ---
80
+
81
+ *Beads: Issue tracking that moves at the speed of thought* ⚡
@@ -0,0 +1,13 @@
1
+ {
2
+ "last_dolt_commit": "67hft9e22hhnthlcumcpeospbbm6m0tn",
3
+ "last_event_id": 0,
4
+ "timestamp": "2026-03-16T13:30:07.162230446Z",
5
+ "counts": {
6
+ "issues": 10,
7
+ "events": 20,
8
+ "comments": 0,
9
+ "dependencies": 15,
10
+ "labels": 0,
11
+ "config": 11
12
+ }
13
+ }
File without changes
@@ -0,0 +1,11 @@
1
+ {"key":"auto_compact_enabled","value":"false"}
2
+ {"key":"compact_batch_size","value":"50"}
3
+ {"key":"compact_parallel_workers","value":"5"}
4
+ {"key":"compact_tier1_days","value":"30"}
5
+ {"key":"compact_tier1_dep_levels","value":"2"}
6
+ {"key":"compact_tier2_commits","value":"100"}
7
+ {"key":"compact_tier2_days","value":"90"}
8
+ {"key":"compact_tier2_dep_levels","value":"5"}
9
+ {"key":"compaction_enabled","value":"false"}
10
+ {"key":"issue_prefix","value":"garlic"}
11
+ {"key":"schema_version","value":"6"}
@@ -0,0 +1,15 @@
1
+ {"created_at":"2026-03-16T15:14:53Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-8ud","issue_id":"garlic-8gf","metadata":"{}","type":"blocks"}
2
+ {"created_at":"2026-03-16T15:14:52Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-8ud","issue_id":"garlic-9ja","metadata":"{}","type":"blocks"}
3
+ {"created_at":"2026-03-16T15:14:54Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-9ja","issue_id":"garlic-9q9","metadata":"{}","type":"blocks"}
4
+ {"created_at":"2026-03-16T15:14:55Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-hth","issue_id":"garlic-acn","metadata":"{}","type":"blocks"}
5
+ {"created_at":"2026-03-16T15:14:55Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-9q9","issue_id":"garlic-b5h","metadata":"{}","type":"blocks"}
6
+ {"created_at":"2026-03-16T15:14:56Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-acn","issue_id":"garlic-b5h","metadata":"{}","type":"blocks"}
7
+ {"created_at":"2026-03-16T15:14:56Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-d9o","issue_id":"garlic-b5h","metadata":"{}","type":"blocks"}
8
+ {"created_at":"2026-03-16T15:14:55Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-d9r","issue_id":"garlic-b5h","metadata":"{}","type":"blocks"}
9
+ {"created_at":"2026-03-16T15:14:55Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-hth","issue_id":"garlic-d9o","metadata":"{}","type":"blocks"}
10
+ {"created_at":"2026-03-16T15:14:54Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-8gf","issue_id":"garlic-d9r","metadata":"{}","type":"blocks"}
11
+ {"created_at":"2026-03-16T15:14:53Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-9ja","issue_id":"garlic-d9r","metadata":"{}","type":"blocks"}
12
+ {"created_at":"2026-03-16T15:14:54Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-hth","issue_id":"garlic-d9r","metadata":"{}","type":"blocks"}
13
+ {"created_at":"2026-03-16T15:14:54Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-iv3","issue_id":"garlic-d9r","metadata":"{}","type":"blocks"}
14
+ {"created_at":"2026-03-16T15:14:53Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-8ud","issue_id":"garlic-hth","metadata":"{}","type":"blocks"}
15
+ {"created_at":"2026-03-16T15:14:53Z","created_by":"Daniel Schwartz","depends_on_id":"garlic-8ud","issue_id":"garlic-iv3","metadata":"{}","type":"blocks"}
@@ -0,0 +1,20 @@
1
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:30Z","event_type":"created","id":1,"issue_id":"garlic-8ud","new_value":"","old_value":""}
2
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:30Z","event_type":"created","id":2,"issue_id":"garlic-9ja","new_value":"","old_value":""}
3
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:30Z","event_type":"created","id":3,"issue_id":"garlic-hth","new_value":"","old_value":""}
4
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:31Z","event_type":"created","id":4,"issue_id":"garlic-8gf","new_value":"","old_value":""}
5
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:33Z","event_type":"created","id":5,"issue_id":"garlic-iv3","new_value":"","old_value":""}
6
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:36Z","event_type":"created","id":6,"issue_id":"garlic-d9r","new_value":"","old_value":""}
7
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:39Z","event_type":"created","id":7,"issue_id":"garlic-9q9","new_value":"","old_value":""}
8
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:41Z","event_type":"created","id":8,"issue_id":"garlic-acn","new_value":"","old_value":""}
9
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:43Z","event_type":"created","id":9,"issue_id":"garlic-d9o","new_value":"","old_value":""}
10
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:14:45Z","event_type":"created","id":10,"issue_id":"garlic-b5h","new_value":"","old_value":""}
11
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:20:31Z","event_type":"status_changed","id":11,"issue_id":"garlic-8ud","new_value":"{\"status\":\"in_progress\"}","old_value":"{\"id\":\"garlic-8ud\",\"title\":\"Project scaffolding\",\"description\":\"Create pyproject.toml with uv, src/garlic/__init__.py, CLI entry point using argparse with subcommands (setup, status, ignore, hook). Set up the src/ layout and project.scripts entry.\",\"status\":\"open\",\"priority\":1,\"issue_type\":\"task\",\"owner\":\"4822513+justanotherspy@users.noreply.github.com\",\"created_at\":\"2026-03-16T13:14:30Z\",\"created_by\":\"Daniel Schwartz\",\"updated_at\":\"2026-03-16T13:14:30Z\"}"}
12
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:21:40Z","event_type":"closed","id":12,"issue_id":"garlic-8ud","new_value":"Created pyproject.toml, src/garlic/__init__.py, src/garlic/cli.py with argparse subcommands (setup, status, ignore, hook), tests/test_cli.py. uv sync and pytest passing.","old_value":""}
13
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:24:33Z","event_type":"status_changed","id":13,"issue_id":"garlic-9ja","new_value":"{\"status\":\"in_progress\"}","old_value":"{\"id\":\"garlic-9ja\",\"title\":\"Config module\",\"description\":\"Load and create ~/.garlic/config.toml with defaults using tomllib (read) and manual TOML writing. Default config: max_prompt_gap_minutes=10, reset_hour=2, nudge_thresholds_minutes=[60,120,180,240], nudge_style='gentle'. Ensure config dir is created if missing.\",\"status\":\"open\",\"priority\":1,\"issue_type\":\"task\",\"owner\":\"4822513+justanotherspy@users.noreply.github.com\",\"created_at\":\"2026-03-16T13:14:30Z\",\"created_by\":\"Daniel Schwartz\",\"updated_at\":\"2026-03-16T13:14:30Z\"}"}
14
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:25:15Z","event_type":"closed","id":14,"issue_id":"garlic-9ja","new_value":"Closed","old_value":""}
15
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:26:39Z","event_type":"status_changed","id":15,"issue_id":"garlic-hth","new_value":"{\"status\":\"in_progress\"}","old_value":"{\"id\":\"garlic-hth\",\"title\":\"State module\",\"description\":\"State file (~/.garlic/state.toml) read/write with fcntl.flock file locking. Tracks: date, accumulated_minutes, last_event_time, nudges_given list, ignored bool. Implements day reset logic based on reset_hour from config. Manual TOML serialization for writing.\",\"status\":\"open\",\"priority\":1,\"issue_type\":\"task\",\"owner\":\"4822513+justanotherspy@users.noreply.github.com\",\"created_at\":\"2026-03-16T13:14:31Z\",\"created_by\":\"Daniel Schwartz\",\"updated_at\":\"2026-03-16T13:14:31Z\"}"}
16
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:27:19Z","event_type":"closed","id":16,"issue_id":"garlic-hth","new_value":"Closed","old_value":""}
17
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:27:45Z","event_type":"status_changed","id":17,"issue_id":"garlic-8gf","new_value":"{\"status\":\"in_progress\"}","old_value":"{\"id\":\"garlic-8gf\",\"title\":\"Time calculation engine\",\"description\":\"Core logic: compute gap between last_event_time and now, cap at max_prompt_gap_minutes, accumulate into accumulated_minutes. Handle the Stop event (records time but doesn't cap — just marks last_event_time). Handle prompt event (calculates gap from last event, caps at max_prompt_gap_minutes, accumulates). Check nudge thresholds and return whether a nudge should fire.\",\"status\":\"open\",\"priority\":1,\"issue_type\":\"task\",\"owner\":\"4822513+justanotherspy@users.noreply.github.com\",\"created_at\":\"2026-03-16T13:14:31Z\",\"created_by\":\"Daniel Schwartz\",\"updated_at\":\"2026-03-16T13:14:31Z\"}"}
18
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:28:22Z","event_type":"closed","id":18,"issue_id":"garlic-8gf","new_value":"Closed","old_value":""}
19
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:28:30Z","event_type":"status_changed","id":19,"issue_id":"garlic-iv3","new_value":"{\"status\":\"in_progress\"}","old_value":"{\"id\":\"garlic-iv3\",\"title\":\"Nudge messages\",\"description\":\"Hardcoded pools of nudge messages in three styles: gentle, firm, spicy. Each pool has multiple messages. Random selection from the appropriate pool. Messages should reference the accumulated time (e.g. 'You have been coding for ~2 hours'). The nudge is plain text output to stdout for the agent to relay to the user.\",\"status\":\"open\",\"priority\":1,\"issue_type\":\"task\",\"owner\":\"4822513+justanotherspy@users.noreply.github.com\",\"created_at\":\"2026-03-16T13:14:34Z\",\"created_by\":\"Daniel Schwartz\",\"updated_at\":\"2026-03-16T13:14:34Z\"}"}
20
+ {"actor":"Daniel Schwartz","comment":null,"created_at":"2026-03-16T15:29:04Z","event_type":"closed","id":20,"issue_id":"garlic-iv3","new_value":"Closed","old_value":""}
@@ -0,0 +1,10 @@
1
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"Closed","closed_at":"2026-03-16T13:28:22Z","closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"842124baac67a42e32b2dc977daf1cd9e5467f1dec451dd7f2a8660fa0686217","created_at":"2026-03-16T13:14:31Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"Core logic: compute gap between last_event_time and now, cap at max_prompt_gap_minutes, accumulate into accumulated_minutes. Handle the Stop event (records time but doesn't cap — just marks last_event_time). Handle prompt event (calculates gap from last event, caps at max_prompt_gap_minutes, accumulates). Check nudge thresholds and return whether a nudge should fire.","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-8gf","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":1,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"closed","target":"","timeout_ns":0,"title":"Time calculation engine","updated_at":"2026-03-16T13:28:22Z","waiters":"","wisp_type":"","work_type":""}
2
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"Created pyproject.toml, src/garlic/__init__.py, src/garlic/cli.py with argparse subcommands (setup, status, ignore, hook), tests/test_cli.py. uv sync and pytest passing.","closed_at":"2026-03-16T13:21:40Z","closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"3d08394b232cf55bb9756989463da79a23cbab21b70d0ce2fd268777f36c714f","created_at":"2026-03-16T13:14:30Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"Create pyproject.toml with uv, src/garlic/__init__.py, CLI entry point using argparse with subcommands (setup, status, ignore, hook). Set up the src/ layout and project.scripts entry.","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-8ud","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":1,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"closed","target":"","timeout_ns":0,"title":"Project scaffolding","updated_at":"2026-03-16T13:21:40Z","waiters":"","wisp_type":"","work_type":""}
3
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"Closed","closed_at":"2026-03-16T13:25:15Z","closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"81f03313e13371aa1b103dd30eed4f1ae6a13a8fa97b4734eed6a407982b64c1","created_at":"2026-03-16T13:14:30Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"Load and create ~/.garlic/config.toml with defaults using tomllib (read) and manual TOML writing. Default config: max_prompt_gap_minutes=10, reset_hour=2, nudge_thresholds_minutes=[60,120,180,240], nudge_style='gentle'. Ensure config dir is created if missing.","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-9ja","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":1,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"closed","target":"","timeout_ns":0,"title":"Config module","updated_at":"2026-03-16T13:25:15Z","waiters":"","wisp_type":"","work_type":""}
4
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"","closed_at":null,"closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"8007fe194a167954cc1a0659b96141966e9b746e4e55bbb9041b4d6d57eefc1a","created_at":"2026-03-16T13:14:40Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"garlic setup reads ~/.claude/settings.json (creates if missing), adds hook entries for SessionStart (matcher: startup), UserPromptSubmit, and Stop events pointing to garlic hook subcommands. Must be idempotent — detects existing garlic hooks and updates them rather than duplicating. Writes valid JSON back. Creates ~/.garlic/ dir and default config.toml if not present.","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-9q9","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":2,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"open","target":"","timeout_ns":0,"title":"Setup command","updated_at":"2026-03-16T13:14:40Z","waiters":"","wisp_type":"","work_type":""}
5
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"","closed_at":null,"closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"5974fca09f87ff6db0c344e8dfa73a5bbc8893da40a6b9bc878b239c40c9ba2d","created_at":"2026-03-16T13:14:42Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"garlic status reads the state file and displays accumulated time for today in a human-friendly format (e.g. '1h 23m of active coding today'). Shows nudge thresholds and which have been reached. Shows if ignore is active.","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-acn","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":2,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"open","target":"","timeout_ns":0,"title":"Status command","updated_at":"2026-03-16T13:14:42Z","waiters":"","wisp_type":"","work_type":""}
6
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"","closed_at":null,"closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"73798eeba98b185f0729f262bde609ee6b048c249ab5dc043244d93ef528b9c4","created_at":"2026-03-16T13:14:45Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"Unit tests for all modules: config loading/defaults, state read/write/locking/reset, time calculation/capping/accumulation, nudge selection, hook command stdin parsing, setup idempotency. Use pytest. No network calls. Mock filesystem where needed.","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-b5h","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":3,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"open","target":"","timeout_ns":0,"title":"Tests","updated_at":"2026-03-16T13:14:45Z","waiters":"","wisp_type":"","work_type":""}
7
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"","closed_at":null,"closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"ec70f009b9f76a9702eee6fda7ea471105cc980a0c44bcaad0d2f540c0451e11","created_at":"2026-03-16T13:14:43Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"garlic ignore sets ignored=true in the state file for today. Nudging is suppressed but time tracking continues. Resets automatically when the day resets (based on reset_hour).","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-d9o","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":2,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"open","target":"","timeout_ns":0,"title":"Ignore command","updated_at":"2026-03-16T13:14:43Z","waiters":"","wisp_type":"","work_type":""}
8
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"","closed_at":null,"closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"85a8a8952df2dc85a622144e442ec9fd7a92d17fc2517160ebe0b9c3f9a25dc2","created_at":"2026-03-16T13:14:37Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"Implement garlic hook session-start, garlic hook prompt, and garlic hook stop subcommands. Each reads JSON from stdin (Claude Code hook format with session_id etc). session-start: records start time as last_event_time. stop: records current time as last_event_time (no accumulation, no cap — just updates the marker). prompt: calculates gap from last_event_time, caps at max_prompt_gap_minutes, accumulates, checks nudge thresholds, outputs nudge message to stdout if threshold crossed and not ignored.","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-d9r","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":2,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"open","target":"","timeout_ns":0,"title":"Hook commands (session-start, prompt, stop)","updated_at":"2026-03-16T13:14:37Z","waiters":"","wisp_type":"","work_type":""}
9
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"Closed","closed_at":"2026-03-16T13:27:20Z","closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"30b905ace650be3dc850438af74947d8d84eb982b630f29ee1ed0f28af88b4f8","created_at":"2026-03-16T13:14:31Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"State file (~/.garlic/state.toml) read/write with fcntl.flock file locking. Tracks: date, accumulated_minutes, last_event_time, nudges_given list, ignored bool. Implements day reset logic based on reset_hour from config. Manual TOML serialization for writing.","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-hth","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":1,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"closed","target":"","timeout_ns":0,"title":"State module","updated_at":"2026-03-16T13:27:20Z","waiters":"","wisp_type":"","work_type":""}
10
+ {"acceptance_criteria":"","actor":"","agent_state":"","assignee":null,"await_id":"","await_type":"","close_reason":"Closed","closed_at":"2026-03-16T13:29:05Z","closed_by_session":"","compacted_at":null,"compacted_at_commit":null,"compaction_level":0,"content_hash":"fc8795a47171483c9fad0525c4787dc066724051d7a533f6f09282495c57ee74","created_at":"2026-03-16T13:14:34Z","created_by":"Daniel Schwartz","crystallizes":0,"defer_until":null,"description":"Hardcoded pools of nudge messages in three styles: gentle, firm, spicy. Each pool has multiple messages. Random selection from the appropriate pool. Messages should reference the accumulated time (e.g. 'You have been coding for ~2 hours'). The nudge is plain text output to stdout for the agent to relay to the user.","design":"","due_at":null,"ephemeral":0,"estimated_minutes":null,"event_kind":"","external_ref":null,"hook_bead":"","id":"garlic-iv3","is_template":0,"issue_type":"task","last_activity":null,"metadata":"{}","mol_type":"","notes":"","original_size":null,"owner":"4822513+justanotherspy@users.noreply.github.com","payload":"","pinned":0,"priority":1,"quality_score":null,"rig":"","role_bead":"","role_type":"","sender":"","source_repo":"","source_system":"","spec_id":"","status":"closed","target":"","timeout_ns":0,"title":"Nudge messages","updated_at":"2026-03-16T13:29:05Z","waiters":"","wisp_type":"","work_type":""}
File without changes
@@ -0,0 +1,54 @@
1
+ # Beads Configuration File
2
+ # This file configures default behavior for all bd commands in this repository
3
+ # All settings can also be set via environment variables (BD_* prefix)
4
+ # or overridden with command-line flags
5
+
6
+ # Issue prefix for this repository (used by bd init)
7
+ # If not set, bd init will auto-detect from directory name
8
+ # Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
9
+ # issue-prefix: ""
10
+
11
+ # Use no-db mode: JSONL-only, no Dolt database
12
+ # When true, bd will use .beads/issues.jsonl as the source of truth
13
+ # no-db: false
14
+
15
+ # Enable JSON output by default
16
+ # json: false
17
+
18
+ # Feedback title formatting for mutating commands (create/update/close/dep/edit)
19
+ # 0 = hide titles, N > 0 = truncate to N characters
20
+ # output:
21
+ # title-length: 255
22
+
23
+ # Default actor for audit trails (overridden by BD_ACTOR or --actor)
24
+ # actor: ""
25
+
26
+ # Export events (audit trail) to .beads/events.jsonl on each flush/sync
27
+ # When enabled, new events are appended incrementally using a high-water mark.
28
+ # Use 'bd export --events' to trigger manually regardless of this setting.
29
+ # events-export: false
30
+
31
+ # Multi-repo configuration (experimental - bd-307)
32
+ # Allows hydrating from multiple repositories and routing writes to the correct database
33
+ # repos:
34
+ # primary: "." # Primary repo (where this database lives)
35
+ # additional: # Additional repos to hydrate from (read-only)
36
+ # - ~/beads-planning # Personal planning repo
37
+ # - ~/work-planning # Work planning repo
38
+
39
+ # JSONL backup (periodic export for off-machine recovery)
40
+ # Auto-enabled when a git remote exists. Override explicitly:
41
+ # backup:
42
+ # enabled: false # Disable auto-backup entirely
43
+ # interval: 15m # Minimum time between auto-exports
44
+ # git-push: false # Disable git push (export locally only)
45
+ # git-repo: "" # Separate git repo for backups (default: project repo)
46
+
47
+ # Integration settings (access with 'bd config get/set')
48
+ # These are stored in the database, not in this file:
49
+ # - jira.url
50
+ # - jira.project
51
+ # - linear.url
52
+ # - linear.api-key
53
+ # - github.org
54
+ # - github.repo
@@ -0,0 +1 @@
1
+ ok
@@ -0,0 +1 @@
1
+ ����"�U ՠ����[�6�p#� ��e
@@ -0,0 +1,96 @@
1
+ # Dolt SQL server configuration
2
+ #
3
+ # Uncomment and edit lines as necessary to modify your configuration.
4
+ # Full documentation: https://docs.dolthub.com/sql-reference/server/configuration
5
+ #
6
+
7
+ # log_level: info
8
+
9
+ # log_format: text
10
+
11
+ # max_logged_query_len: 0
12
+
13
+ # encode_logged_query: false
14
+
15
+ # behavior:
16
+ # read_only: false
17
+ # autocommit: true
18
+ # disable_client_multi_statements: false
19
+ # dolt_transaction_commit: false
20
+ # event_scheduler: "OFF"
21
+ # auto_gc_behavior:
22
+ # enable: true
23
+ # archive_level: 1
24
+
25
+ listener:
26
+ host: 127.0.0.1
27
+ port: 40803
28
+ # max_connections: 1000
29
+ # back_log: 50
30
+ # max_connections_timeout_millis: 60000
31
+ # read_timeout_millis: 28800000
32
+ # write_timeout_millis: 28800000
33
+ # tls_key: key.pem
34
+ # tls_cert: cert.pem
35
+ # require_secure_transport: false
36
+ # allow_cleartext_passwords: false
37
+ # socket: /tmp/mysql.sock
38
+
39
+ # data_dir: .
40
+
41
+ # cfg_dir: .doltcfg
42
+
43
+ # remotesapi:
44
+ # port: 8000
45
+ # read_only: false
46
+
47
+ # mcp_server:
48
+ # port: 7007
49
+ # user: root
50
+ # password: ""
51
+ # database: ""
52
+
53
+ # privilege_file: .doltcfg/privileges.db
54
+
55
+ # branch_control_file: .doltcfg/branch_control.db
56
+
57
+ # user_session_vars:
58
+ # - name: root
59
+ # vars:
60
+ # dolt_log_level: warn
61
+ # dolt_show_system_tables: 1
62
+
63
+ # system_variables:
64
+ # dolt_log_level: info
65
+ # dolt_transaction_commit: 1
66
+
67
+ # jwks: []
68
+
69
+ # metrics:
70
+ # labels: {}
71
+ # host: localhost
72
+ # port: 9091
73
+ # tls_cert: ""
74
+ # tls_key: ""
75
+ # tls_ca: ""
76
+
77
+ # cluster:
78
+ # standby_remotes:
79
+ # - name: standby_replica_one
80
+ # remote_url_template: https://standby_replica_one.svc.cluster.local:50051/{database}
81
+ # - name: standby_replica_two
82
+ # remote_url_template: https://standby_replica_two.svc.cluster.local:50051/{database}
83
+ # bootstrap_role: primary
84
+ # bootstrap_epoch: 1
85
+ # remotesapi:
86
+ # address: 127.0.0.1
87
+ # port: 50051
88
+ # tls_key: remotesapi_key.pem
89
+ # tls_cert: remotesapi_chain.pem
90
+ # tls_ca: standby_cas.pem
91
+ # server_name_urls:
92
+ # - https://standby_replica_one.svc.cluster.local
93
+ # - https://standby_replica_two.svc.cluster.local
94
+ # server_name_dns:
95
+ # - standby_replica_one.svc.cluster.local
96
+ # - standby_replica_two.svc.cluster.local
File without changes