copilot-tap-extension 1.1.4 → 2.0.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
@@ -62,7 +62,7 @@ npx copilot-tap-extension
62
62
  npx copilot-tap-extension --local
63
63
  ```
64
64
 
65
- This installs the bundled extension, the `/loop` skill, the `/monitor` skill, and the agent instructions to the appropriate Copilot directory. Run `npx copilot-tap-extension --help` for all options.
65
+ This installs the bundled extension, the `/tap-loop` skill, the `/tap-monitor` skill, and the agent instructions to the appropriate Copilot directory. Run `npx copilot-tap-extension --help` for all options.
66
66
 
67
67
  To update to the latest version, re-run the same command with `--force`:
68
68
 
@@ -103,13 +103,13 @@ The config file tells the extension which emitters to auto-start. The example de
103
103
 
104
104
  This runs the heartbeat script on session start, drops boot messages, injects warnings and errors, and keeps everything else in the stream.
105
105
 
106
- Once inside the session, describe what you want in natural language. You can also use `/loop` to set up scheduled prompts directly:
106
+ Once inside the session, describe what you want in natural language. You can also use `/tap-loop` to set up scheduled prompts directly:
107
107
 
108
108
  > _"Watch my build logs and tell me if anything fails"_
109
109
 
110
- > _"/loop 5m check for new PR review comments"_
110
+ > _"/tap-loop 5m check for new PR review comments"_
111
111
 
112
- > _"/monitor tail -f /var/log/app.log"_
112
+ > _"/tap-monitor tail -f /var/log/app.log"_
113
113
 
114
114
  > _"Tail the API logs, inject errors, drop health checks"_
115
115
 
@@ -175,11 +175,11 @@ You keep coding. Twenty minutes later, Copilot interrupts: "Run 48291: deploymen
175
175
 
176
176
  **Monitor a command with self-tuning filters**
177
177
 
178
- Use `/monitor` to run a shell command continuously while a companion agent periodically reads the output and updates the filter expressions to separate noise from signal automatically.
178
+ Use `/tap-monitor` to run a shell command continuously while a companion agent periodically reads the output and updates the filter expressions to separate noise from signal automatically.
179
179
 
180
180
  ```
181
- /monitor tail -f /var/log/app.log
182
- /monitor 10m docker logs -f mycontainer
181
+ /tap-monitor tail -f /var/log/app.log
182
+ /tap-monitor 10m docker logs -f mycontainer
183
183
  ```
184
184
 
185
185
  The command stream starts with a sensible initial `notifyPattern`. Every few minutes (configurable) the companion reviews recent log lines and calls `tap_set_event_filter` if the patterns need adjustment. The filter tightens itself based on real output — no manual tuning required.
@@ -189,7 +189,7 @@ The command stream starts with a sensible initial `notifyPattern`. Every few min
189
189
  A PromptEmitter re-runs an agent prompt at a fixed interval. Useful for PR comments, CI status, or ticket queues.
190
190
 
191
191
  ```
192
- /loop 15m Check for new failing CI runs or PR review comments.
192
+ /tap-loop 15m Check for new failing CI runs or PR review comments.
193
193
  Summarize only actionable items.
194
194
  ```
195
195
 
@@ -197,10 +197,10 @@ Every 15 minutes the agent scans and reports back. No news means no interruption
197
197
 
198
198
  **Run a prompt when idle**
199
199
 
200
- Use `/loop idle` to re-run a prompt whenever the session has nothing else to do. Set `maxRuns` to cap iterations.
200
+ Use `/tap-loop idle` to re-run a prompt whenever the session has nothing else to do. Set `maxRuns` to cap iterations.
201
201
 
202
202
  ```
203
- /loop idle Scan for new issues labeled urgent. Summarize what changed.
203
+ /tap-loop idle Scan for new issues labeled urgent. Summarize what changed.
204
204
  ```
205
205
 
206
206
  The prompt fires immediately, then re-fires after each idle period. It stops after reaching the iteration limit.
@@ -222,8 +222,9 @@ Rules can be added or changed while the emitter is running. You never need to re
222
222
  ```text
