@pingvinen/donna-assistant 0.4.0 → 0.6.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/README.md CHANGED
@@ -1,2 +1,131 @@
1
- # donna
2
- A Claude skill based personal assistant
1
+ # Donna
2
+
3
+ Your personal, digital version of Harvey Specter's amazing secretary.
4
+
5
+ Donna is an AI-powered personal assistant that manages the work that falls through the cracks — the 1:1 follow-ups, recurring process tasks, stakeholder requests, and self-initiated work that never makes it into Jira or Linear.
6
+
7
+ She lives inside your terminal. She knows your role, surfaces what needs attention each day, pulls data from your CLI tools, and captures tasks in seconds — all backed by plain markdown and git.
8
+
9
+ Donna is designed to be AI-agnostic, but currently only tested with [Claude Code](https://docs.anthropic.com/en/docs/claude-code). She works from any session, in any project — your tasks follow you wherever you work.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npx @pingvinen/donna-assistant
15
+ ```
16
+
17
+ The installer copies skill files into `~/.claude/commands/donna/` and shared runtime into `~/.donna/`. Run it again to upgrade.
18
+
19
+ **Requirements:** Node.js 18+, an AI coding assistant (tested with Claude Code)
20
+
21
+ ## Setup
22
+
23
+ ```
24
+ /donna:setup
25
+ ```
26
+
27
+ Donna will ask you for a **storage repo** — a git repository (local or remote) where all your tasks and daily files live. Everything is plain markdown, committed to git automatically. If you use [Obsidian](https://obsidian.md), you can open this repo as a vault for a free UI.
28
+
29
+ Then define your role so Donna can suggest recurring tasks relevant to your job:
30
+
31
+ ```
32
+ /donna:set-role
33
+ ```
34
+
35
+ ## Daily workflow
36
+
37
+ ### Start the day
38
+
39
+ ```
40
+ /donna:begin-the-day
41
+ ```
42
+
43
+ This is your morning ritual. Donna will:
44
+
45
+ - **Carry forward** open tasks from your last working day (handles weekends)
46
+ - **Surface recurring tasks** that are due today based on your role
47
+ - **Pull fresh data** from configured tools (GitHub PRs, Jira tickets, etc.)
48
+ - **Deduplicate** across all sources and give you a brief
49
+
50
+ ### Capture tasks throughout the day
51
+
52
+ ```
53
+ /donna:add-task Review Sarah's design doc before Thursday
54
+ ```
55
+
56
+ One command, zero prompts, committed to git in seconds. Can also be called without arguments for a more conversational capture.
57
+
58
+ ### Mark tasks done
59
+
60
+ ```
61
+ /donna:done design doc
62
+ ```
63
+
64
+ Fuzzy-matches by name. Run without arguments to pick from a list.
65
+
66
+ ### Refresh tool data mid-day
67
+
68
+ ```
69
+ /donna:run-tools
70
+ ```
71
+
72
+ Re-pulls data from all configured tools. New items appear, resolved items get closed automatically. Your manually-marked tasks always win.
73
+
74
+ ## External tools
75
+
76
+ Donna can pull tasks and status from CLI tools you already have installed. Register them with:
77
+
78
+ ```
79
+ /donna:add-tool gh
80
+ ```
81
+
82
+ Or call it without arguments — Donna will check your role and suggest tools typically associated with your job.
83
+
84
+ Donna verifies the tool is installed and authenticated, learns its capabilities, and asks what scope to query (which repos, projects, namespaces). Any CLI tool can be added — Donna uses the AI model's knowledge of well-known tools and parses `--help` output for everything else.
85
+
86
+ If a tool version is newer than what the AI model knows, Donna will inspect it to learn its current capabilities. You can also re-learn tools at any time:
87
+
88
+ ```
89
+ /donna:relearn-tools
90
+ ```
91
+
92
+ ## How state is stored
93
+
94
+ ```
95
+ <your-storage-repo>/
96
+ donna/
97
+ role.md # your job role definition
98
+ recurring.md # recurring task schedule
99
+ tools.md # registered tool configurations
100
+ daily/
101
+ 2026-03-16.md # today's tasks, tool data, notes
102
+ 2026-03-15.md
103
+ ...
104
+ ```
105
+
106
+ Every change is committed to git. Files are plain markdown with YAML frontmatter — human-readable, hand-editable, and version-controlled.
107
+
108
+ The storage repo is yours. Donna only writes to the `donna/` and `daily/` directories, so you're free to keep any other notes, files, or folder structures alongside it — great if you're already using the repo as an Obsidian vault or similar.
109
+
110
+ ## Idempotent by design
111
+
112
+ Most commands are safe to run again. Want to update your role? Run `/donna:set-role` again. Added a new tool mid-day? Run `/donna:begin-the-day` again to pull its data in. Re-running a command updates state rather than duplicating it.
113
+
114
+ ## All commands
115
+
116
+ | Command | What it does |
117
+ |---------|-------------|
118
+ | `/donna:setup` | First-time configuration (storage repo, directories) |
119
+ | `/donna:set-role` | Define your job role, get recurring task suggestions |
120
+ | `/donna:begin-the-day` | Morning brief with carry-forward, recurring tasks, tool data |
121
+ | `/donna:add-task` | Capture a task instantly |
122
+ | `/donna:done` | Mark a task complete |
123
+ | `/donna:add-tool` | Register an external CLI tool |
124
+ | `/donna:run-tools` | Refresh tool data mid-day |
125
+ | `/donna:relearn-tools` | Update tool knowledge after upgrades |
126
+ | `/donna:help` | Conversational troubleshooting for config, storage, or skill issues |
127
+ | `/donna:contribute-idea` | Submit a feature idea or bug report via GitHub Issues |
128
+
129
+ ## License
130
+
131
+ MIT
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ module.exports = {
4
+ version: "0.4.0",
5
+ description: "Queue standing file move to donna/ subfolder (runs on next skill use)",
6
+ up(ctx) {
7
+ // Standing files live in the user's storage repo, which is not accessible
8
+ // from the migration context. We write a pending flag to state.md so that
9
+ // workflows can detect and execute the move on next skill run.
10
+ const statePath = ctx.path.join(ctx.donnaDir, "state.md");
11
+
12
+ if (ctx.fs.existsSync(statePath)) {
13
+ const content = ctx.fs.readFileSync(statePath, "utf8");
14
+ if (content.includes("move-standing-files")) {
15
+ // Already queued — idempotent, nothing to do
16
+ return;
17
+ }
18
+ }
19
+
20
+ const pendingFlag = "---\npending_migrations:\n - move-standing-files\n---\n";
21
+ ctx.fs.writeFileSync(statePath, pendingFlag, "utf8");
22
+ },
23
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pingvinen/donna-assistant",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Donna - your AI powered personal assistant",
5
5
  "bin": {
6
6
  "donna-assistant": "./bin/donna-assistant"
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+
3
+ const output = require("./output.cjs");
4
+
5
+ /**
6
+ * Changelog data keyed by version string.
7
+ * Each entry has categories as keys and arrays of change descriptions as values.
8
+ */
9
+ const CHANGELOG = {
10
+ "0.5.0": {
11
+ "New skills": [
12
+ "donna:help — conversational troubleshooting and diagnostics",
13
+ "donna:contribute-idea — submit feature ideas via GitHub Issues",
14
+ ],
15
+ Improvements: [
16
+ "CONTRIBUTING.md developer guide added",
17
+ "Upgrade changelog shown during version bumps",
18
+ ],
19
+ },
20
+ };
21
+
22
+ /**
23
+ * Compare two semver strings. Returns true if a > b.
24
+ *
25
+ * @param {string} a - First version string
26
+ * @param {string} b - Second version string
27
+ * @returns {boolean}
28
+ */
29
+ function semverGt(a, b) {
30
+ const pa = a.split(".").map(Number);
31
+ const pb = b.split(".").map(Number);
32
+ for (let i = 0; i < 3; i++) {
33
+ if (pa[i] > pb[i]) return true;
34
+ if (pa[i] < pb[i]) return false;
35
+ }
36
+ return false;
37
+ }
38
+
39
+ /**
40
+ * Display changelog entries for versions between fromVersion (exclusive)
41
+ * and toVersion (inclusive).
42
+ *
43
+ * @param {string} fromVersion - Previous version (exclusive)
44
+ * @param {string} toVersion - New version (inclusive)
45
+ */
46
+ function displayChangelog(fromVersion, toVersion) {
47
+ const versionsToShow = Object.keys(CHANGELOG)
48
+ .filter((v) => semverGt(v, fromVersion) && !semverGt(v, toVersion))
49
+ .sort((a, b) => (semverGt(a, b) ? 1 : -1));
50
+
51
+ if (versionsToShow.length === 0) return;
52
+
53
+ console.log("");
54
+ output.info("What's new:");
55
+
56
+ for (const ver of versionsToShow) {
57
+ const entry = CHANGELOG[ver];
58
+ for (const [category, items] of Object.entries(entry)) {
59
+ output.info(` ${category}:`);
60
+ for (const item of items) {
61
+ const prefix = category.toLowerCase().includes("new") ? "+" : "\u00b7";
62
+ output.info(` ${prefix} ${item}`);
63
+ }
64
+ }
65
+ }
66
+
67
+ console.log("");
68
+ }
69
+
70
+ module.exports = { CHANGELOG, displayChangelog, semverGt };
package/src/installer.cjs CHANGED
@@ -8,6 +8,7 @@ const output = require("./output.cjs");
8
8
  const version = require("./version.cjs");
9
9
  const migrator = require("./migrator.cjs");
10
10
  const providers = require("./providers/index.cjs");
11
+ const changelog = require("./changelog.cjs");
11
12
 
12
13
  /**
13
14
  * Main installer orchestration.
@@ -50,6 +51,7 @@ async function run(options = {}) {
50
51
  // If upgrading (current version exists but differs)
51
52
  if (currentVersion && currentVersion !== packageVersion) {
52
53
  output.upgradeHeader(currentVersion, packageVersion);
54
+ changelog.displayChangelog(currentVersion, packageVersion);
53
55
  }
54
56
 
55
57
  // Run migrations
@@ -77,7 +79,7 @@ async function run(options = {}) {
77
79
  for (const provider of detected) {
78
80
  fs.cpSync(provider.stubSource, provider.stubTarget, { recursive: true });
79
81
  output.success(
80
- `Copied donna skills (setup, add-task, done, set-role, begin-the-day) to ${provider.stubTarget}`,
82
+ `Copied donna skills (setup, add-task, done, set-role, begin-the-day, add-tool, relearn-tools, run-tools, help, contribute-idea) to ${provider.stubTarget}`,
81
83
  );
82
84
  }
83
85
  } else {
package/src/output.cjs CHANGED
@@ -26,4 +26,9 @@ function migrationLine(desc) {
26
26
  console.log(` \u2713 ${desc}`);
27
27
  }
28
28
 
29
- module.exports = { banner, success, fail, info, upgradeHeader, migrationLine };
29
+ function changelogHeader() {
30
+ console.log("");
31
+ console.log(" What's new:");
32
+ }
33
+
34
+ module.exports = { banner, success, fail, info, upgradeHeader, migrationLine, changelogHeader };
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: donna:add-tool
3
+ description: Declare an external CLI tool and teach Donna its capabilities
4
+ allowed-tools:
5
+ - Read
6
+ - Write
7
+ - Bash
8
+ - AskUserQuestion
9
+ ---
10
+
11
+ <objective>
12
+ Run the Donna add-tool workflow. This command declares external CLI tools (like gh, jira, kubectl) and teaches Donna their capabilities so they can be surfaced in the daily brief.
13
+ </objective>
14
+
15
+ <execution_context>
16
+ @~/.donna/workflows/add-tool.md
17
+ </execution_context>
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: donna:contribute-idea
3
+ description: Submit a feature idea or bug report — checks for duplicates, then creates a GitHub Issue
4
+ allowed-tools:
5
+ - Read
6
+ - Bash
7
+ - AskUserQuestion
8
+ ---
9
+
10
+ <objective>
11
+ Run the Donna contribute-idea workflow. This command helps users submit feature ideas or bug reports by checking for duplicates against existing GitHub Issues and the project's pending todos, then creating a new issue if the idea is novel.
12
+ </objective>
13
+
14
+ <execution_context>
15
+ @~/.donna/workflows/contribute-idea.md
16
+ </execution_context>
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: donna:help
3
+ description: Conversational troubleshooting — diagnose issues with Donna's config, storage, skills, or tools
4
+ allowed-tools:
5
+ - Read
6
+ - Bash
7
+ - AskUserQuestion
8
+ ---
9
+
10
+ <objective>
11
+ Run the Donna help workflow. This command provides interactive troubleshooting by inspecting Donna's state and guiding the user through diagnosing and resolving issues.
12
+ </objective>
13
+
14
+ <execution_context>
15
+ @~/.donna/workflows/help.md
16
+ </execution_context>
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: donna:relearn-tools
3
+ description: Re-learn capabilities for tools whose installed version has changed
4
+ allowed-tools:
5
+ - Read
6
+ - Write
7
+ - Bash
8
+ ---
9
+
10
+ <objective>
11
+ Run the Donna relearn-tools workflow. This command checks each registered tool's installed version against its stored version and re-learns capabilities for tools that have been updated.
12
+ </objective>
13
+
14
+ <execution_context>
15
+ @~/.donna/workflows/relearn-tools.md
16
+ </execution_context>
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: donna:run-tools
3
+ description: Run external tools and pull fresh data into today's daily file
4
+ allowed-tools:
5
+ - Read
6
+ - Write
7
+ - Bash
8
+ ---
9
+
10
+ <objective>
11
+ Run the Donna run-tools workflow. This command executes all configured external tool commands, pulls fresh data, and smart-merges results into today's daily file, without running the full begin-the-day carry-forward and recurring task logic.
12
+ </objective>
13
+
14
+ <execution_context>
15
+ @~/.donna/workflows/run-tools.md
16
+ </execution_context>
@@ -21,6 +21,47 @@ Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (
21
21
  - Otherwise: do nothing.
22
22
  </step>
23
23
 
24
+ <step name="check-pending-migrations">
25
+ Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
26
+
27
+ For each entry in `pending_migrations`:
28
+
29
+ **`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
30
+
31
+ Run via Bash:
32
+ ```bash
33
+ STORAGE_REPO="<storage_repo>"
34
+ DONNA_DIR="$STORAGE_REPO/donna"
35
+ MOVED=0
36
+
37
+ mkdir -p "$DONNA_DIR"
38
+ for FILE in role.md recurring.md role-research.md; do
39
+ if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
40
+ mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
41
+ echo "Moved $FILE to donna/$FILE"
42
+ MOVED=$((MOVED + 1))
43
+ fi
44
+ done
45
+
46
+ echo "MOVED=$MOVED"
47
+ ```
48
+
49
+ If MOVED > 0, commit the move:
50
+ ```bash
51
+ git -C <storage_repo> add -A
52
+ git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
53
+ ```
54
+
55
+ If `auto_push` is true in config, also push.
56
+
57
+ After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
58
+ ```markdown
59
+ ---
60
+ pending_migrations: []
61
+ ---
62
+ ```
63
+ </step>
64
+
24
65
  <step name="get-description">
25
66
  The task description is provided as the argument to this command (e.g., `/donna:add-task buy milk`).
26
67
 
@@ -0,0 +1,261 @@
1
+ # Donna Add-Tool Workflow
2
+
3
+ <objective>
4
+ Declare an external CLI tool, verify its installation and authentication, learn its capabilities, and persist the result to tools.md in the storage repo.
5
+ </objective>
6
+
7
+ <step name="read-config">
8
+ Read `~/.config/donna/config.md`.
9
+
10
+ If the file does not exist, print:
11
+ ```
12
+ ✗ Donna is not configured. Run /donna:setup first.
13
+ ```
14
+ Stop.
15
+
16
+ Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (default: false) fields from the YAML frontmatter.
17
+
18
+ **Obsidian sync:** Check if `<storage_repo>/.obsidian/daily-notes.json` exists.
19
+ - If it exists and has a `folder` field that differs from `<daily_folder>`: update `<daily_folder>` to match Obsidian's value, and update `~/.config/donna/config.md` with the new `daily_folder`. Print `✓ Synced daily folder with Obsidian: <daily_folder>`.
20
+ - If `<storage_repo>/.obsidian/` exists but `daily-notes.json` does not exist or has no `folder` field: write `<storage_repo>/.obsidian/daily-notes.json` with `{"folder":"<daily_folder>"}`. Print `✓ Configured Obsidian daily notes to use <daily_folder>/`.
21
+ - Otherwise: do nothing.
22
+ </step>
23
+
24
+ <step name="check-pending-migrations">
25
+ Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
26
+
27
+ For each entry in `pending_migrations`:
28
+
29
+ **`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
30
+
31
+ Run via Bash:
32
+ ```bash
33
+ STORAGE_REPO="<storage_repo>"
34
+ DONNA_DIR="$STORAGE_REPO/donna"
35
+ MOVED=0
36
+
37
+ mkdir -p "$DONNA_DIR"
38
+ for FILE in role.md recurring.md role-research.md; do
39
+ if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
40
+ mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
41
+ echo "Moved $FILE to donna/$FILE"
42
+ MOVED=$((MOVED + 1))
43
+ fi
44
+ done
45
+
46
+ echo "MOVED=$MOVED"
47
+ ```
48
+
49
+ If MOVED > 0, commit the move:
50
+ ```bash
51
+ git -C <storage_repo> add -A
52
+ git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
53
+ ```
54
+
55
+ If `auto_push` is true in config, also push.
56
+
57
+ After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
58
+ ```markdown
59
+ ---
60
+ pending_migrations: []
61
+ ---
62
+ ```
63
+ </step>
64
+
65
+ <step name="detect-noted-tools">
66
+ Read `<storage_repo>/donna/role.md` and `<storage_repo>/donna/role-research.md` with the Read tool. If either file does not exist, skip reading that file.
67
+
68
+ Look for lines containing tool names noted by set-role's approve-tools step. These lines follow the pattern `✓ Noted: <ToolName>` or `- Noted: <ToolName>`. Collect the noted tool names as `<noted_tools>`.
69
+
70
+ If `<noted_tools>` has more than one entry and no specific tool name was provided as argument to the command, offer batch mode via AskUserQuestion:
71
+
72
+ ```
73
+ Set-role noted these tools: <list>. Configure all of them now? (yes/no)
74
+ ```
75
+
76
+ If yes, set batch mode active and process each tool sequentially through steps 4–11 below. If no, proceed to ask-tool-name for a single tool.
77
+ </step>
78
+
79
+ <step name="ask-tool-name">
80
+ If a tool name was provided as argument (e.g. `/donna:add-tool gh`), use it directly. Otherwise, use AskUserQuestion:
81
+
82
+ ```
83
+ What tool would you like to add? (e.g. gh, jira, kubectl)
84
+ ```
85
+
86
+ Store the answer as `<tool_name>`.
87
+
88
+ Resolve the CLI command — default to the tool name itself. If the tool name is in `<noted_tools>`, pre-fill any context from set-role notes. Use AskUserQuestion to confirm or override the CLI command:
89
+
90
+ ```
91
+ CLI command for <tool_name>? (default: <tool_name>)
92
+ ```
93
+
94
+ If the user presses enter without typing, use the default. Store the confirmed CLI command as `<command>`.
95
+ </step>
96
+
97
+ <step name="verify-installation">
98
+ Run via Bash:
99
+ ```bash
100
+ which <command> && echo "INSTALLED=true" || echo "INSTALLED=false"
101
+ ```
102
+
103
+ If INSTALLED=false, print:
104
+ ```
105
+ ! <command> is not installed. You can still save it, but data pulling won't work until you install it.
106
+ ```
107
+ Continue (do not stop — user may want to pre-configure).
108
+
109
+ If INSTALLED=true, run:
110
+ ```bash
111
+ <command> --version 2>/dev/null | head -1
112
+ ```
113
+
114
+ Store the output as `<version>`. If the command does not support `--version`, store `<version>` as `unknown`.
115
+ </step>
116
+
117
+ <step name="auth-test">
118
+ For well-known tools, run the appropriate auth test via Bash with a 10-second timeout:
119
+
120
+ - `gh`: `timeout 10 gh api user --jq '.login' 2>&1`
121
+ - `jira`: `timeout 10 jira me 2>&1`
122
+ - `kubectl`: `timeout 10 kubectl auth whoami 2>&1`
123
+ - Other tools: skip auth test, print `ℹ No known auth test for <command>. Verify manually.`
124
+
125
+ On success (exit 0): print `✓ Authenticated as <output>`.
126
+
127
+ On failure (non-zero exit): print `! Authentication failed for <command>. Fix: <tool-specific fix instructions>`.
128
+
129
+ Fix instructions per tool:
130
+ - `gh` → run `gh auth login`
131
+ - `jira` → run `jira init`
132
+ - `kubectl` → check your kubeconfig
133
+
134
+ Continue (do not stop — user may want to save the tool despite auth issues).
135
+ </step>
136
+
137
+ <step name="ask-scope">
138
+ Ask the user to define the scope/context for this tool. Different tools need different scope:
139
+
140
+ - **gh**: Which GitHub orgs or repos to pull from (e.g., `mycompany`, `mycompany/api mycompany/web`)
141
+ - **jira**: Which Jira project(s) or board(s) (e.g., `AUTH`, `AUTH PLAT`)
142
+ - **kubectl**: Which namespace(s) or cluster(s) (e.g., `production`, `staging production`)
143
+ - **Other tools**: Any relevant filtering context
144
+
145
+ Use AskUserQuestion:
146
+ ```
147
+ What scope should Donna use for <tool_name>?
148
+ (e.g., for gh: which orgs/repos; for jira: which projects)
149
+ Leave blank for no filtering.
150
+ ```
151
+
152
+ Store the answer as `<scope>`. If blank, set to empty string.
153
+ </step>
154
+
155
+ <step name="learn-capabilities">
156
+ Determine if the tool is well-known (gh, jira, kubectl) or unknown. For well-known tools, synthesize capabilities from training data. Do NOT parse --help for well-known tools.
157
+
158
+ **gh (GitHub CLI) — training data baseline:**
159
+
160
+ If `<scope>` is set, add `--owner=<org>` to each search command for each org in scope (space-separated). If scope contains specific repos (format `owner/repo`), use `--repo=<owner/repo>` instead. If scope is empty, do not add owner/repo filters.
161
+
162
+ - list-assigned-prs: `gh search prs --assignee=@me --state=open --json number,title,url --limit 20`
163
+ - list-review-requests: `gh search prs --review-requested=@me --state=open --json number,title,url --limit 20`
164
+ - list-assigned-issues: `gh search issues --assignee=@me --state=open --json number,title,url --limit 20`
165
+
166
+ **jira (ankitpokhrel/jira-cli) — training data baseline:**
167
+
168
+ If `<scope>` is set, add `-p<project>` to each command for each project in scope (space-separated). If scope is empty, do not add project filters.
169
+
170
+ - list-sprint-issues: `jira sprint list --current -a$(jira me) --plain`
171
+ - list-my-issues: `jira issue list -a$(jira me) --plain`
172
+
173
+ **kubectl — training data baseline:**
174
+
175
+ If `<scope>` is set, replace `--all-namespaces` with `-n <namespace>` for each namespace in scope. If scope is empty, keep `--all-namespaces`.
176
+
177
+ - list-pods: `kubectl get pods --all-namespaces --field-selector=status.phase!=Succeeded -o wide`
178
+ - list-failing: `kubectl get pods --all-namespaces --field-selector=status.phase=Failed -o wide`
179
+
180
+ For **unknown tools**, run `<command> --help 2>&1 | head -80` via Bash and use Claude's understanding to identify 3–5 capabilities relevant to daily task management. If `<scope>` is set, incorporate the scope into the CLI invocations where appropriate. Format each as `name: <cli invocation>`.
181
+
182
+ Store the full list as `<available_capabilities>`.
183
+ </step>
184
+
185
+ <step name="select-capabilities">
186
+ Present `<available_capabilities>` to the user via AskUserQuestion with multi-select. All capabilities are checked by default. The question text:
187
+
188
+ ```
189
+ Which capabilities should Donna use for <tool_name>? (deselect any you don't want, or type additional ones)
190
+ ```
191
+
192
+ If the user types additional capabilities as free text, parse them into the same `name: command` format.
193
+
194
+ Store the final selections as `<selected_capabilities>`.
195
+ </step>
196
+
197
+ <step name="write-tools-md">
198
+ Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist, create it with:
199
+ ```markdown
200
+ ---
201
+ # tools.md — managed by donna:add-tool
202
+ ---
203
+ ```
204
+
205
+ Upsert (not overwrite) the tool's section. Each tool section has this format:
206
+ ```markdown
207
+ ## <tool_name>
208
+
209
+ - command: <command>
210
+ - version: <version>
211
+ - learned: <today's date YYYY-MM-DD>
212
+ - auth_test: <auth_test_command or "none">
213
+ - scope: <scope or "none">
214
+
215
+ ### Capabilities
216
+ - <capability_name>: <cli_invocation>
217
+ ```
218
+
219
+ If a section for this tool already exists in tools.md, replace it entirely. Write the full file back with the Write tool. Preserve all other tool sections unchanged.
220
+ </step>
221
+
222
+ <step name="git-commit">
223
+ Run via Bash:
224
+ ```bash
225
+ git -C <storage_repo> add -A
226
+ ```
227
+
228
+ Check whether there is anything to commit:
229
+ ```bash
230
+ git -C <storage_repo> status --porcelain
231
+ ```
232
+
233
+ If the output is empty, skip the commit and continue.
234
+
235
+ Otherwise, run:
236
+ ```bash
237
+ git -C <storage_repo> commit -m "donna(add-tool): added <tool_name>"
238
+ ```
239
+
240
+ If `auto_push` is true in config, also run:
241
+ ```bash
242
+ git -C <storage_repo> push
243
+ ```
244
+ </step>
245
+
246
+ <step name="confirm">
247
+ Print:
248
+ ```
249
+ ✓ Added <tool_name> to tools registry
250
+ Command: <command>
251
+ Version: <version>
252
+ Capabilities: <count> configured
253
+
254
+ Run /donna:begin-the-day to see tool data in your daily brief.
255
+ ```
256
+
257
+ If in batch mode, repeat steps ask-tool-name through confirm for each remaining tool in `<noted_tools>`, then print a final summary:
258
+ ```
259
+ ✓ Configured <N> tools: <tool_name_1>, <tool_name_2>, ...
260
+ ```
261
+ </step>