@forwardimpact/basecamp 2.9.2 → 2.9.4
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forwardimpact/basecamp",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.4",
|
|
4
4
|
"description": "Claude Code-native personal knowledge system with autonomous agents",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"node": ">=18.0.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"
|
|
33
|
+
"read-excel-file": "^7.0.3"
|
|
34
34
|
},
|
|
35
35
|
"publishConfig": {
|
|
36
36
|
"access": "public"
|
|
@@ -28,9 +28,9 @@ Run this skill:
|
|
|
28
28
|
|
|
29
29
|
- A Workday requisition export file (`.xlsx`) accessible on the filesystem
|
|
30
30
|
(typically in `~/Downloads/`)
|
|
31
|
-
- The `
|
|
31
|
+
- The `read-excel-file` npm package installed in the KB root:
|
|
32
32
|
```bash
|
|
33
|
-
npm install
|
|
33
|
+
npm install read-excel-file
|
|
34
34
|
```
|
|
35
35
|
- User identity configured in `USER.md`
|
|
36
36
|
|
|
@@ -135,9 +135,9 @@ Names may include parenthetical annotations:
|
|
|
135
135
|
|
|
136
136
|
1. Read `USER.md` to get the user's name, email, and domain.
|
|
137
137
|
2. Confirm the XLSX file path with the user (or use the provided path).
|
|
138
|
-
3. Ensure the `
|
|
138
|
+
3. Ensure the `read-excel-file` package is installed:
|
|
139
139
|
```bash
|
|
140
|
-
npm list
|
|
140
|
+
npm list read-excel-file 2>/dev/null || npm install read-excel-file
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
## Step 1: Parse the Export
|
|
@@ -19,11 +19,9 @@
|
|
|
19
19
|
* node scripts/parse-workday.mjs <path-to-xlsx> --summary
|
|
20
20
|
* node scripts/parse-workday.mjs -h|--help
|
|
21
21
|
*
|
|
22
|
-
* Requires: npm install
|
|
22
|
+
* Requires: npm install read-excel-file
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import { readFileSync } from "node:fs";
|
|
26
|
-
|
|
27
25
|
if (
|
|
28
26
|
process.argv.includes("-h") ||
|
|
29
27
|
process.argv.includes("--help") ||
|
|
@@ -39,16 +37,16 @@ Usage:
|
|
|
39
37
|
Output (JSON):
|
|
40
38
|
{ requisition: { id, title, ... }, candidates: [ { name, ... }, ... ] }
|
|
41
39
|
|
|
42
|
-
Requires: npm install
|
|
40
|
+
Requires: npm install read-excel-file`);
|
|
43
41
|
process.exit(process.argv.length < 3 ? 1 : 0);
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
let
|
|
44
|
+
let readXlsxFile;
|
|
47
45
|
try {
|
|
48
|
-
|
|
46
|
+
readXlsxFile = (await import("read-excel-file/node")).default;
|
|
49
47
|
} catch {
|
|
50
48
|
console.error(
|
|
51
|
-
"Error:
|
|
49
|
+
"Error: read-excel-file package not found. Install it first:\n npm install read-excel-file",
|
|
52
50
|
);
|
|
53
51
|
process.exit(1);
|
|
54
52
|
}
|
|
@@ -56,13 +54,20 @@ try {
|
|
|
56
54
|
const filePath = process.argv[2];
|
|
57
55
|
const summaryMode = process.argv.includes("--summary");
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
/** Read a sheet by number (1-indexed) or name, returning rows as arrays of strings. */
|
|
58
|
+
async function readSheet(file, sheet) {
|
|
59
|
+
const rows = await readXlsxFile(file, { sheet });
|
|
60
|
+
// Normalise null cells to empty strings to match previous behaviour
|
|
61
|
+
return rows.map((row) => row.map((cell) => (cell == null ? "" : cell)));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Get sheet names to find the candidates sheet
|
|
65
|
+
const sheets = await readXlsxFile(filePath, { getSheets: true });
|
|
66
|
+
const sheetNames = sheets.map((s) => s.name);
|
|
61
67
|
|
|
62
68
|
// --- Sheet 1: Requisition metadata ---
|
|
63
69
|
|
|
64
|
-
const
|
|
65
|
-
const sheet1Rows = XLSX.utils.sheet_to_json(ws1, { header: 1, defval: "" });
|
|
70
|
+
const sheet1Rows = await readSheet(filePath, 1);
|
|
66
71
|
|
|
67
72
|
/** Extract the requisition ID and title from the header row. */
|
|
68
73
|
function parseReqHeader(headerText) {
|
|
@@ -113,10 +118,9 @@ const requisition = {
|
|
|
113
118
|
// - Old format: 3+ sheets, candidates on a sheet named "Candidates" or Sheet3
|
|
114
119
|
// - New format: 2 sheets, candidates on Sheet2
|
|
115
120
|
const candSheetName =
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
const candRows = XLSX.utils.sheet_to_json(ws3, { header: 1, defval: "" });
|
|
121
|
+
sheetNames.find((n) => n.toLowerCase() === "candidates") ||
|
|
122
|
+
sheetNames[Math.min(2, sheetNames.length - 1)];
|
|
123
|
+
const candRows = await readSheet(filePath, candSheetName);
|
|
120
124
|
|
|
121
125
|
// Find the header row dynamically — look for a row containing "Stage"
|
|
122
126
|
// Old format: row 3 (index 2). New format: row 8 (index 7).
|
|
@@ -199,7 +203,7 @@ function parseName(raw) {
|
|
|
199
203
|
const match = name.match(/^(.+?)\s*\(([^)]+)\)\s*$/);
|
|
200
204
|
if (match) {
|
|
201
205
|
const annotation = match[2].trim();
|
|
202
|
-
let ie
|
|
206
|
+
let ie;
|
|
203
207
|
if (/prior\s*worker/i.test(annotation)) ie = "External (Prior Worker)";
|
|
204
208
|
else if (/internal/i.test(annotation)) ie = "Internal";
|
|
205
209
|
else ie = annotation;
|
package/README.md
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
# @forwardimpact/basecamp
|
|
2
|
-
|
|
3
|
-
A personal knowledge system that runs as scheduled Claude Code tasks. No server,
|
|
4
|
-
no database — just plain files, markdown, and the `claude` CLI. Packaged as a
|
|
5
|
-
native macOS app bundle (`Basecamp.app`) with TCC-compliant process management.
|
|
6
|
-
|
|
7
|
-
Part of the [Forward Impact](https://www.forwardimpact.team) monorepo.
|
|
8
|
-
|
|
9
|
-
## Architecture
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
Basecamp.app/ # macOS app bundle
|
|
13
|
-
└── Contents/
|
|
14
|
-
├── Info.plist # Bundle metadata (LSUIElement)
|
|
15
|
-
├── MacOS/
|
|
16
|
-
│ ├── Basecamp # Swift launcher (TCC responsible)
|
|
17
|
-
│ └── fit-basecamp # Deno scheduler (child process)
|
|
18
|
-
└── Resources/
|
|
19
|
-
├── config/scheduler.json # Default config
|
|
20
|
-
└── template/ # KB template
|
|
21
|
-
|
|
22
|
-
~/.fit/basecamp/ # Scheduler home (user config)
|
|
23
|
-
├── scheduler.json # Task definitions
|
|
24
|
-
├── state.json # Task run state
|
|
25
|
-
├── basecamp.sock # IPC socket
|
|
26
|
-
└── logs/ # Scheduler logs
|
|
27
|
-
|
|
28
|
-
~/Documents/Personal/ # Default personal knowledge base
|
|
29
|
-
├── CLAUDE.md # Claude Code instructions for this KB
|
|
30
|
-
├── knowledge/ # The knowledge graph
|
|
31
|
-
│ ├── People/
|
|
32
|
-
│ ├── Organizations/
|
|
33
|
-
│ ├── Projects/
|
|
34
|
-
│ └── Topics/
|
|
35
|
-
├── .claude/skills/ # Claude Code skill files
|
|
36
|
-
└── drafts/ # Email drafts
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### Process Tree
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
Basecamp (Swift launcher, CFBundleExecutable, TCC responsible)
|
|
43
|
-
├── fit-basecamp --daemon (Deno scheduler, spawned via posix_spawn)
|
|
44
|
-
│ └── claude --print ... (spawned via posix_spawn FFI)
|
|
45
|
-
└── [status menu UI] (AppKit menu bar, in-process)
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
The Swift launcher is the main executable and TCC responsible process. It spawns
|
|
49
|
-
the Deno scheduler via `posix_spawn` so child processes inherit TCC attributes.
|
|
50
|
-
Users grant Calendar, Contacts, and other permissions once to Basecamp.app.
|
|
51
|
-
|
|
52
|
-
## Install from Package
|
|
53
|
-
|
|
54
|
-
1. Double-click `fit-basecamp-<version>.pkg`
|
|
55
|
-
2. Follow the installer prompts
|
|
56
|
-
|
|
57
|
-
The installer places `Basecamp.app` in `/Applications/` and initializes
|
|
58
|
-
`~/Documents/Personal/` as the default knowledge base.
|
|
59
|
-
|
|
60
|
-
After installing, open Basecamp from `/Applications/`. It runs as a menu bar app
|
|
61
|
-
— use "Quit Basecamp" from the status menu to stop it.
|
|
62
|
-
|
|
63
|
-
To uninstall, run `just uninstall` from the source tree.
|
|
64
|
-
|
|
65
|
-
## Install from Source
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
cd products/basecamp
|
|
69
|
-
|
|
70
|
-
# Run the scheduler in dev mode
|
|
71
|
-
just daemon
|
|
72
|
-
|
|
73
|
-
# Or initialize a new KB
|
|
74
|
-
just init ~/Documents/Personal
|
|
75
|
-
|
|
76
|
-
# Configure your identity
|
|
77
|
-
vi ~/Documents/Personal/USER.md
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
## Building
|
|
81
|
-
|
|
82
|
-
Requires [Deno](https://deno.com) >= 2.x and Xcode Command Line Tools.
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
# Build scheduler + launcher binaries
|
|
86
|
-
just build
|
|
87
|
-
|
|
88
|
-
# Build + assemble Basecamp.app
|
|
89
|
-
just build-app
|
|
90
|
-
|
|
91
|
-
# Build + assemble + .pkg installer
|
|
92
|
-
just pkg
|
|
93
|
-
|
|
94
|
-
# Or via npm:
|
|
95
|
-
npm run build # binaries only
|
|
96
|
-
npm run build:app # + Basecamp.app
|
|
97
|
-
npm run build:pkg # + .pkg installer
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Output goes to `dist/`:
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
dist/
|
|
104
|
-
├── fit-basecamp # Deno scheduler binary
|
|
105
|
-
├── Basecamp # Swift launcher binary
|
|
106
|
-
└── Basecamp.app/ # Assembled app bundle
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Multiple Knowledge Bases
|
|
110
|
-
|
|
111
|
-
The scheduler can run tasks across multiple knowledge bases. Each KB is an
|
|
112
|
-
independent directory with its own CLAUDE.md, skills, and knowledge graph.
|
|
113
|
-
|
|
114
|
-
### Adding a new KB
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
# Initialize a new knowledge base
|
|
118
|
-
deno run --allow-all src/basecamp.js --init ~/Documents/Team
|
|
119
|
-
|
|
120
|
-
# Edit the scheduler config to register it
|
|
121
|
-
vi ~/.fit/basecamp/scheduler.json
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Scheduler config format
|
|
125
|
-
|
|
126
|
-
`~/.fit/basecamp/scheduler.json`:
|
|
127
|
-
|
|
128
|
-
```json
|
|
129
|
-
{
|
|
130
|
-
"tasks": {
|
|
131
|
-
"sync-personal-mail": {
|
|
132
|
-
"kb": "~/Documents/Personal",
|
|
133
|
-
"schedule": { "type": "interval", "minutes": 5 },
|
|
134
|
-
"enabled": true,
|
|
135
|
-
"skill": "sync-apple-mail",
|
|
136
|
-
"prompt": "Sync Apple Mail."
|
|
137
|
-
},
|
|
138
|
-
"sync-team-calendar": {
|
|
139
|
-
"kb": "~/Documents/Team",
|
|
140
|
-
"schedule": { "type": "interval", "minutes": 10 },
|
|
141
|
-
"enabled": true,
|
|
142
|
-
"skill": "sync-apple-calendar",
|
|
143
|
-
"prompt": "Sync Apple Calendar."
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### Task fields
|
|
150
|
-
|
|
151
|
-
| Field | Required | Description |
|
|
152
|
-
| ---------- | -------- | --------------------------------------------------------------- |
|
|
153
|
-
| `kb` | yes | Path to the knowledge base directory (supports `~`) |
|
|
154
|
-
| `schedule` | yes | When to run (`interval`, `cron`, or `once`) |
|
|
155
|
-
| `prompt` | yes | The prompt sent to Claude |
|
|
156
|
-
| `enabled` | no | Set to `false` to disable. Default: `true` |
|
|
157
|
-
| `agent` | no | Claude sub-agent name (passed as `--agent`) |
|
|
158
|
-
| `skill` | no | Skill name (matches `.claude/skills/<name>/SKILL.md` in the KB) |
|
|
159
|
-
|
|
160
|
-
### Schedule types
|
|
161
|
-
|
|
162
|
-
```json
|
|
163
|
-
{ "type": "interval", "minutes": 5 }
|
|
164
|
-
{ "type": "cron", "expression": "0 8 * * *" }
|
|
165
|
-
{ "type": "once", "runAt": "2025-02-12T10:00:00Z" }
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
## Updating
|
|
169
|
-
|
|
170
|
-
When you upgrade Basecamp (install a new `.pkg`), the installer automatically
|
|
171
|
-
runs `--update` on all configured knowledge bases. This pushes the latest
|
|
172
|
-
`CLAUDE.md`, skills, and agents into each KB without touching your data.
|
|
173
|
-
|
|
174
|
-
You can also run it manually at any time:
|
|
175
|
-
|
|
176
|
-
```bash
|
|
177
|
-
# Update all configured knowledge bases
|
|
178
|
-
/Applications/Basecamp.app/Contents/MacOS/fit-basecamp --update
|
|
179
|
-
|
|
180
|
-
# Update a specific knowledge base
|
|
181
|
-
/Applications/Basecamp.app/Contents/MacOS/fit-basecamp --update ~/Documents/Personal
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
The update merges `.claude/settings.json` non-destructively — new entries are
|
|
185
|
-
added but your existing permissions are preserved.
|
|
186
|
-
|
|
187
|
-
## CLI Reference
|
|
188
|
-
|
|
189
|
-
```
|
|
190
|
-
fit-basecamp Run due tasks once and exit
|
|
191
|
-
fit-basecamp --daemon Run continuously (poll every 60s)
|
|
192
|
-
fit-basecamp --run <task> Run a specific task immediately
|
|
193
|
-
fit-basecamp --init <path> Initialize a new knowledge base
|
|
194
|
-
fit-basecamp --update [path] Update KB skills, agents, and CLAUDE.md
|
|
195
|
-
fit-basecamp --status Show knowledge bases and task status
|
|
196
|
-
fit-basecamp --validate Validate agents and skills exist
|
|
197
|
-
fit-basecamp --help Show this help
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
When running from source, use `deno run --allow-all src/basecamp.js` or
|
|
201
|
-
`just run` instead of `fit-basecamp`.
|
|
202
|
-
|
|
203
|
-
## Skills
|
|
204
|
-
|
|
205
|
-
Skills are Claude Code-native `SKILL.md` files that are auto-discovered from
|
|
206
|
-
`.claude/skills/<name>/SKILL.md` inside each knowledge base. The default KB
|
|
207
|
-
ships with these skills:
|
|
208
|
-
|
|
209
|
-
| Skill | Directory | Purpose |
|
|
210
|
-
| ---------------------- | ---------------------- | ---------------------------------------------- |
|
|
211
|
-
| Sync Apple Mail | `sync-apple-mail` | Sync Apple Mail threads via SQLite |
|
|
212
|
-
| Sync Apple Calendar | `sync-apple-calendar` | Sync Apple Calendar events via SQLite |
|
|
213
|
-
| Extract Entities | `extract-entities` | Process synced data into knowledge graph notes |
|
|
214
|
-
| Draft Emails | `draft-emails` | Draft email responses using knowledge context |
|
|
215
|
-
| Meeting Prep | `meeting-prep` | Prepare briefings for upcoming meetings |
|
|
216
|
-
| Create Presentations | `create-presentations` | Create slide decks as PDF |
|
|
217
|
-
| Document Collaboration | `doc-collab` | Document creation and collaboration |
|
|
218
|
-
| Organize Files | `organize-files` | File organization and cleanup |
|
|
219
|
-
|
|
220
|
-
## Requirements
|
|
221
|
-
|
|
222
|
-
- Claude CLI (`claude`) installed and authenticated
|
|
223
|
-
- macOS 13+ (Ventura or later)
|
|
224
|
-
- Xcode Command Line Tools (for building the Swift launcher)
|
|
225
|
-
- Deno >= 2.x (for building the standalone binary)
|
|
226
|
-
|
|
227
|
-
## License
|
|
228
|
-
|
|
229
|
-
Apache-2.0
|