@forwardimpact/basecamp 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/LICENSE +201 -0
- package/README.md +229 -0
- package/build.js +124 -0
- package/config/scheduler.json +28 -0
- package/package.json +37 -0
- package/scheduler.js +552 -0
- package/scripts/build-pkg.sh +117 -0
- package/scripts/compile.sh +26 -0
- package/scripts/install.sh +108 -0
- package/scripts/pkg-resources/conclusion.html +62 -0
- package/scripts/pkg-resources/welcome.html +64 -0
- package/scripts/postinstall +46 -0
- package/scripts/uninstall.sh +56 -0
- package/template/.claude/settings.json +40 -0
- package/template/.claude/skills/create-presentations/SKILL.md +75 -0
- package/template/.claude/skills/create-presentations/references/slide.css +35 -0
- package/template/.claude/skills/create-presentations/scripts/convert-to-pdf.js +32 -0
- package/template/.claude/skills/doc-collab/SKILL.md +112 -0
- package/template/.claude/skills/draft-emails/SKILL.md +191 -0
- package/template/.claude/skills/draft-emails/scripts/scan-emails.sh +33 -0
- package/template/.claude/skills/extract-entities/SKILL.md +466 -0
- package/template/.claude/skills/extract-entities/references/TEMPLATES.md +131 -0
- package/template/.claude/skills/extract-entities/scripts/state.py +100 -0
- package/template/.claude/skills/meeting-prep/SKILL.md +135 -0
- package/template/.claude/skills/organize-files/SKILL.md +146 -0
- package/template/.claude/skills/organize-files/scripts/organize-by-type.sh +42 -0
- package/template/.claude/skills/organize-files/scripts/summarize.sh +21 -0
- package/template/.claude/skills/sync-apple-calendar/SKILL.md +101 -0
- package/template/.claude/skills/sync-apple-calendar/references/SCHEMA.md +80 -0
- package/template/.claude/skills/sync-apple-calendar/scripts/sync.py +233 -0
- package/template/.claude/skills/sync-apple-mail/SKILL.md +131 -0
- package/template/.claude/skills/sync-apple-mail/references/SCHEMA.md +88 -0
- package/template/.claude/skills/sync-apple-mail/scripts/parse-emlx.py +104 -0
- package/template/.claude/skills/sync-apple-mail/scripts/sync.py +348 -0
- package/template/CLAUDE.md +152 -0
- package/template/USER.md +5 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# Basecamp Installer (development / repo context)
|
|
5
|
+
#
|
|
6
|
+
# Sets up scheduler config, default knowledge base, and LaunchAgent for local
|
|
7
|
+
# development. The compiled binary is installed via the .pkg installer instead.
|
|
8
|
+
#
|
|
9
|
+
# This script is for engineers running from the repo with deno or node.
|
|
10
|
+
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
+
APP_NAME="fit-basecamp"
|
|
13
|
+
BASECAMP_HOME="$HOME/.fit/basecamp"
|
|
14
|
+
DEFAULT_KB="$HOME/Documents/Personal"
|
|
15
|
+
|
|
16
|
+
echo ""
|
|
17
|
+
echo "Basecamp Installer (dev)"
|
|
18
|
+
echo "========================"
|
|
19
|
+
echo ""
|
|
20
|
+
|
|
21
|
+
# ---------------------------------------------------------------------------
|
|
22
|
+
# 1. Set up scheduler home
|
|
23
|
+
# ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
echo "Setting up scheduler home at $BASECAMP_HOME ..."
|
|
26
|
+
mkdir -p "$BASECAMP_HOME/logs"
|
|
27
|
+
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
# 2. Copy scheduler config (single source of truth: config/scheduler.json)
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
CONFIG_SRC=""
|
|
33
|
+
if [ -f "$SCRIPT_DIR/../config/scheduler.json" ]; then
|
|
34
|
+
CONFIG_SRC="$SCRIPT_DIR/../config/scheduler.json"
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
if [ ! -f "$BASECAMP_HOME/scheduler.json" ]; then
|
|
38
|
+
if [ -n "$CONFIG_SRC" ]; then
|
|
39
|
+
cp "$CONFIG_SRC" "$BASECAMP_HOME/scheduler.json"
|
|
40
|
+
echo " Created $BASECAMP_HOME/scheduler.json"
|
|
41
|
+
else
|
|
42
|
+
echo " Warning: config/scheduler.json not found, skipping config setup."
|
|
43
|
+
fi
|
|
44
|
+
else
|
|
45
|
+
echo " Scheduler config already exists, skipping."
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
# 3. Initialize state file
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
if [ ! -f "$BASECAMP_HOME/state.json" ]; then
|
|
53
|
+
echo '{ "tasks": {} }' > "$BASECAMP_HOME/state.json"
|
|
54
|
+
echo " Created $BASECAMP_HOME/state.json"
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# ---------------------------------------------------------------------------
|
|
58
|
+
# 4. Initialize default knowledge base
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
echo ""
|
|
62
|
+
if [ ! -d "$DEFAULT_KB" ]; then
|
|
63
|
+
echo "Initializing default knowledge base at $DEFAULT_KB ..."
|
|
64
|
+
SCHEDULER="$SCRIPT_DIR/../scheduler.js"
|
|
65
|
+
if command -v deno &>/dev/null && [ -f "$SCHEDULER" ]; then
|
|
66
|
+
deno run --allow-all "$SCHEDULER" --init "$DEFAULT_KB"
|
|
67
|
+
elif command -v node &>/dev/null && [ -f "$SCHEDULER" ]; then
|
|
68
|
+
node "$SCHEDULER" --init "$DEFAULT_KB"
|
|
69
|
+
else
|
|
70
|
+
echo " Neither deno nor node found, skipping KB initialization."
|
|
71
|
+
fi
|
|
72
|
+
else
|
|
73
|
+
echo "Basecamp already initialized at $DEFAULT_KB/"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
# 5. Install LaunchAgent
|
|
78
|
+
# ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
echo ""
|
|
81
|
+
echo "Installing background scheduler (LaunchAgent)..."
|
|
82
|
+
SCHEDULER="$SCRIPT_DIR/../scheduler.js"
|
|
83
|
+
if command -v deno &>/dev/null && [ -f "$SCHEDULER" ]; then
|
|
84
|
+
deno run --allow-all "$SCHEDULER" --install-launchd
|
|
85
|
+
elif command -v node &>/dev/null && [ -f "$SCHEDULER" ]; then
|
|
86
|
+
node "$SCHEDULER" --install-launchd
|
|
87
|
+
else
|
|
88
|
+
echo " Neither deno nor node found, skipping LaunchAgent install."
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# ---------------------------------------------------------------------------
|
|
92
|
+
# Summary
|
|
93
|
+
# ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
echo ""
|
|
96
|
+
echo "Done! Basecamp is installed."
|
|
97
|
+
echo ""
|
|
98
|
+
echo " Config: $BASECAMP_HOME/scheduler.json"
|
|
99
|
+
echo " Knowledge: $DEFAULT_KB/"
|
|
100
|
+
echo " Logs: $BASECAMP_HOME/logs/"
|
|
101
|
+
echo ""
|
|
102
|
+
echo "Next steps:"
|
|
103
|
+
echo " 1. Edit $DEFAULT_KB/USER.md with your name, email, and domain"
|
|
104
|
+
echo " 2. Edit $BASECAMP_HOME/scheduler.json to configure tasks"
|
|
105
|
+
echo " 3. Run the scheduler: deno run --allow-all scheduler.js --status"
|
|
106
|
+
echo " 4. Start the daemon: deno run --allow-all scheduler.js --install-launchd"
|
|
107
|
+
echo " 5. Open your KB: cd $DEFAULT_KB && claude"
|
|
108
|
+
echo ""
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<style>
|
|
5
|
+
body {
|
|
6
|
+
font-family:
|
|
7
|
+
-apple-system,
|
|
8
|
+
Helvetica Neue,
|
|
9
|
+
sans-serif;
|
|
10
|
+
padding: 20px;
|
|
11
|
+
color: #1d1d1f;
|
|
12
|
+
}
|
|
13
|
+
h1 {
|
|
14
|
+
font-size: 22px;
|
|
15
|
+
font-weight: 600;
|
|
16
|
+
margin-bottom: 16px;
|
|
17
|
+
}
|
|
18
|
+
p {
|
|
19
|
+
font-size: 14px;
|
|
20
|
+
line-height: 1.6;
|
|
21
|
+
color: #424245;
|
|
22
|
+
}
|
|
23
|
+
code {
|
|
24
|
+
font-family:
|
|
25
|
+
SF Mono,
|
|
26
|
+
Menlo,
|
|
27
|
+
monospace;
|
|
28
|
+
font-size: 13px;
|
|
29
|
+
background: #f5f5f7;
|
|
30
|
+
padding: 2px 6px;
|
|
31
|
+
border-radius: 4px;
|
|
32
|
+
}
|
|
33
|
+
.cmd {
|
|
34
|
+
margin: 8px 0 8px 16px;
|
|
35
|
+
}
|
|
36
|
+
.note {
|
|
37
|
+
font-size: 12px;
|
|
38
|
+
color: #86868b;
|
|
39
|
+
margin-top: 20px;
|
|
40
|
+
}
|
|
41
|
+
</style>
|
|
42
|
+
</head>
|
|
43
|
+
<body>
|
|
44
|
+
<h1>Basecamp is installed</h1>
|
|
45
|
+
<p>
|
|
46
|
+
The scheduler is running in the background and will start automatically on
|
|
47
|
+
login.
|
|
48
|
+
</p>
|
|
49
|
+
<p><strong>Next steps:</strong></p>
|
|
50
|
+
<p>1. Edit your identity file:</p>
|
|
51
|
+
<p class="cmd"><code>vim ~/Documents/Personal/USER.md</code></p>
|
|
52
|
+
<p>2. Configure scheduled tasks:</p>
|
|
53
|
+
<p class="cmd"><code>vim ~/.fit/basecamp/scheduler.json</code></p>
|
|
54
|
+
<p>3. Check scheduler status:</p>
|
|
55
|
+
<p class="cmd"><code>fit-basecamp --status</code></p>
|
|
56
|
+
<p>4. Open your knowledge base interactively:</p>
|
|
57
|
+
<p class="cmd"><code>cd ~/Documents/Personal && claude</code></p>
|
|
58
|
+
<p class="note">
|
|
59
|
+
To uninstall, run: <code>/usr/local/share/fit-basecamp/uninstall.sh</code>
|
|
60
|
+
</p>
|
|
61
|
+
</body>
|
|
62
|
+
</html>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<style>
|
|
5
|
+
body {
|
|
6
|
+
font-family:
|
|
7
|
+
-apple-system,
|
|
8
|
+
Helvetica Neue,
|
|
9
|
+
sans-serif;
|
|
10
|
+
padding: 20px;
|
|
11
|
+
color: #1d1d1f;
|
|
12
|
+
}
|
|
13
|
+
h1 {
|
|
14
|
+
font-size: 22px;
|
|
15
|
+
font-weight: 600;
|
|
16
|
+
margin-bottom: 16px;
|
|
17
|
+
}
|
|
18
|
+
p {
|
|
19
|
+
font-size: 14px;
|
|
20
|
+
line-height: 1.6;
|
|
21
|
+
color: #424245;
|
|
22
|
+
}
|
|
23
|
+
ul {
|
|
24
|
+
font-size: 14px;
|
|
25
|
+
line-height: 1.8;
|
|
26
|
+
color: #424245;
|
|
27
|
+
padding-left: 20px;
|
|
28
|
+
}
|
|
29
|
+
.note {
|
|
30
|
+
font-size: 12px;
|
|
31
|
+
color: #86868b;
|
|
32
|
+
margin-top: 20px;
|
|
33
|
+
}
|
|
34
|
+
</style>
|
|
35
|
+
</head>
|
|
36
|
+
<body>
|
|
37
|
+
<h1>Basecamp</h1>
|
|
38
|
+
<p>
|
|
39
|
+
Personal knowledge system with scheduled AI tasks. No server, no database.
|
|
40
|
+
just plain files, markdown, and Claude Code.
|
|
41
|
+
</p>
|
|
42
|
+
<p>This installer will:</p>
|
|
43
|
+
<ul>
|
|
44
|
+
<li>
|
|
45
|
+
Install the <code>fit-basecamp</code> binary to
|
|
46
|
+
<code>/usr/local/bin/</code>
|
|
47
|
+
</li>
|
|
48
|
+
<li>
|
|
49
|
+
Set up the scheduler configuration at <code>~/.fit/basecamp/</code>
|
|
50
|
+
</li>
|
|
51
|
+
<li>
|
|
52
|
+
Initialize a default knowledge base at
|
|
53
|
+
<code>~/Documents/Personal/</code>
|
|
54
|
+
</li>
|
|
55
|
+
<li>
|
|
56
|
+
Install a LaunchAgent so the scheduler runs automatically on login
|
|
57
|
+
</li>
|
|
58
|
+
</ul>
|
|
59
|
+
<p class="note">
|
|
60
|
+
Requires the Claude Code CLI (<code>claude</code>) to be installed and
|
|
61
|
+
authenticated.
|
|
62
|
+
</p>
|
|
63
|
+
</body>
|
|
64
|
+
</html>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Basecamp postinstall script — runs as root after macOS pkg installation.
|
|
4
|
+
#
|
|
5
|
+
# Sets up per-user config, default knowledge base, and LaunchAgent for the
|
|
6
|
+
# console user (the person who double-clicked the installer).
|
|
7
|
+
|
|
8
|
+
REAL_USER=$(/usr/bin/stat -f "%Su" /dev/console)
|
|
9
|
+
REAL_HOME=$(/usr/bin/dscl . -read "/Users/$REAL_USER" NFSHomeDirectory | /usr/bin/awk '{print $2}')
|
|
10
|
+
|
|
11
|
+
BASECAMP_HOME="$REAL_HOME/.fit/basecamp"
|
|
12
|
+
DEFAULT_KB="$REAL_HOME/Documents/Personal"
|
|
13
|
+
SHARE_DIR="/usr/local/share/fit-basecamp"
|
|
14
|
+
BINARY="/usr/local/bin/fit-basecamp"
|
|
15
|
+
|
|
16
|
+
# --- Config home -------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
/usr/bin/sudo -u "$REAL_USER" /bin/mkdir -p "$BASECAMP_HOME/logs"
|
|
19
|
+
|
|
20
|
+
if [ ! -f "$BASECAMP_HOME/scheduler.json" ] && [ -f "$SHARE_DIR/config/scheduler.json" ]; then
|
|
21
|
+
/usr/bin/sudo -u "$REAL_USER" /bin/cp "$SHARE_DIR/config/scheduler.json" "$BASECAMP_HOME/scheduler.json"
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
if [ ! -f "$BASECAMP_HOME/state.json" ]; then
|
|
25
|
+
echo '{ "tasks": {} }' | /usr/bin/sudo -u "$REAL_USER" /usr/bin/tee "$BASECAMP_HOME/state.json" > /dev/null
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# --- Default knowledge base --------------------------------------------------
|
|
29
|
+
|
|
30
|
+
if [ ! -d "$DEFAULT_KB" ]; then
|
|
31
|
+
/usr/bin/sudo -u "$REAL_USER" "$BINARY" --init "$DEFAULT_KB" 2>/dev/null || true
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# --- LaunchAgent (runs as user, not root) ------------------------------------
|
|
35
|
+
|
|
36
|
+
PLIST="$REAL_HOME/Library/LaunchAgents/com.fit-basecamp.scheduler.plist"
|
|
37
|
+
if [ -f "$PLIST" ]; then
|
|
38
|
+
# Upgrade: binary already replaced by pkg payload. Kill the old daemon and
|
|
39
|
+
# let KeepAlive restart it with the new binary. No plist rewrite needed.
|
|
40
|
+
/usr/bin/killall fit-basecamp 2>/dev/null || true
|
|
41
|
+
else
|
|
42
|
+
# Fresh install: create plist and load it.
|
|
43
|
+
/usr/bin/sudo -u "$REAL_USER" "$BINARY" --install-launchd 2>/dev/null || true
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
exit 0
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# Basecamp Uninstaller
|
|
5
|
+
#
|
|
6
|
+
# Removes the binary, LaunchAgent, and shared data installed by the .pkg.
|
|
7
|
+
# User data at ~/Documents/Personal/ and config at ~/.fit/basecamp/ are preserved.
|
|
8
|
+
|
|
9
|
+
APP_NAME="${1:-fit-basecamp}"
|
|
10
|
+
PLIST_NAME="${2:-com.fit-basecamp.scheduler}"
|
|
11
|
+
|
|
12
|
+
echo ""
|
|
13
|
+
echo "Basecamp Uninstaller"
|
|
14
|
+
echo "====================="
|
|
15
|
+
echo ""
|
|
16
|
+
|
|
17
|
+
# Remove LaunchAgent
|
|
18
|
+
PLIST="$HOME/Library/LaunchAgents/$PLIST_NAME.plist"
|
|
19
|
+
if [ -f "$PLIST" ]; then
|
|
20
|
+
launchctl unload "$PLIST" 2>/dev/null || true
|
|
21
|
+
rm -f "$PLIST"
|
|
22
|
+
echo " Removed LaunchAgent"
|
|
23
|
+
else
|
|
24
|
+
echo " LaunchAgent not found, skipping."
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Remove binary
|
|
28
|
+
if [ -f "/usr/local/bin/$APP_NAME" ]; then
|
|
29
|
+
sudo rm -f "/usr/local/bin/$APP_NAME"
|
|
30
|
+
echo " Removed /usr/local/bin/$APP_NAME"
|
|
31
|
+
else
|
|
32
|
+
echo " Binary not found at /usr/local/bin/$APP_NAME, skipping."
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Remove shared data (default config template, this uninstall script's installed copy)
|
|
36
|
+
if [ -d "/usr/local/share/fit-basecamp" ]; then
|
|
37
|
+
sudo rm -rf "/usr/local/share/fit-basecamp"
|
|
38
|
+
echo " Removed /usr/local/share/fit-basecamp/"
|
|
39
|
+
else
|
|
40
|
+
echo " Shared data not found, skipping."
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Forget pkg receipt
|
|
44
|
+
pkgutil --pkgs 2>/dev/null | grep -q "com.fit-basecamp.scheduler" && {
|
|
45
|
+
sudo pkgutil --forget "com.fit-basecamp.scheduler" >/dev/null 2>&1
|
|
46
|
+
echo " Removed installer receipt"
|
|
47
|
+
} || true
|
|
48
|
+
|
|
49
|
+
echo ""
|
|
50
|
+
echo "Basecamp uninstalled."
|
|
51
|
+
echo "Your data at ~/Documents/Personal/ has been preserved."
|
|
52
|
+
echo "Your config at ~/.fit/basecamp/ has been preserved."
|
|
53
|
+
echo ""
|
|
54
|
+
echo "To remove all data: rm -rf ~/Documents/Personal/"
|
|
55
|
+
echo "To remove all config: rm -rf ~/.fit/basecamp/"
|
|
56
|
+
echo ""
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
3
|
+
"permissions": {
|
|
4
|
+
"allow": [
|
|
5
|
+
"Read(~/Library/Mail/**)",
|
|
6
|
+
"Read(~/Library/Group Containers/group.com.apple.calendar/**)",
|
|
7
|
+
"Read(~/Library/Calendars/**)",
|
|
8
|
+
"Read(~/Desktop/**)",
|
|
9
|
+
"Read(~/Documents/**)",
|
|
10
|
+
"Read(~/Downloads/**)",
|
|
11
|
+
"Edit(~/Desktop/**)",
|
|
12
|
+
"Edit(~/Documents/**)",
|
|
13
|
+
"Edit(~/Downloads/**)",
|
|
14
|
+
"Read(~/.cache/fit/basecamp/**)",
|
|
15
|
+
"Edit(~/.cache/fit/basecamp/**)"
|
|
16
|
+
],
|
|
17
|
+
"deny": [
|
|
18
|
+
"Edit(~/Library/**)",
|
|
19
|
+
"Read(~/Pictures/**)",
|
|
20
|
+
"Read(~/Music/**)",
|
|
21
|
+
"Read(~/Movies/**)",
|
|
22
|
+
"Read(~/Public/**)",
|
|
23
|
+
"Read(~/.ssh/**)",
|
|
24
|
+
"Read(~/.aws/**)",
|
|
25
|
+
"Read(~/.gnupg/**)",
|
|
26
|
+
"Read(~/.config/**)",
|
|
27
|
+
"Read(~/.env)",
|
|
28
|
+
"Read(~/.env.*)"
|
|
29
|
+
],
|
|
30
|
+
"additionalDirectories": [
|
|
31
|
+
"~/Library/Mail",
|
|
32
|
+
"~/Library/Group Containers/group.com.apple.calendar",
|
|
33
|
+
"~/Library/Calendars",
|
|
34
|
+
"~/Desktop",
|
|
35
|
+
"~/Documents",
|
|
36
|
+
"~/Downloads",
|
|
37
|
+
"~/.cache/fit/basecamp"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-presentations
|
|
3
|
+
description: Generate PDF slide decks from user requests using Playwright to render HTML slides to PDF. Use when the user asks to create a presentation, slide deck, or pitch deck. Pulls context from the knowledge base for company info, project details, and people.
|
|
4
|
+
compatibility: Requires Node.js installed. Playwright is installed on first use.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Create Presentations
|
|
8
|
+
|
|
9
|
+
Generate PDF slide decks from user requests. Uses Playwright to render HTML
|
|
10
|
+
slides to PDF. Can pull context from the knowledge base for company info,
|
|
11
|
+
project details, and people.
|
|
12
|
+
|
|
13
|
+
## Trigger
|
|
14
|
+
|
|
15
|
+
Run when the user asks to create a presentation, slide deck, or pitch deck.
|
|
16
|
+
|
|
17
|
+
## Prerequisites
|
|
18
|
+
|
|
19
|
+
- Node.js installed
|
|
20
|
+
- Playwright will be installed on first use
|
|
21
|
+
|
|
22
|
+
## Inputs
|
|
23
|
+
|
|
24
|
+
- User's description of the presentation
|
|
25
|
+
- `knowledge/` — optional context about company, product, team, projects
|
|
26
|
+
|
|
27
|
+
## Outputs
|
|
28
|
+
|
|
29
|
+
- `~/Desktop/presentation.pdf` — the generated PDF presentation
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Workflow
|
|
34
|
+
|
|
35
|
+
1. Check `knowledge/` for relevant context about the company, product, team,
|
|
36
|
+
etc.
|
|
37
|
+
2. Ensure Playwright is installed:
|
|
38
|
+
`npm install playwright && npx playwright install chromium`
|
|
39
|
+
3. Create an HTML file at `/tmp/basecamp-presentation.html` with slides
|
|
40
|
+
(1280x720px each)
|
|
41
|
+
4. Include the required CSS from [references/slide.css](references/slide.css)
|
|
42
|
+
5. Run the conversion script:
|
|
43
|
+
|
|
44
|
+
node scripts/convert-to-pdf.js
|
|
45
|
+
|
|
46
|
+
6. Tell the user: "Your presentation is ready at ~/Desktop/presentation.pdf"
|
|
47
|
+
|
|
48
|
+
**Do NOT show HTML code to the user. Just create the PDF and deliver it.**
|
|
49
|
+
|
|
50
|
+
The conversion script accepts optional arguments:
|
|
51
|
+
|
|
52
|
+
node scripts/convert-to-pdf.js [input.html] [output.pdf]
|
|
53
|
+
|
|
54
|
+
Defaults: input = `/tmp/basecamp-presentation.html`, output =
|
|
55
|
+
`~/Desktop/presentation.pdf`
|
|
56
|
+
|
|
57
|
+
## PDF Rendering Rules
|
|
58
|
+
|
|
59
|
+
**These prevent rendering issues in PDF:**
|
|
60
|
+
|
|
61
|
+
1. **No layered elements** — Style content elements directly, no separate
|
|
62
|
+
background elements
|
|
63
|
+
2. **No box-shadow** — Use borders instead: `border: 1px solid #e5e7eb`
|
|
64
|
+
3. **Bullets via CSS only** — Use `li::before` pseudo-elements
|
|
65
|
+
4. **Content must fit** — Slides are 1280x720px with 60px padding. Safe area is
|
|
66
|
+
1160x600px. Use `overflow: hidden`
|
|
67
|
+
5. **No footers or headers** — No fixed/absolute positioned footer/header
|
|
68
|
+
elements
|
|
69
|
+
|
|
70
|
+
## Constraints
|
|
71
|
+
|
|
72
|
+
- Always use the knowledge base for context when available
|
|
73
|
+
- Output to `~/Desktop/presentation.pdf` unless user specifies otherwise
|
|
74
|
+
- Keep slides clean and readable — max 5-6 bullet points per slide
|
|
75
|
+
- Use consistent styling throughout
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* Required CSS for HTML slide decks rendered to PDF via Playwright.
|
|
2
|
+
*
|
|
3
|
+
* Include this in the <style> block of /tmp/basecamp-presentation.html.
|
|
4
|
+
* See scripts/convert-to-pdf.js for the rendering script.
|
|
5
|
+
*
|
|
6
|
+
* PDF rendering rules:
|
|
7
|
+
* - No layered elements — style content directly, no separate backgrounds
|
|
8
|
+
* - No box-shadow — use borders: border: 1px solid #e5e7eb
|
|
9
|
+
* - Bullets via CSS only — use li::before pseudo-elements
|
|
10
|
+
* - Content must fit — safe area is 1160x600px (1280x720 minus 60px padding)
|
|
11
|
+
* - No footers or headers — no fixed/absolute positioned elements
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
@page {
|
|
15
|
+
size: 1280px 720px;
|
|
16
|
+
margin: 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
html {
|
|
20
|
+
-webkit-print-color-adjust: exact !important;
|
|
21
|
+
print-color-adjust: exact !important;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.slide {
|
|
25
|
+
width: 1280px;
|
|
26
|
+
height: 720px;
|
|
27
|
+
padding: 60px;
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
page-break-after: always;
|
|
30
|
+
page-break-inside: avoid;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.slide:last-child {
|
|
34
|
+
page-break-after: auto;
|
|
35
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Convert HTML slides to PDF using Playwright.
|
|
2
|
+
//
|
|
3
|
+
// Usage: node scripts/convert-to-pdf.js [input.html] [output.pdf]
|
|
4
|
+
//
|
|
5
|
+
// Defaults:
|
|
6
|
+
// input: /tmp/basecamp-presentation.html
|
|
7
|
+
// output: ~/Desktop/presentation.pdf
|
|
8
|
+
//
|
|
9
|
+
// Requires: npm install playwright && npx playwright install chromium
|
|
10
|
+
|
|
11
|
+
const { chromium } = require("playwright");
|
|
12
|
+
const path = require("path");
|
|
13
|
+
|
|
14
|
+
const input = process.argv[2] || "/tmp/basecamp-presentation.html";
|
|
15
|
+
const output =
|
|
16
|
+
process.argv[3] || path.join(process.env.HOME, "Desktop", "presentation.pdf");
|
|
17
|
+
|
|
18
|
+
(async () => {
|
|
19
|
+
const browser = await chromium.launch();
|
|
20
|
+
const page = await browser.newPage();
|
|
21
|
+
await page.goto(`file://${path.resolve(input)}`, {
|
|
22
|
+
waitUntil: "networkidle",
|
|
23
|
+
});
|
|
24
|
+
await page.pdf({
|
|
25
|
+
path: output,
|
|
26
|
+
width: "1280px",
|
|
27
|
+
height: "720px",
|
|
28
|
+
printBackground: true,
|
|
29
|
+
});
|
|
30
|
+
await browser.close();
|
|
31
|
+
console.log(`Done: ${output}`);
|
|
32
|
+
})();
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doc-collab
|
|
3
|
+
description: Help the user create, edit, and refine documents in the knowledge base. Use when the user asks to create, edit, review, or collaborate on a document. Supports direct editing and approval-based workflows with knowledge base context for entity references.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Document Collaboration
|
|
7
|
+
|
|
8
|
+
Help the user create, edit, and refine documents in the knowledge base. Supports
|
|
9
|
+
direct editing and approval-based workflows. Always uses knowledge base context
|
|
10
|
+
for entity references.
|
|
11
|
+
|
|
12
|
+
## Trigger
|
|
13
|
+
|
|
14
|
+
Run when the user asks to create, edit, review, or collaborate on a document.
|
|
15
|
+
|
|
16
|
+
## Prerequisites
|
|
17
|
+
|
|
18
|
+
- Knowledge base directory exists
|
|
19
|
+
|
|
20
|
+
## Inputs
|
|
21
|
+
|
|
22
|
+
- User's editing instructions
|
|
23
|
+
- `knowledge/` — existing notes and documents
|
|
24
|
+
- Document to edit (user-specified or searched)
|
|
25
|
+
|
|
26
|
+
## Outputs
|
|
27
|
+
|
|
28
|
+
- Created or modified documents in `knowledge/` or user-specified location
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## First: Ask About Edit Mode
|
|
33
|
+
|
|
34
|
+
**Before doing anything, ask:** "Should I make edits directly, or show you
|
|
35
|
+
changes first for approval?"
|
|
36
|
+
|
|
37
|
+
- **Direct mode:** Make edits immediately, confirm after
|
|
38
|
+
- **Approval mode:** Show proposed changes, wait for approval
|
|
39
|
+
|
|
40
|
+
Follow their choice for the entire session.
|
|
41
|
+
|
|
42
|
+
## Core Principles
|
|
43
|
+
|
|
44
|
+
- **Re-read before every response** — the user may have edited the file manually
|
|
45
|
+
- **Be concise** — don't propose outlines unless asked
|
|
46
|
+
- **Don't assume** — if unclear, ask ONE simple question
|
|
47
|
+
- **Use knowledge context** — search knowledge base for mentioned entities, use
|
|
48
|
+
`[[wiki-links]]`
|
|
49
|
+
|
|
50
|
+
## Processing Flow
|
|
51
|
+
|
|
52
|
+
### Step 1: Find the Document
|
|
53
|
+
|
|
54
|
+
Search thoroughly before saying a document doesn't exist:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
rg -l -i "roadmap" knowledge/
|
|
58
|
+
find knowledge/ -iname "*roadmap*" 2>/dev/null
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**If found:** Read it and proceed. **If NOT found:** Ask "I couldn't find
|
|
62
|
+
[name]. Shall I create it?"
|
|
63
|
+
|
|
64
|
+
**Creating new documents:**
|
|
65
|
+
|
|
66
|
+
1. Ask: "Shall I create knowledge/[name].md?"
|
|
67
|
+
2. Create with just a title — don't pre-populate with structure
|
|
68
|
+
3. Ask: "What would you like in this?"
|
|
69
|
+
|
|
70
|
+
### Step 2: Understand the Request
|
|
71
|
+
|
|
72
|
+
**NEVER make unsolicited edits.** If the user hasn't specified what to change,
|
|
73
|
+
ask: "What would you like to change?"
|
|
74
|
+
|
|
75
|
+
Types of requests:
|
|
76
|
+
|
|
77
|
+
1. **Direct edits** — "Change the title", "Add a bullet about Y"
|
|
78
|
+
2. **Content generation** — "Write an intro", "Draft the summary"
|
|
79
|
+
3. **Review/feedback** — "What do you think?", "Is this clear?"
|
|
80
|
+
4. **Research-backed additions** — "Add context about [Person]"
|
|
81
|
+
5. **No clear request** — Read the doc, then ask: "What would you like to
|
|
82
|
+
change?"
|
|
83
|
+
|
|
84
|
+
### Step 3: Execute Changes
|
|
85
|
+
|
|
86
|
+
Make targeted edits — change only what's needed. Preserve the user's voice and
|
|
87
|
+
don't reorganize unless asked.
|
|
88
|
+
|
|
89
|
+
### Step 4: Confirm and Continue
|
|
90
|
+
|
|
91
|
+
- Briefly confirm: "Added the executive summary section"
|
|
92
|
+
- Ask: "What's next?"
|
|
93
|
+
- Don't read back the entire document unless asked
|
|
94
|
+
|
|
95
|
+
## Searching Knowledge for Context
|
|
96
|
+
|
|
97
|
+
When the user mentions people, companies, or projects:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
rg -l "Name" knowledge/
|
|
101
|
+
cat "knowledge/People/Person.md"
|
|
102
|
+
cat "knowledge/Organizations/Company.md"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use `[[wiki-links]]` to connect to other notes. Only link to notes that exist.
|
|
106
|
+
|
|
107
|
+
## Constraints
|
|
108
|
+
|
|
109
|
+
- Match the user's tone and style
|
|
110
|
+
- Make surgical edits — change only what's needed
|
|
111
|
+
- Preserve the user's voice — don't reorganize unless asked
|
|
112
|
+
- Only link to notes that exist — use `[[Person Name]]` for existing notes
|