223
223
  .github/
224
224
  extensions/tap/extension.mjs # extension entry point (loads the runtime)
225
- skills/loop/ # /loop skill for scheduled and idle prompts
226
- skills/monitor/ # /monitor skill for self-tuning command monitors
225
+ skills/tap-loop/ # /tap-loop skill for scheduled and idle prompts
226
+ skills/tap-monitor/ # /tap-monitor skill for self-tuning command monitors
227
+ skills/tap-create-provider/ # /tap-create-provider skill for scaffolding external tool providers
227
228
  copilot-instructions.md # agent guidance for using this extension
228
229
  src/
229
230
  emitter/ # supervisor, lifecycle, spawn, line router
package/bin/install.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { existsSync, mkdirSync, copyFileSync, readFileSync } from "node:fs";
2
+ import { existsSync, mkdirSync, copyFileSync, readFileSync, unlinkSync } from "node:fs";
3
3
  import { execFileSync } from "node:child_process";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import path from "node:path";
@@ -33,22 +33,22 @@ and preserves customizable artifacts. If fresh, does a full install.
33
33
  Options:
34
34
  --global, -g Install to ~/.copilot/ (default)
35
35
  --local, -l Install to .github/ (project-scoped)
36
- --full Force a full install even if already installed
36
+ --force, -f Force a full reinstall even if already installed
37
37
  --help, -h Show this help message
38
38
 
39
39
  Installs:
40
40
  extensions/tap/extension.mjs The bundled ※ tap extension
41
41
  extensions/tap/version.json Installed version metadata
42
- skills/loop/SKILL.md The /loop skill for prompt-based loops
43
- skills/create-provider/SKILL.md The /create-provider skill for scaffolding providers
44
- skills/monitor/SKILL.md The /monitor skill for self-tuning command monitors
42
+ skills/tap-loop/SKILL.md The /tap-loop skill for prompt-based loops
43
+ skills/tap-create-provider/SKILL.md The /tap-create-provider skill for scaffolding providers
44
+ skills/tap-monitor/SKILL.md The /tap-monitor skill for self-tuning command monitors
45
45
  copilot-instructions.md Agent instructions for using ※ tap
