@orderful/droid 0.40.1 → 0.42.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/.claude-plugin/plugin.json +4 -0
- package/CHANGELOG.md +25 -0
- package/dist/bin/droid.js +216 -23
- package/dist/commands/integrations.d.ts.map +1 -1
- package/dist/commands/tui/components/IntegrationsDetails.d.ts +7 -1
- package/dist/commands/tui/components/IntegrationsDetails.d.ts.map +1 -1
- package/dist/commands/tui.d.ts.map +1 -1
- package/dist/integrations/atlassian/references/setup.md +59 -0
- package/dist/integrations/github/index.d.ts +6 -0
- package/dist/integrations/github/index.d.ts.map +1 -0
- package/dist/integrations/github/index.ts +17 -0
- package/dist/integrations/github/references/setup.md +61 -0
- package/dist/integrations/granola/references/setup.md +54 -0
- package/dist/lib/types.d.ts +12 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/tools/meeting/.claude-plugin/plugin.json +22 -0
- package/dist/tools/meeting/TOOL.yaml +15 -0
- package/dist/tools/meeting/commands/meeting.md +35 -0
- package/dist/tools/meeting/skills/meeting/SKILL.md +105 -0
- package/dist/tools/meeting/skills/meeting/references/export-workflow.md +87 -0
- package/dist/tools/share/.claude-plugin/plugin.json +22 -0
- package/dist/tools/share/TOOL.yaml +17 -0
- package/dist/tools/share/commands/share.md +32 -0
- package/dist/tools/share/skills/share/SKILL.md +211 -0
- package/package.json +1 -1
- package/src/commands/integrations.ts +45 -0
- package/src/commands/tui/components/IntegrationsDetails.tsx +185 -4
- package/src/commands/tui.tsx +63 -20
- package/src/integrations/atlassian/references/setup.md +59 -0
- package/src/integrations/github/index.ts +17 -0
- package/src/integrations/github/references/setup.md +61 -0
- package/src/integrations/granola/references/setup.md +54 -0
- package/src/lib/types.ts +15 -0
- package/src/tools/meeting/.claude-plugin/plugin.json +22 -0
- package/src/tools/meeting/TOOL.yaml +15 -0
- package/src/tools/meeting/commands/meeting.md +35 -0
- package/src/tools/meeting/skills/meeting/SKILL.md +105 -0
- package/src/tools/meeting/skills/meeting/references/export-workflow.md +87 -0
- package/src/tools/share/.claude-plugin/plugin.json +22 -0
- package/src/tools/share/TOOL.yaml +17 -0
- package/src/tools/share/commands/share.md +32 -0
- package/src/tools/share/skills/share/SKILL.md +211 -0
|
@@ -22,8 +22,10 @@
|
|
|
22
22
|
"./src/tools/comments/skills/comments/SKILL.md",
|
|
23
23
|
"./src/tools/droid/skills/droid/SKILL.md",
|
|
24
24
|
"./src/tools/droid/skills/droid-bootstrap/SKILL.md",
|
|
25
|
+
"./src/tools/meeting/skills/meeting/SKILL.md",
|
|
25
26
|
"./src/tools/plan/skills/plan/SKILL.md",
|
|
26
27
|
"./src/tools/project/skills/project/SKILL.md",
|
|
28
|
+
"./src/tools/share/skills/share/SKILL.md",
|
|
27
29
|
"./src/tools/status-update/skills/status-update/SKILL.md",
|
|
28
30
|
"./src/tools/tech-design/skills/tech-design/SKILL.md",
|
|
29
31
|
"./src/tools/wrapup/skills/wrapup/SKILL.md"
|
|
@@ -35,8 +37,10 @@
|
|
|
35
37
|
"./src/tools/codex/commands/codex.md",
|
|
36
38
|
"./src/tools/comments/commands/comments.md",
|
|
37
39
|
"./src/tools/droid/commands/setup.md",
|
|
40
|
+
"./src/tools/meeting/commands/meeting.md",
|
|
38
41
|
"./src/tools/plan/commands/plan.md",
|
|
39
42
|
"./src/tools/project/commands/project.md",
|
|
43
|
+
"./src/tools/share/commands/share.md",
|
|
40
44
|
"./src/tools/status-update/commands/status-update.md",
|
|
41
45
|
"./src/tools/tech-design/commands/tech-design.md",
|
|
42
46
|
"./src/tools/wrapup/commands/wrapup.md"
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @orderful/droid
|
|
2
2
|
|
|
3
|
+
## 0.42.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#250](https://github.com/Orderful/droid/pull/250) [`e92ed07`](https://github.com/Orderful/droid/commit/e92ed07c9c0f311b6bc39f506c5c8d36b44d9115) Thanks [@frytyler](https://github.com/frytyler)! - Add GitHub CLI (gh) integration to TUI and CLI status
|
|
8
|
+
|
|
9
|
+
- [#252](https://github.com/Orderful/droid/pull/252) [`4e24ce4`](https://github.com/Orderful/droid/commit/4e24ce4423fb3abdc1dc4607d89f13c638422308) Thanks [@frytyler](https://github.com/frytyler)! - Add Granola integration to TUI and `droid integrations status`, with setup guide docs.
|
|
10
|
+
|
|
11
|
+
- [#253](https://github.com/Orderful/droid/pull/253) [`b7b2e85`](https://github.com/Orderful/droid/commit/b7b2e85c6d73a932a5da40feadbc55f45f9d9602) Thanks [@frytyler](https://github.com/frytyler)! - Add meeting tool for working with meeting notes, summaries, and transcripts via Granola MCP.
|
|
12
|
+
|
|
13
|
+
New `/meeting` skill and command with support for:
|
|
14
|
+
- Listing recent meetings by time range
|
|
15
|
+
- Natural language search across meeting content
|
|
16
|
+
- Quick summaries (Granola) and context-aware summaries (transcript + project context)
|
|
17
|
+
- Exporting meetings to codex with source-neutral frontmatter
|
|
18
|
+
- Pulling decisions and action items from recent meetings
|
|
19
|
+
|
|
20
|
+
Includes Granola as a new integration with TUI status display and setup guide.
|
|
21
|
+
|
|
22
|
+
## 0.41.0
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- [#248](https://github.com/Orderful/droid/pull/248) [`1172a61`](https://github.com/Orderful/droid/commit/1172a61758b44483126918352a580d9722ffc5b0) Thanks [@frytyler](https://github.com/frytyler)! - Add /share tool for sharing content to Confluence (publish pages) and Slack (post summaries with free-form instructions), and add Atlassian to the TUI Integrations tab
|
|
27
|
+
|
|
3
28
|
## 0.40.1
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
package/dist/bin/droid.js
CHANGED
|
@@ -2533,7 +2533,7 @@ async function updateCommand(tool, options) {
|
|
|
2533
2533
|
import { render, Box as Box16, Text as Text17, useInput as useInput9, useApp as useApp2 } from "ink";
|
|
2534
2534
|
import { useState as useState10, useEffect } from "react";
|
|
2535
2535
|
import { readFileSync as readFileSync9 } from "fs";
|
|
2536
|
-
import { spawnSync as
|
|
2536
|
+
import { spawnSync as spawnSync4 } from "child_process";
|
|
2537
2537
|
import { join as join11, dirname as dirname7 } from "path";
|
|
2538
2538
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
2539
2539
|
|
|
@@ -2821,10 +2821,7 @@ function SettingsDetails({
|
|
|
2821
2821
|
// src/commands/tui/components/IntegrationsDetails.tsx
|
|
2822
2822
|
import { Box as Box6, Text as Text6 } from "ink";
|
|
2823
2823
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2824
|
-
function
|
|
2825
|
-
isFocused,
|
|
2826
|
-
selectedAction
|
|
2827
|
-
}) {
|
|
2824
|
+
function SlackDetails({ isFocused, selectedAction }) {
|
|
2828
2825
|
const hasToken = !!process.env.SLACK_USER_TOKEN;
|
|
2829
2826
|
const hasClientId = !!process.env.SLACK_CLIENT_ID;
|
|
2830
2827
|
const hasClientSecret = !!process.env.SLACK_CLIENT_SECRET;
|
|
@@ -2886,6 +2883,122 @@ function IntegrationsDetails({
|
|
|
2886
2883
|
!isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 2, children: /* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: "press enter for options" }) })
|
|
2887
2884
|
] });
|
|
2888
2885
|
}
|
|
2886
|
+
function AtlassianDetails({ isFocused, selectedAction, connected }) {
|
|
2887
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingLeft: 2, flexGrow: 1, children: [
|
|
2888
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.text, bold: true, children: "Atlassian" }),
|
|
2889
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, children: [
|
|
2890
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.textDim, bold: true, children: "MCP Server" }),
|
|
2891
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
2892
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: " Status " }),
|
|
2893
|
+
connected ? /* @__PURE__ */ jsx6(Text6, { color: colors.success, children: "Connected \u2713" }) : /* @__PURE__ */ jsx6(Text6, { color: "#fbbf24", children: "Not yet verified" })
|
|
2894
|
+
] })
|
|
2895
|
+
] }),
|
|
2896
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: connected ? "Confluence and Jira available via MCP" : "Use /share confluence to verify connection" }) }),
|
|
2897
|
+
isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 2, flexDirection: "row", gap: 2, children: /* @__PURE__ */ jsxs6(
|
|
2898
|
+
Text6,
|
|
2899
|
+
{
|
|
2900
|
+
backgroundColor: selectedAction === 0 ? colors.primary : void 0,
|
|
2901
|
+
color: selectedAction === 0 ? "#ffffff" : colors.textDim,
|
|
2902
|
+
bold: selectedAction === 0,
|
|
2903
|
+
children: [
|
|
2904
|
+
" ",
|
|
2905
|
+
"Setup Guide",
|
|
2906
|
+
" "
|
|
2907
|
+
]
|
|
2908
|
+
}
|
|
2909
|
+
) }),
|
|
2910
|
+
isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: colors.textDim, children: [
|
|
2911
|
+
"enter confirm ",
|
|
2912
|
+
"\xB7",
|
|
2913
|
+
" esc back"
|
|
2914
|
+
] }) }),
|
|
2915
|
+
!isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 2, children: /* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: "press enter for options" }) })
|
|
2916
|
+
] });
|
|
2917
|
+
}
|
|
2918
|
+
function GithubDetails({ isFocused, selectedAction, connected }) {
|
|
2919
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingLeft: 2, flexGrow: 1, children: [
|
|
2920
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.text, bold: true, children: "GitHub CLI" }),
|
|
2921
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, children: [
|
|
2922
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.textDim, bold: true, children: "Status" }),
|
|
2923
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
2924
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: " CLI " }),
|
|
2925
|
+
connected ? /* @__PURE__ */ jsx6(Text6, { color: colors.success, children: "Installed \u2713" }) : /* @__PURE__ */ jsx6(Text6, { color: "#fbbf24", children: "Not detected" })
|
|
2926
|
+
] }),
|
|
2927
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
2928
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: " Auth " }),
|
|
2929
|
+
connected ? /* @__PURE__ */ jsx6(Text6, { color: colors.success, children: "Authenticated \u2713" }) : /* @__PURE__ */ jsx6(Text6, { color: "#fbbf24", children: "Not yet verified" })
|
|
2930
|
+
] })
|
|
2931
|
+
] }),
|
|
2932
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: connected ? "Used by codex, tech-design, code-review, share" : "Run `gh auth login` to connect" }) }),
|
|
2933
|
+
isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 2, flexDirection: "row", gap: 2, children: /* @__PURE__ */ jsxs6(
|
|
2934
|
+
Text6,
|
|
2935
|
+
{
|
|
2936
|
+
backgroundColor: selectedAction === 0 ? colors.primary : void 0,
|
|
2937
|
+
color: selectedAction === 0 ? "#ffffff" : colors.textDim,
|
|
2938
|
+
bold: selectedAction === 0,
|
|
2939
|
+
children: [
|
|
2940
|
+
" ",
|
|
2941
|
+
"Setup Guide",
|
|
2942
|
+
" "
|
|
2943
|
+
]
|
|
2944
|
+
}
|
|
2945
|
+
) }),
|
|
2946
|
+
isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: colors.textDim, children: [
|
|
2947
|
+
"enter confirm ",
|
|
2948
|
+
"\xB7",
|
|
2949
|
+
" esc back"
|
|
2950
|
+
] }) }),
|
|
2951
|
+
!isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 2, children: /* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: "press enter for options" }) })
|
|
2952
|
+
] });
|
|
2953
|
+
}
|
|
2954
|
+
function GranolaDetails({ isFocused, selectedAction, connected }) {
|
|
2955
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingLeft: 2, flexGrow: 1, children: [
|
|
2956
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.text, bold: true, children: "Granola" }),
|
|
2957
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, children: [
|
|
2958
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.textDim, bold: true, children: "MCP Server" }),
|
|
2959
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
2960
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: " Status " }),
|
|
2961
|
+
connected ? /* @__PURE__ */ jsx6(Text6, { color: colors.success, children: "Connected \u2713" }) : /* @__PURE__ */ jsx6(Text6, { color: "#fbbf24", children: "Not yet verified" })
|
|
2962
|
+
] })
|
|
2963
|
+
] }),
|
|
2964
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: connected ? "Meeting notes and transcripts available via MCP" : "Use /mcp to add the Granola server" }) }),
|
|
2965
|
+
isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 2, flexDirection: "row", gap: 2, children: /* @__PURE__ */ jsxs6(
|
|
2966
|
+
Text6,
|
|
2967
|
+
{
|
|
2968
|
+
backgroundColor: selectedAction === 0 ? colors.primary : void 0,
|
|
2969
|
+
color: selectedAction === 0 ? "#ffffff" : colors.textDim,
|
|
2970
|
+
bold: selectedAction === 0,
|
|
2971
|
+
children: [
|
|
2972
|
+
" ",
|
|
2973
|
+
"Setup Guide",
|
|
2974
|
+
" "
|
|
2975
|
+
]
|
|
2976
|
+
}
|
|
2977
|
+
) }),
|
|
2978
|
+
isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsxs6(Text6, { color: colors.textDim, children: [
|
|
2979
|
+
"enter confirm ",
|
|
2980
|
+
"\xB7",
|
|
2981
|
+
" esc back"
|
|
2982
|
+
] }) }),
|
|
2983
|
+
!isFocused && /* @__PURE__ */ jsx6(Box6, { marginTop: 2, children: /* @__PURE__ */ jsx6(Text6, { color: colors.textDim, children: "press enter for options" }) })
|
|
2984
|
+
] });
|
|
2985
|
+
}
|
|
2986
|
+
function IntegrationsDetails({
|
|
2987
|
+
isFocused,
|
|
2988
|
+
selectedAction,
|
|
2989
|
+
integration
|
|
2990
|
+
}) {
|
|
2991
|
+
if (integration.id === "atlassian") {
|
|
2992
|
+
return /* @__PURE__ */ jsx6(AtlassianDetails, { isFocused, selectedAction, connected: integration.connected });
|
|
2993
|
+
}
|
|
2994
|
+
if (integration.id === "github") {
|
|
2995
|
+
return /* @__PURE__ */ jsx6(GithubDetails, { isFocused, selectedAction, connected: integration.connected });
|
|
2996
|
+
}
|
|
2997
|
+
if (integration.id === "granola") {
|
|
2998
|
+
return /* @__PURE__ */ jsx6(GranolaDetails, { isFocused, selectedAction, connected: integration.connected });
|
|
2999
|
+
}
|
|
3000
|
+
return /* @__PURE__ */ jsx6(SlackDetails, { isFocused, selectedAction });
|
|
3001
|
+
}
|
|
2889
3002
|
|
|
2890
3003
|
// src/commands/tui/components/PlatformBadges.tsx
|
|
2891
3004
|
import { Box as Box7, Text as Text7 } from "ink";
|
|
@@ -4243,10 +4356,30 @@ function useToolUpdates({ onUpdateComplete }) {
|
|
|
4243
4356
|
};
|
|
4244
4357
|
}
|
|
4245
4358
|
|
|
4359
|
+
// src/integrations/github/index.ts
|
|
4360
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
4361
|
+
function checkGhAuth() {
|
|
4362
|
+
try {
|
|
4363
|
+
const result = spawnSync3("gh", ["auth", "status"], {
|
|
4364
|
+
stdio: "ignore",
|
|
4365
|
+
timeout: 5e3
|
|
4366
|
+
});
|
|
4367
|
+
return result.status === 0;
|
|
4368
|
+
} catch {
|
|
4369
|
+
return false;
|
|
4370
|
+
}
|
|
4371
|
+
}
|
|
4372
|
+
|
|
4246
4373
|
// src/commands/tui.tsx
|
|
4247
4374
|
import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4248
4375
|
var exitMessage = null;
|
|
4249
4376
|
var exitCommand = null;
|
|
4377
|
+
var INTEGRATION_GUIDE_TITLES = {
|
|
4378
|
+
slack: "Slack Integration Setup",
|
|
4379
|
+
atlassian: "Atlassian Integration Setup",
|
|
4380
|
+
github: "GitHub CLI Setup",
|
|
4381
|
+
granola: "Granola Integration Setup"
|
|
4382
|
+
};
|
|
4250
4383
|
var __tui_dirname = dirname7(fileURLToPath5(import.meta.url));
|
|
4251
4384
|
var INTEGRATIONS_DIR = join11(__tui_dirname, "../integrations");
|
|
4252
4385
|
function loadIntegrationReference(integration, filename) {
|
|
@@ -4342,6 +4475,20 @@ function App() {
|
|
|
4342
4475
|
};
|
|
4343
4476
|
const tools = getBundledTools();
|
|
4344
4477
|
const skills = getBundledSkills();
|
|
4478
|
+
const integrations2 = [
|
|
4479
|
+
{ id: "slack", name: "Slack", connected: !!process.env.SLACK_USER_TOKEN },
|
|
4480
|
+
{ id: "atlassian", name: "Atlassian", connected: !!getConfigValue("integrations.atlassian.configured") },
|
|
4481
|
+
{ id: "github", name: "GitHub", connected: !!getConfigValue("integrations.github.configured") },
|
|
4482
|
+
{ id: "granola", name: "Granola", connected: !!getConfigValue("integrations.granola.configured") }
|
|
4483
|
+
];
|
|
4484
|
+
useEffect(() => {
|
|
4485
|
+
if (!getConfigValue("integrations.github.configured")) {
|
|
4486
|
+
const isAuthed = checkGhAuth();
|
|
4487
|
+
if (isAuthed) {
|
|
4488
|
+
setConfigValue("integrations.github.configured", true);
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
}, []);
|
|
4345
4492
|
useInput9(
|
|
4346
4493
|
(input, key) => {
|
|
4347
4494
|
if (message) setMessage(null);
|
|
@@ -4375,7 +4522,7 @@ function App() {
|
|
|
4375
4522
|
setSelectedAction(0);
|
|
4376
4523
|
}
|
|
4377
4524
|
if (key.downArrow) {
|
|
4378
|
-
const maxIndex = activeTab === "tools" ? tools.length - 1 : activeTab === "integrations" ?
|
|
4525
|
+
const maxIndex = activeTab === "tools" ? tools.length - 1 : activeTab === "integrations" ? integrations2.length - 1 : 0;
|
|
4379
4526
|
setSelectedIndex((prev) => {
|
|
4380
4527
|
const newIndex = Math.min(maxIndex, prev + 1);
|
|
4381
4528
|
if (newIndex >= scrollOffset + MAX_VISIBLE_ITEMS) {
|
|
@@ -4400,12 +4547,22 @@ function App() {
|
|
|
4400
4547
|
setSelectedAction(0);
|
|
4401
4548
|
}
|
|
4402
4549
|
if (activeTab === "integrations") {
|
|
4403
|
-
const
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4550
|
+
const currentIntegration = integrations2[selectedIndex];
|
|
4551
|
+
let intActions = [];
|
|
4552
|
+
if (currentIntegration?.id === "slack") {
|
|
4553
|
+
const hasClientCreds = !!process.env.SLACK_CLIENT_ID && !!process.env.SLACK_CLIENT_SECRET;
|
|
4554
|
+
const canRunSetup = hasClientCreds && !process.env.SLACK_USER_TOKEN;
|
|
4555
|
+
intActions = [
|
|
4556
|
+
...canRunSetup ? [{ id: "setup" }] : [],
|
|
4557
|
+
{ id: "guide" }
|
|
4558
|
+
];
|
|
4559
|
+
} else if (currentIntegration?.id === "atlassian") {
|
|
4560
|
+
intActions = [{ id: "guide" }];
|
|
4561
|
+
} else if (currentIntegration?.id === "github") {
|
|
4562
|
+
intActions = [{ id: "guide" }];
|
|
4563
|
+
} else if (currentIntegration?.id === "granola") {
|
|
4564
|
+
intActions = [{ id: "guide" }];
|
|
4565
|
+
}
|
|
4409
4566
|
const maxIntAction = intActions.length - 1;
|
|
4410
4567
|
if (key.leftArrow) {
|
|
4411
4568
|
setSelectedAction((prev) => Math.max(0, prev - 1));
|
|
@@ -4415,14 +4572,16 @@ function App() {
|
|
|
4415
4572
|
}
|
|
4416
4573
|
if (key.return) {
|
|
4417
4574
|
const actionId = intActions[selectedAction]?.id;
|
|
4418
|
-
if (actionId === "setup") {
|
|
4575
|
+
if (actionId === "setup" && currentIntegration?.id === "slack") {
|
|
4419
4576
|
exitCommand = ["droid", "integrations", "setup", "slack"];
|
|
4420
4577
|
exit();
|
|
4421
4578
|
} else if (actionId === "guide") {
|
|
4422
|
-
const
|
|
4579
|
+
const integrationId = currentIntegration?.id ?? "slack";
|
|
4580
|
+
const guideTitle = INTEGRATION_GUIDE_TITLES[integrationId] ?? `${currentIntegration?.name} Setup`;
|
|
4581
|
+
const content = loadIntegrationReference(integrationId, "setup.md");
|
|
4423
4582
|
if (content) {
|
|
4424
4583
|
setPreviousView("detail");
|
|
4425
|
-
setReadmeContent({ title:
|
|
4584
|
+
setReadmeContent({ title: guideTitle, content });
|
|
4426
4585
|
setView("readme");
|
|
4427
4586
|
} else {
|
|
4428
4587
|
setMessage({ text: "Could not load setup guide", type: "error" });
|
|
@@ -4702,11 +4861,14 @@ function App() {
|
|
|
4702
4861
|
" tools total"
|
|
4703
4862
|
] }) })
|
|
4704
4863
|
] }),
|
|
4705
|
-
activeTab === "integrations" && /* @__PURE__ */ jsx17(Box16, { paddingX: 1, children: /* @__PURE__ */ jsxs16(Text17, { children: [
|
|
4706
|
-
selectedIndex ===
|
|
4707
|
-
/* @__PURE__ */
|
|
4708
|
-
|
|
4709
|
-
|
|
4864
|
+
activeTab === "integrations" && /* @__PURE__ */ jsx17(Box16, { flexDirection: "column", paddingX: 1, children: integrations2.map((integration, index) => /* @__PURE__ */ jsxs16(Text17, { children: [
|
|
4865
|
+
selectedIndex === index ? /* @__PURE__ */ jsx17(Text17, { color: colors.primary, children: ">" }) : /* @__PURE__ */ jsx17(Text17, { children: " " }),
|
|
4866
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
4867
|
+
" ",
|
|
4868
|
+
integration.name
|
|
4869
|
+
] }),
|
|
4870
|
+
integration.connected ? /* @__PURE__ */ jsx17(Text17, { color: colors.success, children: " \u2713" }) : /* @__PURE__ */ jsx17(Text17, { color: colors.textDim, children: " \u2717" })
|
|
4871
|
+
] }, integration.id)) }),
|
|
4710
4872
|
activeTab === "settings" && /* @__PURE__ */ jsx17(Box16, { paddingX: 1, children: /* @__PURE__ */ jsx17(Text17, { color: colors.textDim, children: "View and edit config" }) })
|
|
4711
4873
|
] }),
|
|
4712
4874
|
message && /* @__PURE__ */ jsx17(Box16, { paddingX: 1, marginTop: 1, children: /* @__PURE__ */ jsx17(
|
|
@@ -4728,11 +4890,12 @@ function App() {
|
|
|
4728
4890
|
selectedAction
|
|
4729
4891
|
}
|
|
4730
4892
|
),
|
|
4731
|
-
activeTab === "integrations" && /* @__PURE__ */ jsx17(
|
|
4893
|
+
activeTab === "integrations" && integrations2[selectedIndex] && /* @__PURE__ */ jsx17(
|
|
4732
4894
|
IntegrationsDetails,
|
|
4733
4895
|
{
|
|
4734
4896
|
isFocused: view === "detail",
|
|
4735
|
-
selectedAction
|
|
4897
|
+
selectedAction,
|
|
4898
|
+
integration: integrations2[selectedIndex]
|
|
4736
4899
|
}
|
|
4737
4900
|
),
|
|
4738
4901
|
activeTab === "settings" && /* @__PURE__ */ jsx17(
|
|
@@ -4755,7 +4918,7 @@ async function tuiCommand() {
|
|
|
4755
4918
|
if (exitCommand) {
|
|
4756
4919
|
const [cmd, ...args] = exitCommand;
|
|
4757
4920
|
exitCommand = null;
|
|
4758
|
-
|
|
4921
|
+
spawnSync4(cmd, args, { stdio: "inherit" });
|
|
4759
4922
|
return;
|
|
4760
4923
|
}
|
|
4761
4924
|
if (exitMessage) {
|
|
@@ -5341,6 +5504,36 @@ async function integrationsStatusCommand() {
|
|
|
5341
5504
|
console.log(chalk11.yellow(" Status: not configured"));
|
|
5342
5505
|
}
|
|
5343
5506
|
console.log("");
|
|
5507
|
+
console.log(chalk11.bold(" Atlassian"));
|
|
5508
|
+
const atlassianConfigured = getConfigValue("integrations.atlassian.configured");
|
|
5509
|
+
if (atlassianConfigured) {
|
|
5510
|
+
console.log(chalk11.green(" MCP: Connected"));
|
|
5511
|
+
console.log(chalk11.green(" Status: configured"));
|
|
5512
|
+
} else {
|
|
5513
|
+
console.log(chalk11.yellow(" MCP: Not yet verified"));
|
|
5514
|
+
console.log(chalk11.gray(" Use /share confluence to verify, or see setup guide"));
|
|
5515
|
+
}
|
|
5516
|
+
console.log("");
|
|
5517
|
+
console.log(chalk11.bold(" GitHub"));
|
|
5518
|
+
const githubConfigured = getConfigValue("integrations.github.configured");
|
|
5519
|
+
if (githubConfigured) {
|
|
5520
|
+
console.log(chalk11.green(" CLI: Installed"));
|
|
5521
|
+
console.log(chalk11.green(" Status: configured"));
|
|
5522
|
+
} else {
|
|
5523
|
+
console.log(chalk11.yellow(" CLI: Not verified"));
|
|
5524
|
+
console.log(chalk11.gray(" Run: gh auth login"));
|
|
5525
|
+
}
|
|
5526
|
+
console.log("");
|
|
5527
|
+
console.log(chalk11.bold(" Granola"));
|
|
5528
|
+
const granolaConfigured = getConfigValue("integrations.granola.configured");
|
|
5529
|
+
if (granolaConfigured) {
|
|
5530
|
+
console.log(chalk11.green(" MCP: Connected"));
|
|
5531
|
+
console.log(chalk11.green(" Status: configured"));
|
|
5532
|
+
} else {
|
|
5533
|
+
console.log(chalk11.yellow(" MCP: Not yet verified"));
|
|
5534
|
+
console.log(chalk11.gray(" Use /mcp to add the Granola server, then verify with a meeting query"));
|
|
5535
|
+
}
|
|
5536
|
+
console.log("");
|
|
5344
5537
|
}
|
|
5345
5538
|
async function slackPostCommand(options) {
|
|
5346
5539
|
let input;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../src/commands/integrations.ts"],"names":[],"mappings":"AAoNA,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,IAAI,CAAC,CAuInE;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../../src/commands/integrations.ts"],"names":[],"mappings":"AAoNA,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,IAAI,CAAC,CAuInE;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAkF/D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCnF"}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
export interface Integration {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
connected: boolean;
|
|
5
|
+
}
|
|
1
6
|
export interface IntegrationsDetailsProps {
|
|
2
7
|
isFocused: boolean;
|
|
3
8
|
selectedAction: number;
|
|
9
|
+
integration: Integration;
|
|
4
10
|
}
|
|
5
|
-
export declare function IntegrationsDetails({ isFocused, selectedAction, }: IntegrationsDetailsProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare function IntegrationsDetails({ isFocused, selectedAction, integration, }: IntegrationsDetailsProps): import("react/jsx-runtime").JSX.Element;
|
|
6
12
|
//# sourceMappingURL=IntegrationsDetails.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntegrationsDetails.d.ts","sourceRoot":"","sources":["../../../../src/commands/tui/components/IntegrationsDetails.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"IntegrationsDetails.d.ts","sourceRoot":"","sources":["../../../../src/commands/tui/components/IntegrationsDetails.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAmPD,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,cAAc,EACd,WAAW,GACZ,EAAE,wBAAwB,2CAe1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../src/commands/tui.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../src/commands/tui.tsx"],"names":[],"mappings":"AAktBA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAyBhD"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Atlassian Integration Setup
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Atlassian integration connects droid to Confluence (and Jira) via the official Atlassian MCP server. This enables the `/share` tool to publish markdown files directly to Confluence pages.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### 1. Add the Atlassian MCP Server
|
|
10
|
+
|
|
11
|
+
In Claude Code, run:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
/mcp
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Select **Atlassian** from the available MCP servers and follow the authentication prompts. This connects your Atlassian account (Confluence + Jira) to Claude Code.
|
|
18
|
+
|
|
19
|
+
### 2. Verify Connection
|
|
20
|
+
|
|
21
|
+
Run `/share confluence` in a Claude Code session. If the connection is working, you'll see a list of available Confluence spaces.
|
|
22
|
+
|
|
23
|
+
Alternatively, the TUI Integrations tab will show `Atlassian ✓` once the MCP has been used successfully.
|
|
24
|
+
|
|
25
|
+
## How It Works
|
|
26
|
+
|
|
27
|
+
Unlike Slack (which uses environment variables and OAuth), Atlassian uses Claude Code's built-in MCP server system:
|
|
28
|
+
|
|
29
|
+
| Aspect | Slack | Atlassian |
|
|
30
|
+
|--------|-------|-----------|
|
|
31
|
+
| Auth method | OAuth + env vars | MCP server (managed by Claude Code) |
|
|
32
|
+
| Setup | `droid integrations setup slack` | `/mcp` in Claude Code |
|
|
33
|
+
| API access | `@slack/web-api` SDK | MCP tool calls (`mcp__claude_ai_Atlassian__*`) |
|
|
34
|
+
| Config flag | `integrations.slack.configured` | `integrations.atlassian.configured` |
|
|
35
|
+
|
|
36
|
+
The `configured` flag is set automatically on first successful MCP call — no manual configuration needed.
|
|
37
|
+
|
|
38
|
+
## Troubleshooting
|
|
39
|
+
|
|
40
|
+
| Issue | Resolution |
|
|
41
|
+
|-------|------------|
|
|
42
|
+
| MCP not available | Run `/mcp` in Claude Code to add the Atlassian server |
|
|
43
|
+
| No Confluence spaces listed | Check your Atlassian account has Confluence access |
|
|
44
|
+
| Permission errors | Verify your account has edit permissions in the target space |
|
|
45
|
+
| "Not configured" in TUI | Use `/share confluence` once — the flag is set on first success |
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
Once connected, use the `/share` command:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
/share confluence # Interactive - prompts for file
|
|
53
|
+
/share confluence path/to/file.md # Share specific file
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The share skill handles:
|
|
57
|
+
- Choosing a Confluence space and parent page
|
|
58
|
+
- Creating new pages or updating existing ones
|
|
59
|
+
- Storing the page ID in the file's frontmatter for future updates
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/index.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAUrC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { spawnSync } from 'child_process';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if the GitHub CLI (gh) is installed and authenticated.
|
|
5
|
+
* Returns true if `gh auth status` exits with code 0.
|
|
6
|
+
*/
|
|
7
|
+
export function checkGhAuth(): boolean {
|
|
8
|
+
try {
|
|
9
|
+
const result = spawnSync('gh', ['auth', 'status'], {
|
|
10
|
+
stdio: 'ignore',
|
|
11
|
+
timeout: 5000,
|
|
12
|
+
});
|
|
13
|
+
return result.status === 0;
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# GitHub CLI Setup
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The GitHub CLI (`gh`) integration connects droid to GitHub for PR creation, issue management, and repository operations. Several skills depend on it: **codex**, **tech-design**, **code-review**, and **share**.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### 1. Install the GitHub CLI
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
brew install gh
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### 2. Authenticate
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
gh auth login
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Follow the interactive prompts to authenticate with your GitHub account. Choose HTTPS as the preferred protocol.
|
|
22
|
+
|
|
23
|
+
### 3. Verify
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
gh auth status
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
You should see your GitHub username and the scopes available. The TUI Integrations tab will show `GitHub ✓` once detection runs.
|
|
30
|
+
|
|
31
|
+
## How It Works
|
|
32
|
+
|
|
33
|
+
Unlike Slack (which uses environment variables and OAuth) or Atlassian (which uses MCP), GitHub uses a locally installed CLI binary:
|
|
34
|
+
|
|
35
|
+
| Aspect | Slack | Atlassian | GitHub |
|
|
36
|
+
|--------|-------|-----------|--------|
|
|
37
|
+
| Auth method | OAuth + env vars | MCP server (managed by Claude Code) | `gh auth login` (local CLI) |
|
|
38
|
+
| Setup | `droid integrations setup slack` | `/mcp` in Claude Code | `brew install gh && gh auth login` |
|
|
39
|
+
| API access | `@slack/web-api` SDK | MCP tool calls (`mcp__claude_ai_Atlassian__*`) | `gh` CLI via Bash |
|
|
40
|
+
| Config flag | `integrations.slack.configured` | `integrations.atlassian.configured` | `integrations.github.configured` |
|
|
41
|
+
|
|
42
|
+
The `configured` flag is set automatically when the TUI detects a working `gh auth status` — no manual configuration needed.
|
|
43
|
+
|
|
44
|
+
## Troubleshooting
|
|
45
|
+
|
|
46
|
+
| Issue | Resolution |
|
|
47
|
+
|-------|------------|
|
|
48
|
+
| `gh: command not found` | Install with `brew install gh` |
|
|
49
|
+
| Not authenticated | Run `gh auth login` and follow prompts |
|
|
50
|
+
| Wrong account | Run `gh auth logout` then `gh auth login` |
|
|
51
|
+
| Scopes missing | Run `gh auth refresh -s <scope>` to add scopes |
|
|
52
|
+
| "Not configured" in TUI | Relaunch the TUI — detection runs on startup |
|
|
53
|
+
|
|
54
|
+
## Dependent Skills
|
|
55
|
+
|
|
56
|
+
These skills use `gh` and will fail without it:
|
|
57
|
+
|
|
58
|
+
- **codex** — Fetches PR metadata and diffs for context
|
|
59
|
+
- **tech-design** — Creates PRs for tech design documents
|
|
60
|
+
- **code-review** — Reads PR details, checks, and comments
|
|
61
|
+
- **share** — Creates PRs and interacts with GitHub APIs
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Granola Integration Setup
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Granola integration connects droid to your meeting notes, summaries, and transcripts through the Granola MCP server in Claude Code.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### 1. Install Granola
|
|
10
|
+
|
|
11
|
+
Install and sign in to the Granola app first if you have not already.
|
|
12
|
+
|
|
13
|
+
### 2. Add the Granola MCP Server
|
|
14
|
+
|
|
15
|
+
In Claude Code, run:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
/mcp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Select **Granola** and complete the auth flow.
|
|
22
|
+
|
|
23
|
+
### 3. Verify Connection
|
|
24
|
+
|
|
25
|
+
Ask Claude to list recent meetings. If successful, droid can use Granola MCP tools and the Integrations tab should show `Granola ✓`.
|
|
26
|
+
|
|
27
|
+
## Available MCP Tools
|
|
28
|
+
|
|
29
|
+
Depending on your Granola MCP version, tools may include:
|
|
30
|
+
|
|
31
|
+
- `list_meetings`
|
|
32
|
+
- `get_meetings`
|
|
33
|
+
- `get_meeting_transcript`
|
|
34
|
+
- `query_granola_meetings`
|
|
35
|
+
|
|
36
|
+
## How It Works
|
|
37
|
+
|
|
38
|
+
Granola follows the same integration model as Atlassian: MCP is managed by Claude Code, not by a local CLI.
|
|
39
|
+
|
|
40
|
+
| Aspect | Granola |
|
|
41
|
+
|--------|---------|
|
|
42
|
+
| Auth method | MCP server via Claude Code |
|
|
43
|
+
| Setup command | `/mcp` |
|
|
44
|
+
| Config flag | `integrations.granola.configured` |
|
|
45
|
+
|
|
46
|
+
No `droid integrations setup granola` command is required.
|
|
47
|
+
|
|
48
|
+
## Troubleshooting
|
|
49
|
+
|
|
50
|
+
| Issue | Resolution |
|
|
51
|
+
|-------|------------|
|
|
52
|
+
| Granola not shown in `/mcp` | Update Claude Code and try again |
|
|
53
|
+
| Not connected in TUI | Re-run `/mcp` and verify with a meeting query |
|
|
54
|
+
| No meetings returned | Confirm the Granola app has synced meetings |
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -44,8 +44,20 @@ export interface IntegrationSlackConfig {
|
|
|
44
44
|
configured?: boolean;
|
|
45
45
|
crosspost_channel?: string;
|
|
46
46
|
}
|
|
47
|
+
export interface IntegrationAtlassianConfig {
|
|
48
|
+
configured?: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface IntegrationGithubConfig {
|
|
51
|
+
configured?: boolean;
|
|
52
|
+
}
|
|
53
|
+
export interface IntegrationGranolaConfig {
|
|
54
|
+
configured?: boolean;
|
|
55
|
+
}
|
|
47
56
|
export interface IntegrationsConfig {
|
|
48
57
|
slack?: IntegrationSlackConfig;
|
|
58
|
+
atlassian?: IntegrationAtlassianConfig;
|
|
59
|
+
github?: IntegrationGithubConfig;
|
|
60
|
+
granola?: IntegrationGranolaConfig;
|
|
49
61
|
}
|
|
50
62
|
export interface DroidConfig {
|
|
51
63
|
platform: Platform;
|