create-ai-memory 0.1.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.
package/install.sh ADDED
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env bash
2
+ # ai-memory installer. Interactive when run in a terminal (banner + prompts),
3
+ # and non-interactive when piped (npx, CI): it takes defaults or environment
4
+ # overrides and never blocks. Idempotent; it never clobbers existing vault notes
5
+ # and never double-appends to ~/.zshrc.
6
+ set -euo pipefail
7
+
8
+ HERE="$(cd "$(dirname "$0")" && pwd)"
9
+
10
+ # Interactive only when both stdin and stdout are a terminal.
11
+ INTERACTIVE=0
12
+ [ -t 0 ] && [ -t 1 ] && INTERACTIVE=1
13
+
14
+ # ask <var> <prompt> <default>: read a value interactively, else take the default
15
+ # (or an existing environment value of the same name).
16
+ ask() {
17
+ local __var="$1" __prompt="$2" __default="$3" __cur __reply
18
+ __cur="${!__var:-}"
19
+ [ -n "$__cur" ] && __default="$__cur"
20
+ if [ "$INTERACTIVE" -eq 1 ]; then
21
+ read -r -p " $__prompt [$__default] " __reply || true
22
+ printf -v "$__var" '%s' "${__reply:-$__default}"
23
+ else
24
+ printf -v "$__var" '%s' "$__default"
25
+ fi
26
+ }
27
+
28
+ confirm() { # confirm <prompt> -> 0 for yes; defaults to yes, and yes when piped
29
+ [ "$INTERACTIVE" -eq 0 ] && return 0
30
+ local __reply
31
+ read -r -p " $1 [Y/n] " __reply || true
32
+ case "${__reply:-Y}" in [Nn]*) return 1 ;; *) return 0 ;; esac
33
+ }
34
+
35
+ # Color only when it lands in a real terminal that wants it.
36
+ supports_color() {
37
+ [ "$INTERACTIVE" -eq 1 ] || return 1
38
+ [ -z "${NO_COLOR:-}" ] || return 1
39
+ [ "${TERM:-}" != "dumb" ] || return 1
40
+ }
41
+
42
+ # ANSI Shadow "AI MEMORY" with a teal->violet vertical gradient (24-bit color),
43
+ # degrading to plain block art when color is unavailable.
44
+ banner() {
45
+ local art=(
46
+ ' █████╗ ██╗ ███╗ ███╗███████╗███╗ ███╗ ██████╗ ██████╗ ██╗ ██╗'
47
+ '██╔══██╗██║ ████╗ ████║██╔════╝████╗ ████║██╔═══██╗██╔══██╗╚██╗ ██╔╝'
48
+ '███████║██║ ██╔████╔██║█████╗ ██╔████╔██║██║ ██║██████╔╝ ╚████╔╝ '
49
+ '██╔══██║██║ ██║╚██╔╝██║██╔══╝ ██║╚██╔╝██║██║ ██║██╔══██╗ ╚██╔╝ '
50
+ '██║ ██║██║ ██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║╚██████╔╝██║ ██║ ██║ '
51
+ '╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ '
52
+ )
53
+ local grad=( '45;212;191' '56;189;248' '59;130;246' '99;102;241' '139;92;246' '168;85;247' )
54
+ echo
55
+ if supports_color; then
56
+ local i
57
+ for i in "${!art[@]}"; do
58
+ printf '\033[1;38;2;%sm%s\033[0m\n' "${grad[$i]}" "${art[$i]}"
59
+ done
60
+ printf '\033[2m persistent, agent-agnostic session memory · one vault, any CLI\033[0m\n\n'
61
+ else
62
+ printf '%s\n' "${art[@]}"
63
+ printf ' persistent, agent-agnostic session memory - one vault, any CLI\n\n'
64
+ fi
65
+ }
66
+
67
+ banner
68
+
69
+ # --- gather settings ---------------------------------------------------------
70
+ AI_MEM_ROOT="${AI_MEM_ROOT:-$HOME/.ai-memory/_Ai_Memory}"
71
+ ask AI_MEM_ROOT "Where should your memory vault live?" "$AI_MEM_ROOT"
72
+ AI_MEM_AGENTS="${AI_MEM_AGENTS:-claude codex gemini cursor}"
73
+ ask AI_MEM_AGENTS "Which agents should get <agent>-start launchers?" "$AI_MEM_AGENTS"
74
+
75
+ # --- scaffold the vault ------------------------------------------------------
76
+ echo
77
+ echo " scaffolding vault at: $AI_MEM_ROOT"
78
+ mkdir -p "$AI_MEM_ROOT/_projects" "$AI_MEM_ROOT/_session_logs"
79
+
80
+ copy_if_absent() { # never overwrite the user's real notes on a re-run
81
+ local src="$1" dst="$2"
82
+ if [ -e "$dst" ]; then echo " keep ${dst##*/}"; else cp "$src" "$dst"; echo " create ${dst##*/}"; fi
83
+ }
84
+ copy_if_absent "$HERE/vault-template/_Global_Profile.md" "$AI_MEM_ROOT/_Global_Profile.md"
85
+ copy_if_absent "$HERE/vault-template/_Standards.md" "$AI_MEM_ROOT/_Standards.md"
86
+ copy_if_absent "$HERE/vault-template/_projects/_project_template.md" "$AI_MEM_ROOT/_projects/_project_template.md"
87
+ copy_if_absent "$HERE/vault-template/_session_logs/_session_template.md" "$AI_MEM_ROOT/_session_logs/_session_template.md"
88
+
89
+ # --- assemble the ~/.zshrc lines ---------------------------------------------
90
+ LINES="export AI_MEM_ROOT=\"$AI_MEM_ROOT\""
91
+ if [ "$AI_MEM_AGENTS" != "claude codex gemini cursor" ]; then
92
+ LINES="$LINES
93
+ export AI_MEM_AGENTS=\"$AI_MEM_AGENTS\""
94
+ fi
95
+ LINES="$LINES
96
+ source \"$HERE/shell/ai-mem.zsh\""
97
+
98
+ RC="$HOME/.zshrc"
99
+ SOURCE_LINE="source \"$HERE/shell/ai-mem.zsh\""
100
+
101
+ echo
102
+ if [ -f "$RC" ] && grep -qF "$SOURCE_LINE" "$RC"; then
103
+ echo " ~/.zshrc already sources ai-memory; leaving it untouched."
104
+ elif confirm "Append the setup lines to ~/.zshrc now?"; then
105
+ { printf '\n# ai-memory (https://github.com/rambaarde/create-ai-memory)\n'; printf '%s\n' "$LINES"; } >> "$RC"
106
+ echo " added to $RC"
107
+ echo
108
+ echo " Reload your shell: exec zsh"
109
+ else
110
+ cat <<EOF
111
+
112
+ Add these lines to your ~/.zshrc yourself:
113
+
114
+ $(printf '%s\n' "$LINES" | sed 's/^/ /')
115
+ EOF
116
+ fi
117
+
118
+ cat <<EOF
119
+
120
+ Done. From inside any git repo, run: claude-start
121
+ (or codex-start / gemini-start / cursor-start)
122
+
123
+ Optional integrations: see $HERE/hooks/ and the README.
124
+ EOF
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "create-ai-memory",
3
+ "version": "0.1.0",
4
+ "description": "Persistent, agent-agnostic session memory for AI coding CLIs (Claude Code, Codex, Gemini, Cursor, opencode). One Markdown vault, any agent.",
5
+ "bin": {
6
+ "create-ai-memory": "bin/create-ai-memory.js"
7
+ },
8
+ "type": "commonjs",
9
+ "engines": {
10
+ "node": ">=18"
11
+ },
12
+ "files": [
13
+ "bin/",
14
+ "shell/",
15
+ "hooks/",
16
+ "vault-template/",
17
+ "install.sh",
18
+ "create-ai-memory.plugin.zsh",
19
+ "LICENSE"
20
+ ],
21
+ "keywords": [
22
+ "ai",
23
+ "memory",
24
+ "claude",
25
+ "codex",
26
+ "gemini",
27
+ "cursor",
28
+ "opencode",
29
+ "cli",
30
+ "agent",
31
+ "obsidian",
32
+ "zsh"
33
+ ],
34
+ "homepage": "https://github.com/rambaarde/create-ai-memory#readme",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/rambaarde/create-ai-memory.git"
38
+ },
39
+ "bugs": {
40
+ "url": "https://github.com/rambaarde/create-ai-memory/issues"
41
+ },
42
+ "license": "MIT",
43
+ "author": "Ram Christopher Baarde"
44
+ }
@@ -0,0 +1,75 @@
1
+ # Agent launch adapters for ai-mem.
2
+ #
3
+ # One function per agent: _ai_adapter_<name>. It receives:
4
+ # $1 memory_prompt — assembled vault context + session-mode block
5
+ # $2 mode_block — just the session-mode instructions (may be empty)
6
+ # $3… extra CLI args — anything passed to <name>-start (e.g. files to open)
7
+ #
8
+ # Add a new agent (opencode, aider, …) by defining _ai_adapter_<name> here and
9
+ # listing <name> in AI_MEM_AGENTS (see ai-mem.zsh). No core edits needed.
10
+
11
+ # Codex: --add-dir grants read access to the vault; prompt is positional.
12
+ _ai_adapter_codex() {
13
+ local memory_prompt="$1"
14
+ codex --add-dir "$AI_MEM_ROOT" "$memory_prompt"
15
+ }
16
+
17
+ # Claude Code: --add-dir is variadic, so the prompt must come FIRST or it gets
18
+ # swallowed as a bogus directory and Claude starts with no initial prompt.
19
+ _ai_adapter_claude() {
20
+ local memory_prompt="$1" mode_block="$2"
21
+ if [[ -n "$mode_block" ]]; then
22
+ claude "$memory_prompt" --add-dir "$AI_MEM_ROOT" --append-system-prompt "$mode_block"
23
+ else
24
+ claude "$memory_prompt" --add-dir "$AI_MEM_ROOT"
25
+ fi
26
+ }
27
+
28
+ # Gemini CLI: --include-directories for vault access, -i for the initial prompt.
29
+ _ai_adapter_gemini() {
30
+ local memory_prompt="$1"
31
+ gemini --include-directories "$AI_MEM_ROOT" -i "$memory_prompt"
32
+ }
33
+
34
+ # Cursor has no CLI prompt path, so persist the session's skill choices as a
35
+ # managed always-apply rule that this adapter rewrites each launch (and clears
36
+ # when nothing is selected).
37
+ _ai_adapter_cursor() {
38
+ local memory_prompt="$1" mode_block="$2"
39
+ shift 2
40
+ local cursor_rule="$HOME/.cursor/rules/_ai-session.mdc"
41
+ if [[ -n "$mode_block" ]]; then
42
+ mkdir -p "$HOME/.cursor/rules"
43
+ {
44
+ print -r -- "---"
45
+ print -r -- "description: Active AI session skills (managed by cursor-start; rewritten each launch, cleared when none chosen)."
46
+ print -r -- "globs:"
47
+ print -r -- "alwaysApply: true"
48
+ print -r -- "---"
49
+ print -r --
50
+ print -r -- "$mode_block"
51
+ } > "$cursor_rule"
52
+ else
53
+ rm -f "$cursor_rule"
54
+ fi
55
+ if command -v cursor >/dev/null 2>&1; then
56
+ cursor "$@"
57
+ else
58
+ open -a Cursor
59
+ fi
60
+ }
61
+
62
+ # opencode (sst/opencode): the TUI seeds its first message from --prompt. It has
63
+ # no --add-dir, so vault access rides on the inlined profile/standards in the
64
+ # prompt plus the absolute note paths the agent can read on demand.
65
+ _ai_adapter_opencode() {
66
+ local memory_prompt="$1"
67
+ opencode --prompt "$memory_prompt"
68
+ }
69
+
70
+ # --- Example: add another agent by defining its adapter and listing it in
71
+ # AI_MEM_AGENTS. aider takes the initial instruction via --message:
72
+ # _ai_adapter_aider() {
73
+ # local memory_prompt="$1"
74
+ # aider --message "$memory_prompt"
75
+ # }