agent-knowledge-cli 0.1.2__py3-none-any.whl

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 (88) hide show
  1. agent_knowledge/__init__.py +3 -0
  2. agent_knowledge/__main__.py +3 -0
  3. agent_knowledge/assets/__init__.py +0 -0
  4. agent_knowledge/assets/claude/global.md +44 -0
  5. agent_knowledge/assets/claude/project-template.md +46 -0
  6. agent_knowledge/assets/claude/scripts/install.sh +85 -0
  7. agent_knowledge/assets/commands/doctor.md +21 -0
  8. agent_knowledge/assets/commands/global-knowledge-sync.md +27 -0
  9. agent_knowledge/assets/commands/graphify-sync.md +26 -0
  10. agent_knowledge/assets/commands/knowledge-sync.md +26 -0
  11. agent_knowledge/assets/commands/ship.md +29 -0
  12. agent_knowledge/assets/rules/generate-architecture-doc.mdc +87 -0
  13. agent_knowledge/assets/rules/history-backfill.mdc +67 -0
  14. agent_knowledge/assets/rules/memory-bootstrap.mdc +53 -0
  15. agent_knowledge/assets/rules/memory-writeback.mdc +90 -0
  16. agent_knowledge/assets/rules/shared-memory.mdc +102 -0
  17. agent_knowledge/assets/rules/workflow-orchestration.mdc +93 -0
  18. agent_knowledge/assets/rules-global/action-first.mdc +26 -0
  19. agent_knowledge/assets/rules-global/no-icons-emojis.mdc +16 -0
  20. agent_knowledge/assets/rules-global/no-unsolicited-docs.mdc +20 -0
  21. agent_knowledge/assets/scripts/bootstrap-memory-tree.sh +389 -0
  22. agent_knowledge/assets/scripts/compact-memory.sh +191 -0
  23. agent_knowledge/assets/scripts/doctor.sh +137 -0
  24. agent_knowledge/assets/scripts/global-knowledge-sync.sh +372 -0
  25. agent_knowledge/assets/scripts/graphify-sync.sh +397 -0
  26. agent_knowledge/assets/scripts/import-agent-history.sh +706 -0
  27. agent_knowledge/assets/scripts/install-project-links.sh +258 -0
  28. agent_knowledge/assets/scripts/lib/knowledge-common.sh +875 -0
  29. agent_knowledge/assets/scripts/measure-token-savings.py +540 -0
  30. agent_knowledge/assets/scripts/ship.sh +256 -0
  31. agent_knowledge/assets/scripts/update-knowledge.sh +341 -0
  32. agent_knowledge/assets/scripts/validate-knowledge.sh +265 -0
  33. agent_knowledge/assets/skills/decision-recording/SKILL.md +124 -0
  34. agent_knowledge/assets/skills/history-backfill/SKILL.md +115 -0
  35. agent_knowledge/assets/skills/memory-compaction/SKILL.md +115 -0
  36. agent_knowledge/assets/skills/memory-management/SKILL.md +134 -0
  37. agent_knowledge/assets/skills/project-ontology-bootstrap/SKILL.md +173 -0
  38. agent_knowledge/assets/skills/session-management/SKILL.md +116 -0
  39. agent_knowledge/assets/skills-cursor/create-rule/SKILL.md +164 -0
  40. agent_knowledge/assets/skills-cursor/create-skill/SKILL.md +498 -0
  41. agent_knowledge/assets/skills-cursor/create-subagent/SKILL.md +225 -0
  42. agent_knowledge/assets/skills-cursor/migrate-to-skills/SKILL.md +134 -0
  43. agent_knowledge/assets/skills-cursor/shell/SKILL.md +24 -0
  44. agent_knowledge/assets/skills-cursor/update-cursor-settings/SKILL.md +122 -0
  45. agent_knowledge/assets/templates/dashboards/project-overview.template.md +24 -0
  46. agent_knowledge/assets/templates/dashboards/session-rollup.template.md +23 -0
  47. agent_knowledge/assets/templates/hooks/hooks.json.template +11 -0
  48. agent_knowledge/assets/templates/integrations/claude/CLAUDE.md +7 -0
  49. agent_knowledge/assets/templates/integrations/codex/AGENTS.md +7 -0
  50. agent_knowledge/assets/templates/integrations/cursor/agent-knowledge.mdc +11 -0
  51. agent_knowledge/assets/templates/integrations/cursor/hooks.json +11 -0
  52. agent_knowledge/assets/templates/memory/MEMORY.root.template.md +36 -0
  53. agent_knowledge/assets/templates/memory/branch.template.md +33 -0
  54. agent_knowledge/assets/templates/memory/decision.template.md +33 -0
  55. agent_knowledge/assets/templates/memory/profile.hybrid.yaml +16 -0
  56. agent_knowledge/assets/templates/memory/profile.ml-platform.yaml +18 -0
  57. agent_knowledge/assets/templates/memory/profile.robotics.yaml +19 -0
  58. agent_knowledge/assets/templates/memory/profile.web-app.yaml +16 -0
  59. agent_knowledge/assets/templates/portfolio/.obsidian/README.md +21 -0
  60. agent_knowledge/assets/templates/portfolio/.obsidian/app.json +5 -0
  61. agent_knowledge/assets/templates/portfolio/.obsidian/core-plugins.json +7 -0
  62. agent_knowledge/assets/templates/project/.agent-project.yaml +36 -0
  63. agent_knowledge/assets/templates/project/.agentknowledgeignore +10 -0
  64. agent_knowledge/assets/templates/project/AGENTS.md +87 -0
  65. agent_knowledge/assets/templates/project/agent-knowledge/.obsidian/README.md +23 -0
  66. agent_knowledge/assets/templates/project/agent-knowledge/.obsidian/app.json +5 -0
  67. agent_knowledge/assets/templates/project/agent-knowledge/.obsidian/core-plugins.json +7 -0
  68. agent_knowledge/assets/templates/project/agent-knowledge/Evidence/README.md +34 -0
  69. agent_knowledge/assets/templates/project/agent-knowledge/Evidence/imports/README.md +29 -0
  70. agent_knowledge/assets/templates/project/agent-knowledge/Evidence/raw/README.md +25 -0
  71. agent_knowledge/assets/templates/project/agent-knowledge/Memory/MEMORY.md +37 -0
  72. agent_knowledge/assets/templates/project/agent-knowledge/Memory/decisions/decisions.md +31 -0
  73. agent_knowledge/assets/templates/project/agent-knowledge/Outputs/README.md +24 -0
  74. agent_knowledge/assets/templates/project/agent-knowledge/STATUS.md +43 -0
  75. agent_knowledge/assets/templates/project/agent-knowledge/Sessions/README.md +21 -0
  76. agent_knowledge/assets/templates/project/agent-knowledge/Templates/README.md +19 -0
  77. agent_knowledge/assets/templates/project/gitignore.agent-knowledge +13 -0
  78. agent_knowledge/cli.py +457 -0
  79. agent_knowledge/runtime/__init__.py +0 -0
  80. agent_knowledge/runtime/integrations.py +154 -0
  81. agent_knowledge/runtime/paths.py +46 -0
  82. agent_knowledge/runtime/shell.py +22 -0
  83. agent_knowledge/runtime/sync.py +255 -0
  84. agent_knowledge_cli-0.1.2.dist-info/METADATA +155 -0
  85. agent_knowledge_cli-0.1.2.dist-info/RECORD +88 -0
  86. agent_knowledge_cli-0.1.2.dist-info/WHEEL +4 -0
  87. agent_knowledge_cli-0.1.2.dist-info/entry_points.txt +2 -0
  88. agent_knowledge_cli-0.1.2.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,191 @@