46
46
  `);
47
47
  }
48
48
 
49
49
  function parseArgs(argv) {
50
50
  const args = argv.slice(2);
51
- const flags = { scope: "global", full: false, help: false };
51
+ const flags = { scope: "global", force: false, help: false };
52
52
  for (const arg of args) {
53
53
  switch (arg) {
54
54
  case "--global":
@@ -59,12 +59,12 @@ function parseArgs(argv) {
59
59
  case "-l":
60
60
  flags.scope = "local";
61
61
  break;
62
+ case "--force":
63
+ case "-f":
62
64
  case "--full":
63
- flags.full = true;
65
+ flags.force = true;
64
66
  break;
65
67
  // Keep legacy flags working
66
- case "--force":
67
- case "-f":
68
68
  case "--update":
69
69
  case "-u":
70
70
  break;
@@ -128,6 +128,36 @@ function isCopilotCliInstalled() {
128
128
  }
129
129
  }
130
130
 
131
+ function removeDeprecatedSkills(targetRoot) {
132
+ const deprecated = ["loop", "monitor", "create-provider"];
133
+ let allOk = true;
134
+ let removedAny = false;
135
+
136
+ for (const name of deprecated) {
137
+ const oldPath = path.join(targetRoot, "skills", name, "SKILL.md");
138
+ if (!existsSync(oldPath)) {
139
+ continue;
140
+ }
141
+ try {
142
+ unlinkSync(oldPath);
143
+ if (!removedAny) {
144
+ console.log();
145
+ removedAny = true;
146
+ }
147
+ console.log(` ✓ Removed deprecated skill: skills/${name}/SKILL.md`);
148
+ } catch {
149
+ allOk = false;
150
+ console.warn(` ⚠ Could not remove deprecated skill at ${oldPath} — remove it manually`);
151
+ }
152
+ }
153
+
154
+ if (removedAny) {
155
+ console.log(`\n Use the new namespaced commands: /tap-loop /tap-monitor /tap-create-provider`);
156
+ }
157
+
158
+ return allOk;
159
+ }
160
+
131
161
  function install(flags) {
132
162
  const targetRoot = getTargetRoot(flags.scope);
133
163
  const scopeLabel = flags.scope === "global" ? "global (~/.copilot)" : "local (.github)";
@@ -141,16 +171,20 @@ function install(flags) {
141
171
  }
142
172
 
143
173
  const installed = isAlreadyInstalled(targetRoot);
144
- const isUpdate = installed && !flags.full;
174
+ const isUpdate = installed && !flags.force;
175
+ const isReinstall = installed && flags.force;
176
+ const installedVersion = installed ? getInstalledVersion(targetRoot) : null;
145
177
 
146
178
  if (isUpdate) {
147
- const installedVersion = getInstalledVersion(targetRoot);
148
179
  if (installedVersion && installedVersion === packageVersion) {
149
180
  console.log(`\n${BRAND} — already up to date (v${installedVersion})\n`);
150
181
  process.exit(0);
151
182
  }
152
183
  const fromLabel = installedVersion ? `v${installedVersion}` : "unknown";
153
184
  console.log(`\n${BRAND} — updating ${fromLabel} → v${packageVersion} (${scopeLabel})\n`);
185
+ } else if (isReinstall) {
186
+ const fromLabel = installedVersion ? `v${installedVersion}` : "unknown";
187
+ console.log(`\n${BRAND} — reinstalling ${fromLabel} → v${packageVersion} (${scopeLabel})\n`);
154
188
  } else {
155
189
  console.log(`\n${BRAND} — installing v${packageVersion} (${scopeLabel})\n`);
156
190
  }
@@ -170,19 +204,19 @@ function install(flags) {
170
204
 
171
205
  const ancillaryArtifacts = [
172
206
  {
173
- src: path.join(distDir, "skills", "loop", "SKILL.md"),
174
- dest: path.join(targetRoot, "skills", "loop", "SKILL.md"),
175
- label: "skills/loop/SKILL.md"
207
+ src: path.join(distDir, "skills", "tap-loop", "SKILL.md"),
208
+ dest: path.join(targetRoot, "skills", "tap-loop", "SKILL.md"),
209
+ label: "skills/tap-loop/SKILL.md"
176
210
  },
177
211
  {
178
- src: path.join(distDir, "skills", "create-provider", "SKILL.md"),
179
- dest: path.join(targetRoot, "skills", "create-provider", "SKILL.md"),
180
- label: "skills/create-provider/SKILL.md"
212
+ src: path.join(distDir, "skills", "tap-create-provider", "SKILL.md"),
213
+ dest: path.join(targetRoot, "skills", "tap-create-provider", "SKILL.md"),
214
+ label: "skills/tap-create-provider/SKILL.md"
181
215
  },
182
216
  {
183
- src: path.join(distDir, "skills", "monitor", "SKILL.md"),
184
- dest: path.join(targetRoot, "skills", "monitor", "SKILL.md"),
185
- label: "skills/monitor/SKILL.md"
217
+ src: path.join(distDir, "skills", "tap-monitor", "SKILL.md"),
218
+ dest: path.join(targetRoot, "skills", "tap-monitor", "SKILL.md"),
219
+ label: "skills/tap-monitor/SKILL.md"
186
220
  },
187
221
  {
188
222
  src: path.join(distDir, "copilot-instructions.md"),
@@ -191,7 +225,12 @@ function install(flags) {
191
225
  }
192
226
  ];
193
227
 
194
- const artifacts = isUpdate ? coreArtifacts : [...coreArtifacts, ...ancillaryArtifacts];
228
+ // During updates, also install ancillary artifacts that don't yet exist at the destination
229
+ // (e.g. new skills added in a newer version). Existing ones are preserved to keep user customizations.
230
+ const newAncillaryArtifacts = isUpdate
231
+ ? ancillaryArtifacts.filter(({ dest }) => !existsSync(dest))
232
+ : ancillaryArtifacts;
233
+ const artifacts = [...coreArtifacts, ...newAncillaryArtifacts];
195
234
 
196
235
  let allOk = true;
197
236
  for (const { src, dest, label } of artifacts) {
@@ -200,14 +239,20 @@ function install(flags) {
200
239
  }
201
240
  }
202
241
 
242
+ if (installed && !removeDeprecatedSkills(targetRoot)) {
243
+ allOk = false;
244
+ }
245
+
203
246
  console.log();
204
247
  if (allOk) {
205
- const verb = isUpdate ? "updated" : "installed";
248
+ const verb = isUpdate ? "updated" : isReinstall ? "reinstalled" : "installed";
206
249
  console.log(`✓ ${BRAND} ${verb} to ${targetRoot}`);
207
- } else {
208
- console.error(`⚠ Some artifacts could not be ${isUpdate ? "updated" : "installed"}.`);
209
- process.exit(1);
250
+ return;
210
251
  }
252
+
253
+ const verb = isUpdate ? "updated" : isReinstall ? "reinstalled" : "installed";
254
+ console.error(`⚠ Some artifacts could not be ${verb}.`);
255
+ process.exit(1);
211
256
  }
212
257
 
213
258
  const flags = parseArgs(process.argv);
@@ -146,7 +146,7 @@ If the work is mostly reasoning rather than data collection, prefer a PromptEmit
146
146
  - prompt once for a background check (oneTime)
147
147
  - prompt + `runInterval` for a fixed maintenance loop (timed)
148
148
 
149
- This is the closest analogue to Claude's session-scoped `/loop` behavior in this extension.
149
+ This is the closest analogue to Claude's session-scoped `/tap-loop` behavior in this extension.
150
150
 
151
151
  ## Borrow from the official SDK examples
152
152
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: create-provider
2
+ name: tap-create-provider
3
3
  description: "Create an external tool provider that connects to ※ tap. Use when the user says 'create a provider', 'build a provider', 'scaffold a provider', 'add an external tool', 'connect a service to tap', or wants to extend Copilot with tools written in any language."
4
4
  argument-hint: "<what the provider should do>"
5
5
  user-invocable: true
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: loop
2
+ name: tap-loop
3
3
  description: "Run a prompt on a recurring schedule or when idle. Use when the user says 'loop', 'every 5 minutes', 'check periodically', 'keep watching', 'repeat this', 'run when idle', or wants any prompt to re-run automatically."
4
4
  argument-hint: "<interval|idle> <prompt>"
5
5
  user-invocable: true
@@ -17,7 +17,7 @@ Interpret the invocation as:
17
17
  Example (timed):
18
18
 
19
19
  ```text
