@onlooker-community/ecosystem 0.30.1 → 0.31.0

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 (148) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.gitattributes +18 -0
  3. package/.release-please-manifest.json +17 -17
  4. package/CHANGELOG.md +7 -0
  5. package/package.json +2 -3
  6. package/plugins/archivist/.claude-plugin/plugin.json +1 -1
  7. package/plugins/archivist/CHANGELOG.md +7 -0
  8. package/plugins/archivist/README.md +4 -10
  9. package/plugins/archivist/config.json +0 -1
  10. package/plugins/archivist/scripts/hooks/archivist-extract.sh +0 -6
  11. package/plugins/archivist/scripts/hooks/archivist-inject.sh +2 -7
  12. package/plugins/archivist/scripts/lib/archivist-config.sh +0 -8
  13. package/plugins/assayer/.claude-plugin/plugin.json +1 -1
  14. package/plugins/assayer/CHANGELOG.md +7 -0
  15. package/plugins/assayer/README.md +4 -10
  16. package/plugins/assayer/config.json +0 -1
  17. package/plugins/assayer/scripts/hooks/assayer-stop.sh +1 -3
  18. package/plugins/assayer/scripts/lib/assayer-config.sh +0 -6
  19. package/plugins/bursar/.claude-plugin/plugin.json +1 -1
  20. package/plugins/bursar/CHANGELOG.md +7 -0
  21. package/plugins/bursar/README.md +3 -11
  22. package/plugins/bursar/config.json +0 -1
  23. package/plugins/bursar/scripts/hooks/bursar-session-end.sh +4 -6
  24. package/plugins/bursar/scripts/hooks/bursar-session-start.sh +3 -5
  25. package/plugins/bursar/scripts/lib/bursar-config.sh +1 -7
  26. package/plugins/cartographer/.claude-plugin/plugin.json +1 -1
  27. package/plugins/cartographer/CHANGELOG.md +7 -0
  28. package/plugins/cartographer/README.md +3 -10
  29. package/plugins/cartographer/config.json +0 -1
  30. package/plugins/cartographer/scripts/hooks/cartographer-post-write.sh +0 -2
  31. package/plugins/cartographer/scripts/hooks/cartographer-session-start.sh +0 -2
  32. package/plugins/cartographer/scripts/lib/cartographer-config.sh +0 -7
  33. package/plugins/cartographer/skills/cartographer/SKILL.md +0 -5
  34. package/plugins/compass/.claude-plugin/plugin.json +1 -1
  35. package/plugins/compass/CHANGELOG.md +7 -0
  36. package/plugins/compass/README.md +4 -10
  37. package/plugins/compass/config.json +0 -1
  38. package/plugins/compass/scripts/hooks/compass-bash-gate.sh +0 -4
  39. package/plugins/compass/scripts/hooks/compass-pre-tool-use.sh +0 -4
  40. package/plugins/compass/scripts/hooks/compass-record-write.sh +0 -4
  41. package/plugins/compass/scripts/hooks/compass-session-start.sh +1 -6
  42. package/plugins/compass/scripts/lib/compass-config.sh +0 -7
  43. package/plugins/counsel/.claude-plugin/plugin.json +1 -1
  44. package/plugins/counsel/CHANGELOG.md +7 -0
  45. package/plugins/counsel/README.md +6 -10
  46. package/plugins/counsel/config.json +0 -1
  47. package/plugins/counsel/scripts/hooks/counsel-session-start.sh +1 -7
  48. package/plugins/counsel/scripts/lib/counsel-config.sh +0 -6
  49. package/plugins/counsel/skills/counsel/SKILL.md +0 -5
  50. package/plugins/curator/.claude-plugin/plugin.json +1 -1
  51. package/plugins/curator/CHANGELOG.md +7 -0
  52. package/plugins/curator/README.md +1 -11
  53. package/plugins/curator/config.json +0 -1
  54. package/plugins/curator/scripts/hooks/curator-session-start.sh +0 -6
  55. package/plugins/curator/scripts/lib/curator-config.sh +0 -7
  56. package/plugins/echo/.claude-plugin/plugin.json +1 -1
  57. package/plugins/echo/CHANGELOG.md +7 -0
  58. package/plugins/echo/README.md +3 -9
  59. package/plugins/echo/config.json +0 -1
  60. package/plugins/echo/scripts/hooks/echo-stop-gate.sh +1 -3
  61. package/plugins/echo/scripts/lib/echo-config.sh +0 -6
  62. package/plugins/governor/.claude-plugin/plugin.json +1 -1
  63. package/plugins/governor/CHANGELOG.md +7 -0
  64. package/plugins/governor/README.md +4 -10
  65. package/plugins/governor/config.json +0 -1
  66. package/plugins/governor/scripts/hooks/governor-post-tool-use.sh +0 -5
  67. package/plugins/governor/scripts/hooks/governor-pre-tool-use.sh +0 -5
  68. package/plugins/governor/scripts/hooks/governor-session-start.sh +4 -9
  69. package/plugins/governor/scripts/hooks/governor-stop.sh +0 -5
  70. package/plugins/governor/scripts/lib/governor-config.sh +0 -7
  71. package/plugins/historian/.claude-plugin/plugin.json +1 -1
  72. package/plugins/historian/CHANGELOG.md +7 -0
  73. package/plugins/historian/README.md +3 -7
  74. package/plugins/historian/config.json +0 -1
  75. package/plugins/historian/scripts/hooks/historian-prompt-submit.sh +1 -6
  76. package/plugins/historian/scripts/hooks/historian-session-end.sh +0 -2
  77. package/plugins/historian/scripts/lib/historian-config.sh +0 -6
  78. package/plugins/inspector/.claude-plugin/plugin.json +1 -1
  79. package/plugins/inspector/CHANGELOG.md +7 -0
  80. package/plugins/inspector/README.md +9 -5
  81. package/plugins/inspector/config.json +0 -1
  82. package/plugins/inspector/scripts/hooks/inspector-post-write.sh +0 -7
  83. package/plugins/inspector/scripts/lib/inspector-config.sh +0 -7
  84. package/plugins/librarian/.claude-plugin/plugin.json +1 -1
  85. package/plugins/librarian/CHANGELOG.md +7 -0
  86. package/plugins/librarian/README.md +5 -9
  87. package/plugins/librarian/config.json +0 -1
  88. package/plugins/librarian/scripts/hooks/librarian-session-end.sh +0 -2
  89. package/plugins/librarian/scripts/hooks/librarian-session-start.sh +0 -6
  90. package/plugins/librarian/scripts/lib/librarian-config.sh +0 -8
  91. package/plugins/lineage/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lineage/CHANGELOG.md +7 -1
  93. package/plugins/lineage/README.md +3 -12
  94. package/plugins/lineage/config.json +0 -1
  95. package/plugins/lineage/scripts/hooks/lineage-post-tool-use.sh +0 -1
  96. package/plugins/lineage/scripts/lib/lineage-config.sh +0 -7
  97. package/plugins/lineage/skills/lineage/SKILL.md +1 -4
  98. package/plugins/scribe/.claude-plugin/plugin.json +1 -1
  99. package/plugins/scribe/CHANGELOG.md +7 -0
  100. package/plugins/scribe/README.md +4 -12
  101. package/plugins/scribe/config.json +0 -1
  102. package/plugins/scribe/scripts/hooks/scribe-capture.sh +0 -4
  103. package/plugins/scribe/scripts/hooks/scribe-session-start.sh +2 -7
  104. package/plugins/scribe/scripts/hooks/scribe-stop.sh +0 -5
  105. package/plugins/scribe/scripts/lib/scribe-config.sh +1 -8
  106. package/plugins/scribe/scripts/lib/scribe-extract.sh +16 -12
  107. package/plugins/tribunal/.claude-plugin/plugin.json +1 -1
  108. package/plugins/tribunal/CHANGELOG.md +7 -0
  109. package/plugins/tribunal/README.md +7 -1
  110. package/plugins/tribunal/config.json +0 -1
  111. package/plugins/tribunal/scripts/hooks/tribunal-stop-gate.sh +3 -14
  112. package/plugins/tribunal/scripts/lib/tribunal-config.sh +0 -8
  113. package/plugins/warden/.claude-plugin/plugin.json +1 -1
  114. package/plugins/warden/CHANGELOG.md +7 -0
  115. package/plugins/warden/README.md +3 -12
  116. package/plugins/warden/config.json +0 -1
  117. package/plugins/warden/scripts/hooks/warden-post-tool-use.sh +0 -4
  118. package/plugins/warden/scripts/hooks/warden-pre-tool-use.sh +0 -4
  119. package/plugins/warden/scripts/hooks/warden-session-start.sh +1 -6
  120. package/plugins/warden/scripts/lib/warden-config.sh +1 -8
  121. package/renovate.json +34 -0
  122. package/test/bats/archivist-config-files.bats +2 -2
  123. package/test/bats/archivist-config.bats +0 -25
  124. package/test/bats/archivist-inject.bats +1 -13
  125. package/test/bats/assayer-config.bats +0 -13
  126. package/test/bats/assayer-stop-hook.bats +3 -17
  127. package/test/bats/bursar-config.bats +0 -25
  128. package/test/bats/bursar-session-end.bats +0 -20
  129. package/test/bats/bursar-session-start.bats +1 -18
  130. package/test/bats/cartographer-config.bats +0 -25
  131. package/test/bats/compass-config.bats +1 -26
  132. package/test/bats/compass-gate.bats +1 -3
  133. package/test/bats/curator-session-start.bats +2 -12
  134. package/test/bats/echo-config.bats +0 -24
  135. package/test/bats/echo-stop-hook.bats +3 -15
  136. package/test/bats/governor-config.bats +0 -36
  137. package/test/bats/historian-prompt-submit.bats +1 -8
  138. package/test/bats/historian-session-end.bats +4 -14
  139. package/test/bats/inspector-config.bats +0 -13
  140. package/test/bats/inspector-post-write-hook.bats +10 -17
  141. package/test/bats/librarian-session-end.bats +0 -11
  142. package/test/bats/librarian-session-start.bats +1 -11
  143. package/test/bats/lineage-config.bats +0 -25
  144. package/test/bats/lineage-post-tool-use.bats +1 -7
  145. package/test/bats/scribe-extract.bats +6 -6
  146. package/test/bats/tribunal-config.bats +0 -25
  147. package/test/bats/warden-config.bats +0 -25
  148. package/test/bats/warden-scanner.bats +1 -1
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0](https://github.com/onlooker-community/ecosystem/compare/historian-v0.2.1...historian-v0.3.0) (2026-07-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * **plugins:** installation enables plugins — remove per-plugin 'enabled' config key ([#108](https://github.com/onlooker-community/ecosystem/issues/108)) ([45e4e6b](https://github.com/onlooker-community/ecosystem/commit/45e4e6bd29a0a7545dbd5007bf3f09600e1be391))
9
+
3
10
  ## [0.2.1](https://github.com/onlooker-community/ecosystem/compare/historian-v0.2.0...historian-v0.2.1) (2026-06-28)
4
11
 
5
12
 
@@ -17,14 +17,10 @@ See [`docs/design.md`](docs/design.md) and [ADR-001](docs/adr/001-local-embeddin
17
17
 
18
18
  ## Activation
19
19
 
20
- Historian is **off by default**. Enable per-project in `.claude/settings.json`:
20
+ Install via the marketplace:
21
21
 
22
- ```json
23
- {
24
- "historian": {
25
- "enabled": true
26
- }
27
- }
22
+ ```
23
+ /plugin install historian@onlooker-community
28
24
  ```
29
25
 
30
26
  See [`config.json`](config.json) for the full set of tunable defaults.
@@ -2,7 +2,6 @@
2
2
  "plugin_name": "historian",
3
3
  "storage_path": "~/.onlooker",
4
4
  "historian": {
5
- "enabled": false,
6
5
  "indexing": {
7
6
  "trigger": "SessionEnd",
8
7
  "min_transcript_chars_to_index": 1200,
@@ -17,7 +17,7 @@
17
17
  # Hook contract:
18
18
  # - Always exits 0. Never blocks the prompt.
19
19
  # - Emits valid hookSpecificOutput JSON even when nothing to inject.
20
- # - No-ops when historian.enabled is not true OR retrieval is disabled.
20
+ # - No-ops when retrieval is disabled.
21
21
  # - Lifecycle events: historian.retrieval.started fires when the rate
22
22
  # gate clears and we are about to embed. All outcomes flow through
23
23
  # historian.retrieval.complete with `outcome: surfaced | empty |
@@ -81,11 +81,6 @@ PROMPT=$(printf '%s' "$INPUT" | jq -r '.prompt // .user_message // .message // "
81
81
  REPO_ROOT=$(historian_project_repo_root "$CWD")
82
82
  historian_config_load "$REPO_ROOT"
83
83
 
84
- if ! historian_config_enabled; then
85
- _emit_context ""
86
- exit 0
87
- fi
88
-
89
84
  RETRIEVAL_ENABLED=$(historian_config_get '.historian.retrieval.enabled')
90
85
  if [[ "$RETRIEVAL_ENABLED" == "false" ]]; then
91
86
  _emit_context ""
@@ -8,7 +8,6 @@
8
8
  #
9
9
  # Hook contract:
10
10
  # - Always exits 0. Never blocks session shutdown.
11
- # - No-ops when historian.enabled is not true.
12
11
  # - No-ops when there is no project key, no transcript path, or the
13
12
  # transcript is shorter than min_transcript_chars_to_index.
14
13
  # - Indexing failures are fail-soft: an emitted historian.indexing.complete
@@ -59,7 +58,6 @@ TRANSCRIPT_PATH=$(printf '%s' "$INPUT" | jq -r '.transcript_path // ""' 2>/dev/n
59
58
 
60
59
  REPO_ROOT=$(historian_project_repo_root "$CWD")
61
60
  historian_config_load "$REPO_ROOT"
62
- historian_config_enabled || exit 0
63
61
 
64
62
  PROJECT_KEY=$(historian_project_key "$CWD")
65
63
  [[ -z "$PROJECT_KEY" ]] && exit 0
@@ -9,7 +9,6 @@
9
9
  # Exposes:
10
10
  # historian_config_load <repo_root> # populates _HISTORIAN_CONFIG (JSON)
11
11
  # historian_config_get <jq-path> # echoes string value (empty if unset)
12
- # historian_config_enabled # 0 if historian.enabled is true
13
12
  #
14
13
  # Settings overlay only touches the `historian.*` subtree of settings.json.
15
14
 
@@ -59,8 +58,3 @@ historian_config_get() {
59
58
  | jq -r "${path} | if . == null then empty else . end" 2>/dev/null
60
59
  }
61
60
 
62
- historian_config_enabled() {
63
- local v
64
- v=$(historian_config_get '.historian.enabled')
65
- [[ "$v" == "true" ]]
66
- }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inspector",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Per-edit lint and typecheck gate. Runs the project's configured checks on just the touched file after every Write / Edit / MultiEdit, so the agent sees its own type errors before claiming success. Cheaper than proctor (which runs project-wide verification at Stop); complements assayer (which catches the agent lying about claims). Builds on the Onlooker ecosystem plugin.",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0](https://github.com/onlooker-community/ecosystem/compare/inspector-v0.2.0...inspector-v0.3.0) (2026-07-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * **plugins:** installation enables plugins — remove per-plugin 'enabled' config key ([#108](https://github.com/onlooker-community/ecosystem/issues/108)) ([45e4e6b](https://github.com/onlooker-community/ecosystem/commit/45e4e6bd29a0a7545dbd5007bf3f09600e1be391))
9
+
3
10
  ## [0.2.0](https://github.com/onlooker-community/ecosystem/compare/inspector-v0.1.0...inspector-v0.2.0) (2026-06-15)
4
11
 
5
12
 
@@ -51,13 +51,18 @@ checks too. The agent sees this on its next turn.
51
51
 
52
52
  ## Activation
53
53
 
54
- Inspector ships disabled. Opt in per project (or globally) by adding the
55
- `inspector` block to `.claude/settings.json`:
54
+ Install the plugin from the marketplace:
55
+
56
+ ```
57
+ /plugin install inspector@onlooker-community
58
+ ```
59
+
60
+ Once installed, inspector is active. Configure it per project (or globally) by
61
+ adding the `inspector` block to `.claude/settings.json`:
56
62
 
57
63
  ```jsonc
58
64
  {
59
65
  "inspector": {
60
- "enabled": true,
61
66
  "checks": {
62
67
  ".ts": [{ "name": "biome", "kind": "lint", "argv": ["biome", "check", "${file}"] },
63
68
  { "name": "tsc", "kind": "typecheck", "argv": ["tsc", "--noEmit"] }],
@@ -87,7 +92,6 @@ A bare argv array (`["shellcheck", "${file}"]`) is also accepted as a shorthand
87
92
 
88
93
  | Field | Default | Meaning |
89
94
  |---|---|---|
90
- | `enabled` | `false` | Master switch. |
91
95
  | `timeout_seconds_per_check` | `10` | Wall-clock cap per check. Exceeded → `inspector.check.skipped` with `reason: "timeout"`. |
92
96
  | `total_timeout_seconds` | `30` | Wall-clock cap for the whole run. Remaining checks emit `.skipped` with `reason: "total_budget_exhausted"`. |
93
97
  | `output_excerpt_max_bytes` | `4096` | Cap on captured output, both in the event and shown to the agent. Excess is replaced with `…[truncated]`. |
@@ -108,7 +112,7 @@ All events are registered in `@onlooker-community/schema`.
108
112
  |---|---|---|
109
113
  | `inspector.check.passed` | A check returned exit 0 | `file_path`, `tool_name`, `check_name`, `check_kind`, `argv`, `duration_ms` |
110
114
  | `inspector.check.failed` | A check returned non-zero | `exit_code`, `issue_count` (best-effort, may be `null`), `output_excerpt`, `output_truncated` |
111
- | `inspector.check.skipped` | A check or whole file was not run | `reason`: one of `disabled`, `excluded_path`, `no_extension_match`, `not_in_repo`, `tool_missing`, `timeout`, `total_budget_exhausted` |
115
+ | `inspector.check.skipped` | A check or whole file was not run | `reason`: one of `excluded_path`, `no_extension_match`, `not_in_repo`, `tool_missing`, `timeout`, `total_budget_exhausted` |
112
116
  | `inspector.run.completed` | Once per hook fire after all checks | `checks_run`, `checks_passed`, `checks_failed`, `checks_skipped`, `duration_ms` |
113
117
 
114
118
  Downstream consumers that just want "did this edit produce broken code?" read
@@ -2,7 +2,6 @@
2
2
  "plugin_name": "inspector",
3
3
  "storage_path": "~/.onlooker",
4
4
  "inspector": {
5
- "enabled": false,
6
5
  "timeout_seconds_per_check": 10,
7
6
  "total_timeout_seconds": 30,
8
7
  "output_excerpt_max_bytes": 4096,
@@ -61,7 +61,6 @@ export INSPECTOR_PROJECT_KEY="$PROJECT_KEY"
61
61
  if [[ "$CANONICAL" != "$REPO_ROOT"/* && "$CANONICAL" != "$REPO_ROOT" ]]; then
62
62
  export INSPECTOR_FILE_RELATIVE="$CANONICAL"
63
63
  inspector_config_load "$REPO_ROOT"
64
- inspector_config_enabled || exit 0
65
64
  inspector_emit_whole_file_skipped "not_in_repo"
66
65
  exit 0
67
66
  fi
@@ -69,12 +68,6 @@ export INSPECTOR_FILE_RELATIVE="${CANONICAL#"$REPO_ROOT"/}"
69
68
 
70
69
  inspector_config_load "$REPO_ROOT"
71
70
 
72
- if ! inspector_config_enabled; then
73
- # Silent skip — do not even emit an event when disabled. Disabled means
74
- # "this plugin is dormant," not "this file was uninteresting."
75
- exit 0
76
- fi
77
-
78
71
  # Excluded path containment check.
79
72
  EXCLUDES=$(inspector_config_exclude_paths)
80
73
  if [[ -n "$EXCLUDES" && "$EXCLUDES" != "null" && "$EXCLUDES" != "[]" ]]; then
@@ -8,7 +8,6 @@
8
8
  #
9
9
  # Usage:
10
10
  # inspector_config_load <repo_root>
11
- # inspector_config_enabled
12
11
  # inspector_config_get ".inspector.timeout_seconds_per_check"
13
12
  # inspector_config_get_json ".inspector.exclude_paths"
14
13
  # inspector_config_checks_for_extension ".ts"
@@ -54,12 +53,6 @@ inspector_config_get_json() {
54
53
  printf '%s' "$_INSPECTOR_CONFIG" | jq -c "$path // empty" 2>/dev/null
55
54
  }
56
55
 
57
- inspector_config_enabled() {
58
- local v
59
- v=$(inspector_config_get '.inspector.enabled')
60
- [[ "$v" == "true" ]]
61
- }
62
-
63
56
  inspector_config_show_clean_runs() {
64
57
  local v
65
58
  v=$(inspector_config_get '.inspector.show_clean_runs')
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "librarian",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Consolidation layer between archivist's per-session artifacts and the user's durable typed memory store. Detects which session decisions, dead-ends, and open questions deserve to live across sessions, classifies them into the user/feedback/project/reference types, and queues them as proposals for explicit confirmation. Auto-promotion is opt-in. Builds on the Onlooker ecosystem plugin.",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.0](https://github.com/onlooker-community/ecosystem/compare/librarian-v0.3.0...librarian-v0.4.0) (2026-07-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * **plugins:** installation enables plugins — remove per-plugin 'enabled' config key ([#108](https://github.com/onlooker-community/ecosystem/issues/108)) ([45e4e6b](https://github.com/onlooker-community/ecosystem/commit/45e4e6bd29a0a7545dbd5007bf3f09600e1be391))
9
+
3
10
  ## [0.3.0](https://github.com/onlooker-community/ecosystem/compare/librarian-v0.2.0...librarian-v0.3.0) (2026-06-24)
4
11
 
5
12
 
@@ -15,17 +15,13 @@ Librarian is a sibling plugin to [`ecosystem`](../../) and assumes the Onlooker
15
15
 
16
16
  ## Activation
17
17
 
18
- Librarian is **off by default**. Enable per-project in `.claude/settings.json`:
19
-
20
- ```json
21
- {
22
- "librarian": {
23
- "enabled": true
24
- }
25
- }
18
+ Install Librarian from the marketplace:
19
+
20
+ ```
21
+ /plugin install librarian@onlooker-community
26
22
  ```
27
23
 
28
- Or globally in `~/.claude/settings.json`. See [`config.json`](config.json) for the full set of tunable defaults.
24
+ Installing the plugin enables it. See [`config.json`](config.json) for the full set of tunable defaults.
29
25
 
30
26
  ## Storage layout
31
27
 
@@ -2,7 +2,6 @@
2
2
  "plugin_name": "librarian",
3
3
  "storage_path": "~/.onlooker",
4
4
  "librarian": {
5
- "enabled": false,
6
5
  "auto_promote": false,
7
6
  "auto_promote_threshold": 0.85,
8
7
  "memory_store_path": "${HOME}/.claude/projects/${CLAUDE_PROJECT_ENCODED}/memory",
@@ -7,7 +7,6 @@
7
7
  #
8
8
  # Hook contract:
9
9
  # - Always exits 0. Never blocks session shutdown.
10
- # - No-ops when librarian.enabled is not true.
11
10
  # - No-ops when no project key (no git context) or no archivist artifacts.
12
11
  # - Classifier failures degrade gracefully: the affected candidate is
13
12
  # dropped, the rest of the scan proceeds.
@@ -56,7 +55,6 @@ SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // ""' 2>/dev/null) || SE
56
55
  [[ -z "$SESSION_ID" ]] && SESSION_ID="unknown"
57
56
 
58
57
  librarian_config_load "$(librarian_project_repo_root "$CWD")"
59
- librarian_config_enabled || exit 0
60
58
 
61
59
  PROJECT_KEY=$(librarian_project_key "$CWD")
62
60
  [[ -z "$PROJECT_KEY" ]] && exit 0
@@ -11,7 +11,6 @@
11
11
  # Hook contract:
12
12
  # - Always exits 0. Never blocks session start.
13
13
  # - Emits valid hookSpecificOutput JSON, even when nothing to say.
14
- # - No-ops when librarian.enabled is not true.
15
14
  # - No-ops when there is no project key (no git context).
16
15
 
17
16
  set -uo pipefail
@@ -59,11 +58,6 @@ CWD=$(printf '%s' "$INPUT" | jq -r '.cwd // ""' 2>/dev/null) || CWD=""
59
58
  REPO_ROOT=$(librarian_project_repo_root "$CWD")
60
59
  librarian_config_load "$REPO_ROOT"
61
60
 
62
- if ! librarian_config_enabled; then
63
- _emit ""
64
- exit 0
65
- fi
66
-
67
61
  PROJECT_KEY=$(librarian_project_key "$CWD")
68
62
  if [[ -z "$PROJECT_KEY" ]]; then
69
63
  _emit ""
@@ -9,7 +9,6 @@
9
9
  # Exposes:
10
10
  # librarian_config_load <repo_root> # populates _LIBRARIAN_CONFIG (JSON)
11
11
  # librarian_config_get <jq-path> # echoes string value (empty if unset)
12
- # librarian_config_enabled # 0 if librarian.enabled is true
13
12
  # librarian_config_auto_promote # 0 if librarian.auto_promote is true
14
13
  #
15
14
  # Settings overlay only touches the `librarian.*` subtree of settings.json so
@@ -59,13 +58,6 @@ librarian_config_get() {
59
58
  printf '%s' "$_LIBRARIAN_CONFIG" | jq -r "${path} // empty" 2>/dev/null
60
59
  }
61
60
 
62
- # Returns 0 if librarian.enabled is true, 1 otherwise.
63
- librarian_config_enabled() {
64
- local v
65
- v=$(librarian_config_get '.librarian.enabled')
66
- [[ "$v" == "true" ]]
67
- }
68
-
69
61
  # Returns 0 if librarian.auto_promote is true, 1 otherwise.
70
62
  librarian_config_auto_promote() {
71
63
  local v
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lineage",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Per-change provenance for the Onlooker ecosystem. Records session/turn metadata plus a secret-redacted, size-capped snippet for every Edit/Write/MultiEdit at PostToolUse, then answers \"why does this line exist?\" via /lineage by joining change records to historian-preserved transcripts. Emits lineage.* events for audit. Builds on the Onlooker ecosystem plugin.",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -1,9 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.0](https://github.com/onlooker-community/ecosystem/compare/lineage-v0.1.0...lineage-v0.2.0) (2026-07-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * **plugins:** installation enables plugins — remove per-plugin 'enabled' config key ([#108](https://github.com/onlooker-community/ecosystem/issues/108)) ([45e4e6b](https://github.com/onlooker-community/ecosystem/commit/45e4e6bd29a0a7545dbd5007bf3f09600e1be391))
9
+
3
10
  ## [0.1.0](https://github.com/onlooker-community/ecosystem/compare/lineage-v0.0.1...lineage-v0.1.0) (2026-06-12)
4
11
 
5
12
 
6
13
  ### Features
7
14
 
8
15
  * **lineage:** introduce per-change provenance plugin ([#83](https://github.com/onlooker-community/ecosystem/issues/83)) ([86b00d3](https://github.com/onlooker-community/ecosystem/commit/86b00d3d7393e2b63c5b04d60692fc89f202bf6c))
9
-
@@ -49,18 +49,11 @@ the substrate's turn counter.
49
49
 
50
50
  ## Activation
51
51
 
52
- Lineage is **off by default**. Enable it per-project in `.claude/settings.json`:
52
+ Install the plugin in Claude from the marketplace with:
53
53
 
54
- ```json
55
- {
56
- "lineage": {
57
- "enabled": true
58
- }
59
- }
60
54
  ```
61
-
62
- Or globally in `~/.claude/settings.json`. While disabled, the hook skips silently
63
- and no ledger is written.
55
+ /plugin install lineage@onlooker-community
56
+ ```
64
57
 
65
58
  ## Configuration
66
59
 
@@ -69,7 +62,6 @@ All keys are optional. Unset keys fall back to the plugin's `config.json` defaul
69
62
  ```json
70
63
  {
71
64
  "lineage": {
72
- "enabled": false,
73
65
  "max_snippet_chars": 4000,
74
66
  "redact_secrets": true,
75
67
  "ignore_globs": ["**/.git/**", "**/node_modules/**", "**/dist/**", "**/*.lock"],
@@ -80,7 +72,6 @@ All keys are optional. Unset keys fall back to the plugin's `config.json` defaul
80
72
 
81
73
  | Key | Default | Description |
82
74
  |-----|---------|-------------|
83
- | `enabled` | `false` | Must be `true` for recording, querying, or event emission to run. |
84
75
  | `max_snippet_chars` | `4000` | Cap on the added-content snippet stored per change. |
85
76
  | `redact_secrets` | `true` | Scrub secret-shaped substrings (AWS/GitHub/Anthropic/OpenAI keys, bearer tokens, KEY=value secrets) before storing a snippet. |
86
77
  | `ignore_globs` | `[".git", "node_modules", "dist", "*.lock"]` | Paths matching these are not recorded. Supports `**/<dir>/**` (path segment) and `**/*.<ext>` (suffix) shapes. |
@@ -2,7 +2,6 @@
2
2
  "plugin_name": "lineage",
3
3
  "storage_path": "~/.onlooker",
4
4
  "lineage": {
5
- "enabled": false,
6
5
  "max_snippet_chars": 4000,
7
6
  "redact_secrets": true,
8
7
  "ignore_globs": ["**/.git/**", "**/node_modules/**", "**/dist/**", "**/*.lock"],
@@ -48,7 +48,6 @@ esac
48
48
  [[ -z "$CWD" ]] && CWD="$(pwd)"
49
49
  REPO_ROOT=$(lineage_project_repo_root "$CWD")
50
50
  lineage_config_load "$REPO_ROOT"
51
- lineage_config_enabled || _done
52
51
 
53
52
  PROJECT_KEY=$(lineage_project_key "$CWD")
54
53
  [[ -z "$PROJECT_KEY" ]] && _done
@@ -10,7 +10,6 @@
10
10
  # lineage_config_load <repo_root> # populates _LINEAGE_CONFIG (JSON)
11
11
  # lineage_config_get <jq-path> # echoes string value (empty if unset)
12
12
  # lineage_config_get_json <jq-path> # echoes JSON value (null if unset)
13
- # lineage_config_enabled # 0 if lineage.enabled is true
14
13
  # lineage_config_max_snippet_chars # echoes the snippet cap (default 4000)
15
14
  # lineage_config_redact_enabled # 0 unless redact_secrets is false
16
15
  # lineage_config_prompt_source # echoes the prompt-source strategy
@@ -69,12 +68,6 @@ lineage_config_get_json() {
69
68
  printf '%s' "$_LINEAGE_CONFIG" | jq -c "${path}" 2>/dev/null
70
69
  }
71
70
 
72
- lineage_config_enabled() {
73
- local v
74
- v=$(lineage_config_get '.lineage.enabled')
75
- [[ "$v" == "true" ]]
76
- }
77
-
78
71
  lineage_config_max_snippet_chars() {
79
72
  local v
80
73
  v=$(lineage_config_get '.lineage.max_snippet_chars')
@@ -29,10 +29,7 @@ source "$PLUGIN_ROOT/scripts/lib/lineage-query.sh"
29
29
 
30
30
  REPO_ROOT=$(lineage_project_repo_root "$(pwd)")
31
31
  lineage_config_load "$REPO_ROOT"
32
- if ! lineage_config_enabled; then
33
- echo "Lineage is disabled. Set lineage.enabled=true in .claude/settings.json to enable."
34
- exit 0
35
- fi
32
+
36
33
  PROJECT_KEY=$(lineage_project_key "$(pwd)")
37
34
  if [[ -z "$PROJECT_KEY" ]]; then
38
35
  echo "No project key — lineage needs a git repository (remote or root) to scope its ledger."
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scribe",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Intent documentation from agent activity. Captures why changes were made — problem context, decisions, tradeoffs — and distills them into readable artifacts at session end.",
5
5
  "author": {
6
6
  "name": "Onlooker Community",
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.0](https://github.com/onlooker-community/ecosystem/compare/scribe-v0.3.0...scribe-v0.4.0) (2026-07-03)
4
+
5
+
6
+ ### Features
7
+
8
+ * **plugins:** installation enables plugins — remove per-plugin 'enabled' config key ([#108](https://github.com/onlooker-community/ecosystem/issues/108)) ([45e4e6b](https://github.com/onlooker-community/ecosystem/commit/45e4e6bd29a0a7545dbd5007bf3f09600e1be391))
9
+
3
10
  ## [0.3.0](https://github.com/onlooker-community/ecosystem/compare/scribe-v0.2.1...scribe-v0.3.0) (2026-06-24)
4
11
 
5
12
 
@@ -14,21 +14,15 @@ Scribe is a sibling plugin to [`ecosystem`](../../) and assumes the Onlooker obs
14
14
  | `UserPromptSubmit` | On the first turn of a session (when `captured_prompt` is still null), stores the prompt text — truncated to `capture.prompt_max_chars` — as the problem-statement seed. Subsequent turns are ignored, since the full transcript is available at Stop time. |
15
15
  | `Stop` | Reads the full session transcript, runs a single Haiku extraction pass via `claude -p` to identify the problem, decisions, tradeoffs, constraints, and out-of-scope items, formats the result as a Markdown intent document, and writes it under `~/.onlooker/scribe/<project-key>/`. Emits `scribe.distill.complete`. |
16
16
 
17
- The Stop hook silently skips when the session has fewer than `capture.min_turns` user turns, when `scribe.enabled` is false, or when no readable `transcript_path` is present in the hook input. Every hook always exits 0 — Scribe never blocks a session.
17
+ The Stop hook silently skips when the session has fewer than `capture.min_turns` user turns or when no readable `transcript_path` is present in the hook input. Every hook always exits 0 — Scribe never blocks a session.
18
18
 
19
19
  ## Activation
20
20
 
21
- Scribe is **on by default**. Disable it per-project in `.claude/settings.json`:
21
+ Install the plugin in Claude from the marketplace with:
22
22
 
23
- ```json
24
- {
25
- "scribe": {
26
- "enabled": false
27
- }
28
- }
29
23
  ```
30
-
31
- Or globally in `~/.claude/settings.json`.
24
+ /plugin install scribe@onlooker-community
25
+ ```
32
26
 
33
27
  ## Configuration
34
28
 
@@ -37,7 +31,6 @@ All keys are optional. Unset keys fall back to the plugin's `config.json` defaul
37
31
  ```json
38
32
  {
39
33
  "scribe": {
40
- "enabled": true,
41
34
  "evaluator": {
42
35
  "model": "claude-haiku-4-5-20251001",
43
36
  "timeout": 60,
@@ -59,7 +52,6 @@ All keys are optional. Unset keys fall back to the plugin's `config.json` defaul
59
52
 
60
53
  | Key | Default | Description |
61
54
  |-----|---------|-------------|
62
- | `enabled` | `true` | Must be `true` for any capture or distillation to run. |
63
55
  | `evaluator.model` | `claude-haiku-4-5-20251001` | Model used for the intent-extraction pass. Haiku is fast and cheap; the extraction prompt is structured and does not require deep reasoning. |
64
56
  | `evaluator.timeout` | `60` | Wall-clock timeout in seconds passed to the `timeout` command around the `claude -p` call. |
65
57
  | `evaluator.max_tokens` | `2048` | Token ceiling for the extraction response. |
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "scribe": {
3
- "enabled": true,
4
3
  "evaluator": {
5
4
  "model": "claude-haiku-4-5-20251001",
6
5
  "timeout": 60,
@@ -33,10 +33,6 @@ _done() { exit 0; }
33
33
 
34
34
  scribe_config_load "$CWD"
35
35
 
36
- if ! scribe_config_enabled; then
37
- _done
38
- fi
39
-
40
36
  ONLOOKER_DIR="${ONLOOKER_DIR:-${HOME}/.onlooker}"
41
37
  STATE_FILE="${ONLOOKER_DIR}/scribe/sessions/${SESSION_ID}.json"
42
38
 
@@ -2,9 +2,8 @@
2
2
  # Scribe SessionStart hook.
3
3
  #
4
4
  # Fires at every session start. Responsibilities:
5
- # 1. Skip silently when scribe.enabled is false.
6
- # 2. Create storage directories.
7
- # 3. Initialize session state file:
5
+ # 1. Create storage directories.
6
+ # 2. Initialize session state file:
8
7
  # - captured_prompt: null (populated by scribe-capture.sh on first turn)
9
8
  # - captured_at: null
10
9
  #
@@ -30,10 +29,6 @@ _done() { exit 0; }
30
29
 
31
30
  scribe_config_load "$CWD"
32
31
 
33
- if ! scribe_config_enabled; then
34
- _done
35
- fi
36
-
37
32
  export _HOOK_SESSION_ID="$SESSION_ID"
38
33
 
39
34
  ONLOOKER_DIR="${ONLOOKER_DIR:-${HOME}/.onlooker}"
@@ -7,7 +7,6 @@
7
7
  # ~/.onlooker/scribe/<project_key>/<date>-<session>.md.
8
8
  #
9
9
  # Skip conditions (all silent):
10
- # - scribe.enabled is false
11
10
  # - no transcript_path in hook input, or file is unreadable
12
11
  # - session has fewer turns than scribe.capture.min_turns
13
12
  #
@@ -46,10 +45,6 @@ _done() { exit 0; }
46
45
 
47
46
  scribe_config_load "$CWD"
48
47
 
49
- if ! scribe_config_enabled; then
50
- _done
51
- fi
52
-
53
48
  if [[ -z "$TRANSCRIPT_PATH" || ! -f "$TRANSCRIPT_PATH" ]]; then
54
49
  _done
55
50
  fi
@@ -10,7 +10,6 @@
10
10
  # scribe_config_load <repo_root> # populates _SCRIBE_CONFIG (JSON)
11
11
  # scribe_config_get <jq-path> # echoes string value (empty if unset)
12
12
  # scribe_config_get_json <jq-path> # echoes JSON value (null if unset)
13
- # scribe_config_enabled # 0 if scribe.enabled is true
14
13
 
15
14
  _SCRIBE_CONFIG="{}"
16
15
 
@@ -63,10 +62,4 @@ scribe_config_get() {
63
62
  scribe_config_get_json() {
64
63
  local path="$1"
65
64
  printf '%s' "$_SCRIBE_CONFIG" | jq -c "${path}" 2>/dev/null
66
- }
67
-
68
- scribe_config_enabled() {
69
- local v
70
- v=$(scribe_config_get '.scribe.enabled')
71
- [[ "$v" == "true" ]]
72
- }
65
+ }
@@ -59,9 +59,13 @@ scribe_count_turns() {
59
59
  local line
60
60
  while IFS= read -r line; do
61
61
  [[ -z "$line" ]] && continue
62
- local role
63
- role=$(printf '%s' "$line" | jq -r '.role // empty' 2>/dev/null) || continue
64
- [[ "$role" == "user" ]] && count=$((count + 1))
62
+ local entry_type
63
+ entry_type=$(printf '%s' "$line" | jq -r '.type // empty' 2>/dev/null) || continue
64
+ [[ "$entry_type" == "user" ]] || continue
65
+ # Only count real user prompts (string content), not tool results (array content)
66
+ local content_type
67
+ content_type=$(printf '%s' "$line" | jq -r '.message.content | type' 2>/dev/null) || continue
68
+ [[ "$content_type" == "string" ]] && count=$((count + 1))
65
69
  done < "$transcript_path"
66
70
 
67
71
  printf '%s' "$count"
@@ -79,21 +83,21 @@ scribe_extract_intent() {
79
83
 
80
84
  local transcript_content
81
85
  transcript_content=$(jq -r '
82
- select(.role != null) |
83
- if .role == "user" then
86
+ select(.type == "user" or .type == "assistant") |
87
+ if .type == "user" then
84
88
  "[User]\n" + (
85
- if (.content | type) == "array" then
86
- [.content[] | select(.type == "text") | .text] | join("\n")
89
+ if (.message.content | type) == "array" then
90
+ [.message.content[] | select(.type == "text") | .text] | join("\n")
87
91
  else
88
- (.content // "")
92
+ (.message.content // "")
89
93
  end
90
94
  )
91
- elif .role == "assistant" then
95
+ elif .type == "assistant" then
92
96
  "[Assistant]\n" + (
93
- if (.content | type) == "array" then
94
- [.content[] | select(.type == "text") | .text] | join("\n")
97
+ if (.message.content | type) == "array" then
98
+ [.message.content[] | select(.type == "text") | .text] | join("\n")
95
99
  else
96
- (.content // "")
100
+ (.message.content // "")
97
101
  end
98
102
  )
99
103
  else empty end