1
+ #!/bin/bash
2
+ #
3
+ # Compact and clean memory notes conservatively.
4
+ #
5
+
6
+ set -euo pipefail
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
9
+ # shellcheck source=/dev/null
10
+ . "$SCRIPT_DIR/lib/knowledge-common.sh"
11
+
12
+ usage() {
13
+ cat <<'EOF'
14
+ Usage:
15
+ scripts/compact-memory.sh [project-dir]
16
+ scripts/compact-memory.sh --project <dir> [--dry-run] [--json] [--summary-file <file>]
17
+ EOF
18
+ }
19
+
20
+ TARGET_PROJECT_ARG="."
21
+ POSITIONAL=()
22
+ COMPACTED=()
23
+ WARNINGS=()
24
+
25
+ while [ "$#" -gt 0 ]; do
26
+ if kc_parse_common_flag "$@" ; then
27
+ shift
28
+ continue
29
+ fi
30
+ flag_status=$?
31
+ if [ "$flag_status" -eq 2 ]; then
32
+ shift 2
33
+ continue
34
+ fi
35
+
36
+ case "$1" in
37
+ --project)
38
+ TARGET_PROJECT_ARG="${2:-.}"
39
+ shift 2
40
+ ;;
41
+ *)
42
+ POSITIONAL+=("$1")
43
+ shift
44
+ ;;
45
+ esac
46
+ done
47
+
48
+ if [ "$SHOW_HELP" -eq 1 ]; then
49
+ usage
50
+ exit 0
51
+ fi
52
+
53
+ if [ ${#POSITIONAL[@]} -ge 1 ]; then
54
+ TARGET_PROJECT_ARG="${POSITIONAL[0]}"
55
+ fi
56
+
57
+ kc_load_project_context "$TARGET_PROJECT_ARG"
58
+ [ -d "$MEMORY_DIR" ] || kc_fail "No memory tree at: $MEMORY_DIR"
59
+
60
+ compact_recent_changes() {
61
+ local file="$1"
62
+ local limit="$2"
63
+ local label="$3"
64
+ local tmp_file
65
+
66
+ tmp_file="$(mktemp)"
67
+ awk -v limit="$limit" '
68
+ BEGIN {
69
+ in_recent = 0
70
+ count = 0
71
+ }
72
+ {
73
+ if ($0 == "## Recent Changes") {
74
+ in_recent = 1
75
+ delete seen
76
+ print
77
+ next
78
+ }
79
+
80
+ if (in_recent && /^## /) {
81
+ in_recent = 0
82
+ }
83
+
84
+ if (in_recent) {
85
+ if ($0 ~ /^- /) {
86
+ if (!($0 in seen) && count < limit) {
87
+ seen[$0] = 1
88
+ kept[++count] = $0
89
+ }
90
+ next
91
+ }
92
+ if ($0 ~ /^[[:space:]]*$/) {
93
+ next
94
+ }
95
+ }
96
+
97
+ print
98
+
99
+ if (!in_recent) {
100
+ next
101
+ }
102
+ }
103
+ END {
104
+ if (count > 0) {
105
+ for (i = 1; i <= count; i++) {
106
+ print kept[i]
107
+ }
108
+ }
109
+ }
110
+ ' "$file" > "$tmp_file"
111
+
112
+ kc_apply_temp_file "$tmp_file" "$file" "$label"
113
+ case "$KC_LAST_ACTION" in
114
+ updated|would-update)
115
+ COMPACTED+=("$label")
116
+ ;;
117
+ esac
118
+ }
119
+
120
+ health_check_note() {
121
+ local file="$1"
122
+ local rel="$2"
123
+ local lines
124
+
125
+ lines="$(wc -l < "$file" 2>/dev/null || echo 0)"
126
+ if [ "$lines" -gt 220 ]; then
127
+ WARNINGS+=("$rel is still over 220 lines after compaction")
128
+ elif [ "$lines" -gt 180 ]; then
129
+ WARNINGS+=("$rel is still over 180 lines after compaction")
130
+ fi
131
+ }
132
+
133
+ kc_log "Compacting memory: $MEMORY_DIR"
134
+
135
+ memory_files="$(find "$MEMORY_DIR" -name "*.md" | sort)"
136
+ while IFS= read -r file; do
137
+ [ -n "$file" ] || continue
138
+ rel="$(kc_rel_knowledge_path "$file")"
139
+ limit=12
140
+ case "$file" in
141
+ "$MEMORY_ROOT")
142
+ limit=8
143
+ ;;
144
+ */decisions/*)
145
+ limit=8
146
+ ;;
147
+ esac
148
+ compact_recent_changes "$file" "$limit" "$rel"
149
+ done <<EOF
150
+ $memory_files
151
+ EOF
152
+
153
+ while IFS= read -r file; do
154
+ [ -n "$file" ] || continue
155
+ rel="$(kc_rel_knowledge_path "$file")"
156
+ health_check_note "$file" "$rel"
157
+ done <<EOF
158
+ $memory_files
159
+ EOF
160
+
161
+ kc_status_load
162
+ if [ "${DRY_RUN:-0}" -eq 0 ] && [ ${#COMPACTED[@]} -gt 0 ]; then
163
+ STATUS_LAST_COMPACTION="$(kc_now_utc)"
164
+ fi
165
+ STATUS_WARNING_LINES="$(printf '%s\n' "${WARNINGS[@]+"${WARNINGS[@]}"}")"
166
+ kc_status_write "$STATUS_WARNING_LINES"
167
+
168
+ json_summary="{"
169
+ json_summary="$json_summary\"script\":\"compact-memory\","
170
+ json_summary="$json_summary\"project_root\":\"$(kc_json_escape "$TARGET_PROJECT")\","
171
+ json_summary="$json_summary\"dry_run\":$(kc_json_bool "$DRY_RUN"),"
172
+ json_summary="$json_summary\"compacted\":$(kc_json_array "${COMPACTED[@]+"${COMPACTED[@]}"}"),"
173
+ json_summary="$json_summary\"warnings\":$(kc_json_array "${WARNINGS[@]+"${WARNINGS[@]}"}")"
174
+ json_summary="$json_summary}"
175
+ kc_write_json_output "$json_summary"
176
+
177
+ if [ "$JSON_MODE" -ne 1 ]; then
178
+ kc_log ""
179
+ if [ ${#COMPACTED[@]} -gt 0 ]; then
180
+ kc_log "Compacted notes:"
181
+ printf ' %s\n' "${COMPACTED[@]+"${COMPACTED[@]}"}"
182
+ else
183
+ kc_log "No compaction changes were needed."
184
+ fi
185
+
186
+ if [ ${#WARNINGS[@]} -gt 0 ]; then
187
+ kc_log ""
188
+ kc_log "Warnings:"
189
+ printf ' %s\n' "${WARNINGS[@]+"${WARNINGS[@]}"}"
190
+ fi
191
+ fi
@@ -0,0 +1,137 @@
1
+ #!/bin/bash
2
+ #
3
+ # Quick troubleshooting entrypoint for the project knowledge system.
4
+ #
5
+
6
+ set -euo pipefail
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
9
+ # shellcheck source=/dev/null
10
+ . "$SCRIPT_DIR/lib/knowledge-common.sh"
11
+
12
+ usage() {
13
+ cat <<'EOF'
14
+ Usage:
15
+ scripts/doctor.sh [project-dir]
16
+ scripts/doctor.sh --project <dir> [--json] [--summary-file <file>] [--dry-run]
17
+ EOF
18
+ }
19
+
20
+ TARGET_PROJECT_ARG="."
21
+ POSITIONAL=()
22
+ WARNINGS=()
23
+
24
+ while [ "$#" -gt 0 ]; do
25
+ if kc_parse_common_flag "$@" ; then
26
+ shift
27
+ continue
28
+ fi
29
+ flag_status=$?
30
+ if [ "$flag_status" -eq 2 ]; then
31
+ shift 2
32
+ continue
33
+ fi
34
+
35
+ case "$1" in
36
+ --project)
37
+ TARGET_PROJECT_ARG="${2:-.}"
38
+ shift 2
39
+ ;;
40
+ *)
41
+ POSITIONAL+=("$1")
42
+ shift
43
+ ;;
44
+ esac
45
+ done
46
+
47
+ if [ "$SHOW_HELP" -eq 1 ]; then
48
+ usage
49
+ exit 0
50
+ fi
51
+
52
+ if [ ${#POSITIONAL[@]} -ge 1 ]; then
53
+ TARGET_PROJECT_ARG="${POSITIONAL[0]}"
54
+ fi
55
+
56
+ kc_load_project_context "$TARGET_PROJECT_ARG"
57
+
58
+ validation_status="ok"
59
+ doctor_validate_args=(--project "$TARGET_PROJECT")
60
+ if [ "$DRY_RUN" -eq 1 ]; then
61
+ doctor_validate_args+=(--dry-run)
62
+ fi
63
+ if ! kc_run_child_script "$SCRIPT_DIR/validate-knowledge.sh" "${doctor_validate_args[@]}"; then
64
+ validation_status="error"
65
+ fi
66
+
67
+ if [ -n "$FRAMEWORK_REPO" ] && [ ! -d "$FRAMEWORK_REPO" ]; then
68
+ WARNINGS+=("Framework repo path from .agent-project.yaml does not exist: $FRAMEWORK_REPO")
69
+ fi
70
+
71
+ if [ ! -f "$TARGET_PROJECT/AGENTS.md" ]; then
72
+ WARNINGS+=("AGENTS.md is missing from the project repo.")
73
+ fi
74
+
75
+ if [ -f "$TARGET_PROJECT/.cursor/hooks.json" ]; then
76
+ WARNINGS+=("Repo-local hooks are installed; review them if sync behavior is surprising.")
77
+ fi
78
+
79
+ if [ ! -L "$KNOWLEDGE_POINTER_PATH" ]; then
80
+ if kc_is_windows_like; then
81
+ WARNINGS+=("agent-knowledge is not reported as a symlink. If this is a junction, verify it still resolves to the external knowledge folder.")
82
+ else
83
+ WARNINGS+=("agent-knowledge is not a symlink. Canonical external source-of-truth mode is not active.")
84
+ fi
85
+ fi
86
+
87
+ # Detect integrations
88
+ INTEGRATIONS=()
89
+ [ -d "$TARGET_PROJECT/.cursor" ] && INTEGRATIONS+=("cursor")
90
+ [ -d "$TARGET_PROJECT/.claude" ] || [ -f "$TARGET_PROJECT/CLAUDE.md" ] && INTEGRATIONS+=("claude")
91
+ [ -d "$TARGET_PROJECT/.codex" ] && INTEGRATIONS+=("codex")
92
+
93
+ # Read onboarding state
94
+ ONBOARDING_STATUS="$(kc_yaml_leaf_value "$STATUS_FILE" "onboarding" 2>/dev/null || echo "unknown")"
95
+
96
+ doctor_result="ok"
97
+ if [ "$validation_status" = "error" ]; then
98
+ doctor_result="error"
99
+ elif [ ${#WARNINGS[@]} -gt 0 ]; then
100
+ doctor_result="warn"
101
+ fi
102
+
103
+ kc_status_load
104
+ if [ "${DRY_RUN:-0}" -eq 0 ]; then
105
+ STATUS_LAST_DOCTOR="$(kc_now_utc)"
106
+ STATUS_LAST_DOCTOR_RESULT="$doctor_result"
107
+ fi
108
+ STATUS_WARNING_LINES="$(printf '%s\n' "${WARNINGS[@]+"${WARNINGS[@]}"}")"
109
+ kc_status_write "$STATUS_WARNING_LINES"
110
+
111
+ json_summary="{"
112
+ json_summary="$json_summary\"script\":\"doctor\","
113
+ json_summary="$json_summary\"project_root\":\"$(kc_json_escape "$TARGET_PROJECT")\","
114
+ json_summary="$json_summary\"result\":\"$(kc_json_escape "$doctor_result")\","
115
+ json_summary="$json_summary\"dry_run\":$(kc_json_bool "$DRY_RUN"),"
116
+ json_summary="$json_summary\"onboarding\":\"$(kc_json_escape "$ONBOARDING_STATUS")\","
117
+ json_summary="$json_summary\"integrations\":$(kc_json_array "${INTEGRATIONS[@]+"${INTEGRATIONS[@]}"}"),"
118
+ json_summary="$json_summary\"warnings\":$(kc_json_array "${WARNINGS[@]+"${WARNINGS[@]}"}")"
119
+ json_summary="$json_summary}"
120
+ kc_write_json_output "$json_summary"
121
+
122
+ if [ "$JSON_MODE" -ne 1 ]; then
123
+ kc_log "Doctor result: $doctor_result"
124
+ kc_log " project: $TARGET_PROJECT"
125
+ kc_log " pointer: $KNOWLEDGE_POINTER_PATH"
126
+ kc_log " real knowledge path: $KNOWLEDGE_REAL_DIR"
127
+ kc_log " onboarding: $ONBOARDING_STATUS"
128
+ kc_log " integrations: ${INTEGRATIONS[*]+"${INTEGRATIONS[*]}"}"
129
+ if [ ${#WARNINGS[@]} -gt 0 ]; then
130
+ kc_log "Warnings:"
131
+ printf ' %s\n' "${WARNINGS[@]+"${WARNINGS[@]}"}"
132
+ fi
133
+ fi
134
+
135
+ if [ "$doctor_result" = "error" ]; then
136
+ exit 1
137
+ fi
@@ -0,0 +1,372 @@
1
+ #!/bin/bash
2
+ #
3
+ # Build or update a project-scoped tooling knowledge base from safe allowlisted sources.
4
+ #
5
+
6
+ set -euo pipefail
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
9
+ # shellcheck source=/dev/null
10
+ . "$SCRIPT_DIR/lib/knowledge-common.sh"
11
+
12
+ usage() {
13
+ cat <<'EOF'
14
+ Usage:
15
+ scripts/global-knowledge-sync.sh [project-dir]
16
+ scripts/global-knowledge-sync.sh --project <dir> [--dry-run] [--json] [--summary-file <file>]
17
+ EOF
18
+ }
19
+
20
+ TARGET_PROJECT_ARG="."
21
+ POSITIONAL=()
22
+ SCANNED=()
23
+ SKIPPED=()
24
+ UPDATED=()
25
+ CACHED=()
26
+ WARNINGS=()
27
+ GENERATED_AT="$(kc_now_utc)"
28
+
29
+ while [ "$#" -gt 0 ]; do
30
+ if kc_parse_common_flag "$@" ; then
31
+ shift
32
+ continue
33
+ fi
34
+ flag_status=$?
35
+ if [ "$flag_status" -eq 2 ]; then
36
+ shift 2
37
+ continue
38
+ fi
39
+
40
+ case "$1" in
41
+ --project)
42
+ TARGET_PROJECT_ARG="${2:-.}"
43
+ shift 2
44
+ ;;
45
+ *)
46
+ POSITIONAL+=("$1")
47
+ shift
48
+ ;;
49
+ esac
50
+ done
51
+
52
+ if [ "$SHOW_HELP" -eq 1 ]; then
53
+ usage
54
+ exit 0
55
+ fi
56
+
57
+ if [ ${#POSITIONAL[@]} -ge 1 ]; then
58
+ TARGET_PROJECT_ARG="${POSITIONAL[0]}"
59
+ fi
60
+
61
+ kc_load_project_context "$TARGET_PROJECT_ARG"
62
+ kc_require_knowledge_pointer
63
+
64
+ TOOLING_EVIDENCE_DIR="$EVIDENCE_TOOLING_DIR"
65
+ TOOLING_MEMORY_DIR="$MEMORY_DIR/tooling"
66
+ TOOLING_INDEX="$TOOLING_MEMORY_DIR/INDEX.md"
67
+
68
+ kc_ensure_dir "$TOOLING_EVIDENCE_DIR" "agent-knowledge/Evidence/tooling"
69
+ kc_ensure_dir "$TOOLING_MEMORY_DIR" "agent-knowledge/Memory/tooling"
70
+ kc_ensure_dir "$EVIDENCE_CACHE_DIR" "agent-knowledge/Evidence/.cache"
71
+
72
+ is_allowlisted_tool_file() {
73
+ local path="$1"
74
+ case "$path" in
75
+ "$HOME/.claude/settings.json"|"$HOME/.claude/CLAUDE.md"|"$HOME/.codex/config.toml"|"$HOME/.cursor/settings.json")
76
+ return 0
77
+ ;;
78
+ "$HOME/.claude/agents/"*|"$HOME/.cursor/rules/"*|"$HOME/.cursor/snippets/"*)
79
+ return 0
80
+ ;;
81
+ esac
82
+ return 1
83
+ }
84
+
85
+ is_safe_tool_file() {
86
+ local path="$1"
87
+ case "$path" in
88
+ *session*|*oauth*|*token*|*auth*|*cache*|*.db|*.sqlite|*.sqlite3)
89
+ return 1
90
+ ;;
91
+ *)
92
+ return 0
93
+ ;;
94
+ esac
95
+ }
96
+
97
+ redact_tool_file() {
98
+ local src="$1"
99
+ sed -E \
100
+ -e 's/([Pp]assword[[:space:]]*[:=][[:space:]]*).*/\1[REDACTED]/g' \
101
+ -e 's/([Tt]oken[[:space:]]*[:=][[:space:]]*).*/\1[REDACTED]/g' \
102
+ -e 's/([Ss]ecret[[:space:]]*[:=][[:space:]]*).*/\1[REDACTED]/g' \
103
+ -e 's/([Aa]uthorization[[:space:]]*[:=][[:space:]]*).*/\1[REDACTED]/g' \
104
+ -e 's/([Cc]ookie[[:space:]]*[:=][[:space:]]*).*/\1[REDACTED]/g' \
105
+ -e 's/([Oo]auth[^:=]*[[:space:]]*[:=][[:space:]]*).*/\1[REDACTED]/g' \
106
+ -e 's/([Aa]pi[_-]?[Kk]ey[[:space:]]*[:=][[:space:]]*).*/\1[REDACTED]/g' \
107
+ -e 's/([Rr]efresh[_-]?[Tt]oken[[:space:]]*[:=][[:space:]]*).*/\1[REDACTED]/g' \
108
+ "$src"
109
+ }
110
+
111
+ capture_tooling_evidence() {
112
+ local src="$1"
113
+ local family="$2"
114
+ local name="$3"
115
+ local dst="$TOOLING_EVIDENCE_DIR/$name"
116
+ local meta_dst="$dst.meta.json"
117
+ local signature=""
118
+ local tmp_file=""
119
+ local changed=0
120
+
121
+ signature="$(kc_signature_from_paths "$src")"
122
+ if kc_cache_is_current "global-tooling" "$name" "$signature" "$dst" "$meta_dst"; then
123
+ CACHED+=("agent-knowledge/Evidence/tooling/$name")
124
+ SCANNED+=("$src")
125
+ TOOLING_FAMILIES="${TOOLING_FAMILIES}${family}"$'\n'
126
+ TOOLING_FILES="${TOOLING_FILES}${family}|$name|$src"$'\n'
127
+ return 0
128
+ fi
129
+
130
+ tmp_file="$(mktemp)"
131
+ {
132
+ printf '# Tooling Evidence\n'
133
+ printf '# Source: %s\n' "$src"
134
+ printf '# Kind: tooling-import\n'
135
+ printf '# Confidence: EXTRACTED\n'
136
+ printf '# Generated: %s\n\n' "$GENERATED_AT"
137
+ redact_tool_file "$src"
138
+ } > "$tmp_file"
139
+
140
+ kc_apply_temp_file "$tmp_file" "$dst" "agent-knowledge/Evidence/tooling/$name"
141
+ case "$KC_LAST_ACTION" in
142
+ created|updated|would-create|would-update)
143
+ changed=1
144
+ ;;
145
+ esac
146
+
147
+ kc_write_metadata_json "$meta_dst" "agent-knowledge/Evidence/tooling/$name.meta.json" "$src" "tooling-import" "EXTRACTED" "$GENERATED_AT" "$src" "Redacted allowlisted tooling surface captured for project-scoped reference."
148
+ case "$KC_LAST_ACTION" in
149
+ created|updated|would-create|would-update)
150
+ changed=1
151
+ ;;
152
+ esac
153
+
154
+ kc_cache_store "global-tooling" "$name" "$signature"
155
+
156
+ if [ "$changed" -eq 1 ]; then
157
+ UPDATED+=("agent-knowledge/Evidence/tooling/$name")
158
+ fi
159
+ SCANNED+=("$src")
160
+ TOOLING_FAMILIES="${TOOLING_FAMILIES}${family}"$'\n'
161
+ TOOLING_FILES="${TOOLING_FILES}${family}|$name|$src"$'\n'
162
+ }
163
+
164
+ write_tooling_note() {
165
+ local family="$1"
166
+ local title="$2"
167
+ local purpose="$3"
168
+ local file_name="$TOOLING_MEMORY_DIR/$family.md"
169
+ local entries=""
170
+ local line=""
171
+ local signature=""
172
+ local tmp_file=""
173
+
174
+ while IFS= read -r line; do
175
+ [ -n "$line" ] || continue
176
+ case "$line" in
177
+ "$family|"*)
178
+ name="$(printf '%s' "$line" | cut -d'|' -f2)"
179
+ src="$(printf '%s' "$line" | cut -d'|' -f3-)"
180
+ entries="${entries}- [../../Evidence/tooling/$name](../../Evidence/tooling/$name) - Redacted import from \`$src\`."$'\n'
181
+ ;;
182
+ esac
183
+ done <<EOF
184
+ $TOOLING_FILES
185
+ EOF
186
+
187
+ [ -n "$entries" ] || entries="- No allowlisted sources were captured."
188
+ signature="$(kc_signature_from_lines "$(printf '%s\n---\n%s\n---\n%s\n' "$family" "$title" "$entries")")"
189
+ if kc_cache_is_current "global-tooling-note" "$family" "$signature" "$file_name"; then
190
+ CACHED+=("agent-knowledge/Memory/tooling/$family.md")
191
+ return 0
192
+ fi
193
+
194
+ tmp_file="$(mktemp)"
195
+ {
196
+ printf '%s\n' '---'
197
+ printf 'note_type: tooling-memory\n'
198
+ printf 'project: %s\n' "$PROJECT_NAME"
199
+ printf 'profile: %s\n' "$PROJECT_PROFILE"
200
+ printf 'area: tooling-%s\n' "$family"
201
+ printf 'status: active\n'
202
+ printf 'last_updated: %s\n' "$(kc_today)"
203
+ printf '%s\n\n' '---'
204
+ printf '# %s\n\n' "$title"
205
+ printf '## Purpose\n\n- %s\n\n' "$purpose"
206
+ printf '## Current State\n\n- Tooling knowledge is derived only from allowlisted local configuration surfaces.\n- Sensitive lines are redacted before evidence is written.\n\n'
207
+ printf '## Recent Changes\n\n- %s - Refreshed tooling evidence for `%s`.\n\n' "$(kc_today)" "$family"
208
+ printf '## Decisions\n\n- No tooling-specific decisions recorded yet.\n\n'
209
+ printf '## Open Questions\n\n- Which parts of this tooling setup are stable enough to rely on across sessions?\n\n'
210
+ printf '## Subtopics\n\n%s\n' "$entries"
211
+ } > "$tmp_file"
212
+
213
+ kc_apply_temp_file "$tmp_file" "$file_name" "agent-knowledge/Memory/tooling/$family.md"
214
+ case "$KC_LAST_ACTION" in
215
+ created|updated|would-create|would-update)
216
+ UPDATED+=("agent-knowledge/Memory/tooling/$family.md")
217
+ ;;
218
+ esac
219
+ kc_cache_store "global-tooling-note" "$family" "$signature"
220
+ }
221
+
222
+ write_tooling_index() {
223
+ local families=""
224
+ local family=""
225
+ local bullets=""
226
+ local signature=""
227
+ local tmp_file=""
228
+
229
+ families="$(printf '%s\n' "$TOOLING_FAMILIES" | awk 'NF && !seen[$0]++ { print $0 }')"
230
+ while IFS= read -r family; do
231
+ [ -n "$family" ] || continue
232
+ bullets="${bullets}- [${family}.md](${family}.md) - Redacted ${family} tooling summary."$'\n'
233
+ done <<EOF
234
+ $families
235
+ EOF
236
+
237
+ [ -n "$bullets" ] || bullets="- No allowlisted tooling sources were found."
238
+ signature="$(kc_signature_from_lines "$bullets")"
239
+ if kc_cache_is_current "global-tooling-note" "index" "$signature" "$TOOLING_INDEX"; then
240
+ CACHED+=("agent-knowledge/Memory/tooling/INDEX.md")
241
+ return 0
242
+ fi
243
+
244
+ tmp_file="$(mktemp)"
245
+ {
246
+ printf '%s\n' '---'
247
+ printf 'note_type: tooling-index\n'
248
+ printf 'project: %s\n' "$PROJECT_NAME"
249
+ printf 'status: active\n'
250
+ printf 'last_updated: %s\n' "$(kc_today)"
251
+ printf '%s\n\n' '---'
252
+ printf '# Tooling\n\n'
253
+ printf '## Purpose\n\n- Curated summary of safe local tooling surfaces relevant to this project.\n\n'
254
+ printf '## Current State\n\n- Evidence is redacted and stored under [../../Evidence/tooling](../../Evidence/tooling).\n\n'
255
+ printf '## Recent Changes\n\n- %s - Refreshed tooling knowledge from allowlisted local sources.\n\n' "$(kc_today)"
256
+ printf '## Decisions\n\n- No tooling decisions recorded yet.\n\n'
257
+ printf '## Open Questions\n\n- Which global tool defaults should be copied into project-specific durable memory?\n\n'
258
+ printf '## Subtopics\n\n%s\n' "$bullets"
259
+ } > "$tmp_file"
260
+
261
+ kc_apply_temp_file "$tmp_file" "$TOOLING_INDEX" "agent-knowledge/Memory/tooling/INDEX.md"
262
+ case "$KC_LAST_ACTION" in
263
+ created|updated|would-create|would-update)
264
+ UPDATED+=("agent-knowledge/Memory/tooling/INDEX.md")
265
+ ;;
266
+ esac
267
+ kc_cache_store "global-tooling-note" "index" "$signature"
268
+ kc_append_unique_bullet "$MEMORY_ROOT" "Subtopics" "- [Tooling](tooling/INDEX.md) - Redacted local tooling setup relevant to this project." "agent-knowledge/Memory/MEMORY.md"
269
+ }
270
+
271
+ TOOLING_FAMILIES=""
272
+ TOOLING_FILES=""
273
+
274
+ for path in \
275
+ "$HOME/.claude/settings.json" \
276
+ "$HOME/.claude/CLAUDE.md" \
277
+ "$HOME/.codex/config.toml" \
278
+ "$HOME/.cursor/settings.json"; do
279
+ if [ -f "$path" ] && is_allowlisted_tool_file "$path"; then
280
+ if is_safe_tool_file "$path"; then
281
+ case "$path" in
282
+ "$HOME/.claude/"*)
283
+ capture_tooling_evidence "$path" "claude" "$(basename "$path" | tr '[:upper:]' '[:lower:]')"
284
+ ;;
285
+ "$HOME/.codex/"*)
286
+ capture_tooling_evidence "$path" "codex" "$(basename "$path" | tr '[:upper:]' '[:lower:]')"
287
+ ;;
288
+ "$HOME/.cursor/"*)
289
+ capture_tooling_evidence "$path" "cursor" "$(basename "$path" | tr '[:upper:]' '[:lower:]')"
290
+ ;;
291
+ esac
292
+ else
293
+ SKIPPED+=("$path")
294
+ fi
295
+ fi
296
+ done
297
+
298
+ for dir in "$HOME/.claude/agents" "$HOME/.cursor/rules" "$HOME/.cursor/snippets"; do
299
+ [ -d "$dir" ] || continue
300
+ while IFS= read -r path; do
301
+ [ -n "$path" ] || continue
302
+ if ! is_allowlisted_tool_file "$path"; then
303
+ continue
304
+ fi
305
+ if ! is_safe_tool_file "$path"; then
306
+ SKIPPED+=("$path")
307
+ continue
308
+ fi
309
+ case "$dir" in
310
+ "$HOME/.claude/agents")
311
+ capture_tooling_evidence "$path" "claude" "agents-$(basename "$path")"
312
+ ;;
313
+ "$HOME/.cursor/"*)
314
+ capture_tooling_evidence "$path" "cursor" "$(basename "$dir")-$(basename "$path")"
315
+ ;;
316
+ esac
317
+ done <<EOF
318
+ $(find "$dir" -type f \( -name "*.md" -o -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.toml" -o -name "*.txt" \) 2>/dev/null | sort)
319
+ EOF
320
+ done
321
+
322
+ if [ -z "$TOOLING_FILES" ]; then
323
+ WARNINGS+=("No allowlisted local tooling sources were found.")
324
+ else
325
+ if printf '%s\n' "$TOOLING_FAMILIES" | grep -q '^claude$'; then
326
+ write_tooling_note "claude" "Claude Tooling" "Redacted Claude settings and prompt surfaces that may affect project work."
327
+ fi
328
+ if printf '%s\n' "$TOOLING_FAMILIES" | grep -q '^codex$'; then
329
+ write_tooling_note "codex" "Codex Tooling" "Redacted Codex configuration surfaces that may affect project work."
330
+ fi
331
+ if printf '%s\n' "$TOOLING_FAMILIES" | grep -q '^cursor$'; then
332
+ write_tooling_note "cursor" "Cursor Tooling" "Redacted Cursor customization surfaces that may affect project work."
333
+ fi
334
+ write_tooling_index
335
+ fi
336
+
337
+ kc_status_load
338
+ if [ "${DRY_RUN:-0}" -eq 0 ] && [ ${#UPDATED[@]} -gt 0 ]; then
339
+ STATUS_LAST_GLOBAL_SYNC="$(kc_now_utc)"
340
+ fi
341
+ STATUS_WARNING_LINES="$(printf '%s\n' "${WARNINGS[@]+"${WARNINGS[@]}"}")"
342
+ kc_status_write "$STATUS_WARNING_LINES"
343
+
344
+ json_summary="{"
345
+ json_summary="$json_summary\"script\":\"global-knowledge-sync\","
346
+ json_summary="$json_summary\"project_root\":\"$(kc_json_escape "$TARGET_PROJECT")\","
347
+ json_summary="$json_summary\"dry_run\":$(kc_json_bool "$DRY_RUN"),"
348
+ json_summary="$json_summary\"scanned\":$(kc_json_array "${SCANNED[@]+"${SCANNED[@]}"}"),"
349
+ json_summary="$json_summary\"skipped\":$(kc_json_array "${SKIPPED[@]+"${SKIPPED[@]}"}"),"
350
+ json_summary="$json_summary\"updated\":$(kc_json_array "${UPDATED[@]+"${UPDATED[@]}"}"),"
351
+ json_summary="$json_summary\"cached\":$(kc_json_array "${CACHED[@]+"${CACHED[@]}"}"),"
352
+ json_summary="$json_summary\"warnings\":$(kc_json_array "${WARNINGS[@]+"${WARNINGS[@]}"}")"
353
+ json_summary="$json_summary}"
354
+ kc_write_json_output "$json_summary"
355
+
356
+ if [ "$JSON_MODE" -ne 1 ]; then
357
+ kc_log "Global tooling sync: $TARGET_PROJECT"
358
+ if [ ${#SCANNED[@]} -gt 0 ]; then
359
+ kc_log "Scanned:"
360
+ printf ' %s\n' "${SCANNED[@]+"${SCANNED[@]}"}"
361
+ fi
362
+ if [ ${#CACHED[@]} -gt 0 ]; then
363
+ kc_log ""
364
+ kc_log "Cached:"
365
+ printf ' %s\n' "${CACHED[@]+"${CACHED[@]}"}"
366
+ fi
367
+ if [ ${#SKIPPED[@]} -gt 0 ]; then
368
+ kc_log ""
369
+ kc_log "Skipped for safety:"
370
+ printf ' %s\n' "${SKIPPED[@]+"${SKIPPED[@]}"}"
371
+ fi
372
+ fi