20
- /loop 5m check the deploy
20
+ /tap-loop 5m check the deploy
21
21
  ```
22
22
 
23
23
  means:
@@ -28,7 +28,7 @@ means:
28
28
  Example (idle):
29
29
 
30
30
  ```text
31
- /loop idle check the deploy
31
+ /tap-loop idle check the deploy
32
32
  ```
33
33
 
34
34
  means:
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: monitor
2
+ name: tap-monitor
3
3
  description: "Start a self-tuning command monitor. Use when the user says 'monitor', 'watch', 'tail', 'track', 'keep an eye on', or wants a shell command to run continuously while Copilot automatically reviews and tunes the output filters over time."
4
4
  argument-hint: "<shell-command>"
5
5
  user-invocable: true
@@ -14,7 +14,7 @@ The entire invocation is the shell command to run continuously.
14
14
  Example:
15
15
 
16
16
  ```text
17
- /monitor tail -f /var/log/app.log
17
+ /tap-monitor tail -f /var/log/app.log
18
18
  ```
19
19
 
20
20
  means:
package/dist/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "1.1.4"
2
+ "version": "2.0.0"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "copilot-tap-extension",
3
- "version": "1.1.4",
3
+ "version": "2.0.0",
4
4
  "description": "Copilot CLI extension for background event emitters, event streams, and session injection.",
5
5
  "type": "module",
6
6
  "license": "MIT",