@harnessforce/claude-code-plugin 0.3.0 → 0.3.1
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/commands/setup.md
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Harnessforce setup. Walks through checking Node.js, choosing whether to send session content, installing the CLI, running harnessforce init, importing past sessions, and confirming the first event after the restart
|
|
3
|
-
disable-model-invocation: true
|
|
2
|
+
description: Harnessforce setup. Walks through checking Node.js, choosing whether to send session content, installing the CLI, running harnessforce init, importing past sessions, showing the remaining workspace steps, and confirming the first event after the restart
|
|
4
3
|
---
|
|
5
4
|
|
|
6
5
|
# Harnessforce setup
|
|
7
6
|
|
|
8
|
-
Go through the steps below in order, interacting with the user.
|
|
7
|
+
Go through the steps below in order, interacting with the user. Run this setup when the user types `/harnessforce:setup`, or when the user asks to install, connect or set up Harnessforce. Do not run it when the user has not asked for it. Running it again is safe: every step converges to the same state.
|
|
8
|
+
|
|
9
|
+
## How setup ends
|
|
10
|
+
|
|
11
|
+
Setup ends only at one of the endings below, and the last line of the ending is the text shown here, as it is. Do not tell the user that setup has ended at any other point, and do not use words that say setup is finished ("complete", "done" and so on) except in the second ending of part 2.
|
|
12
|
+
|
|
13
|
+
- Node.js is missing or below 18 (step 1): the text in step 1.
|
|
14
|
+
- Stopped part way: "Harnessforce setup stopped at step {n} ({name}). Fix the cause shown above, then run `/harnessforce:setup` again. Steps already done are safe to repeat." Replace `{n}` and `{name}` with the number and the heading of the step that failed.
|
|
15
|
+
- End of part 1 (step 8): "Harnessforce setup, part 1 of 2, is done. Restart Claude Code, then run `/harnessforce:setup` again in the new session. Part 2 checks that the first event arrived."
|
|
16
|
+
- End of part 2 (step 9): "Harnessforce setup is complete."
|
|
17
|
+
|
|
18
|
+
When a command fails, show its output to the user. Whether setup then stops or goes on is written in each step. Errors that other plugins' hooks show do not affect setup: do not stop because of them and do not mention them.
|
|
9
19
|
|
|
10
20
|
## 1. Check Node.js
|
|
11
21
|
|
|
@@ -15,16 +25,20 @@ First run `node --version`. If the command is not found, or the version is below
|
|
|
15
25
|
|
|
16
26
|
## 2. Check whether this run is after the restart
|
|
17
27
|
|
|
18
|
-
If `harnessforce --version` succeeds and the environment variable `HARNESSFORCE_WORKSPACE_ID` of this session is not empty, this is a session restarted after `harnessforce init`. Skip steps 3 to
|
|
28
|
+
If `harnessforce --version` succeeds and the environment variable `HARNESSFORCE_WORKSPACE_ID` of this session is not empty, this is a session restarted after `harnessforce init`. Skip steps 3 to 8 and go to step 9.
|
|
19
29
|
|
|
20
30
|
## 3. Install the CLI
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
If `harnessforce --version` succeeds, do not install anything. Otherwise run the following, then confirm the install with `harnessforce --version`.
|
|
23
33
|
|
|
24
34
|
```sh
|
|
25
35
|
npm install -g @harnessforce/cli
|
|
26
36
|
```
|
|
27
37
|
|
|
38
|
+
If the install fails, show its output and stop at this step. When npm cannot write to its global install location (`EACCES`), also show the following before the last line.
|
|
39
|
+
|
|
40
|
+
> npm cannot write to its global install location. Use a Node.js installed with a version manager such as nvm, or change npm's prefix to your own directory, then try again.
|
|
41
|
+
|
|
28
42
|
## 4. Choose whether to send content
|
|
29
43
|
|
|
30
44
|
Before `harnessforce init`, present the option to send the content of the user's sessions, with "send" selected by default. The login is not done yet at this point, so neither the Workspace to connect nor what it stores is known. Do not change what you show depending on the Workspace; `harnessforce init` decides each category from the Workspace it connects, and writes `0` for a category the Workspace does not store.
|
|
@@ -42,22 +56,42 @@ Use the following option text as it is.
|
|
|
42
56
|
|
|
43
57
|
## 5. Connect to Harnessforce
|
|
44
58
|
|
|
45
|
-
Follow the choice in step 4: run `harnessforce init --send-content` if selected, or `harnessforce init` if not. Tell the user to log in to Harnessforce in the browser and choose one Workspace to connect. If the browser does not open, show the user the URL that `harnessforce init` prints. The command waits up to 5 minutes for the login to complete, so run it with a Bash timeout of 10 minutes.
|
|
59
|
+
Follow the choice in step 4: run `harnessforce init --send-content` if selected, or `harnessforce init` if not. Tell the user to log in to Harnessforce in the browser, or sign up, and choose one Workspace to connect. A user without a Workspace can create one on the same page and continue. If the browser does not open, show the user the URL that `harnessforce init` prints. The command waits up to 5 minutes for the login to complete, so run it with a Bash timeout of 10 minutes.
|
|
46
60
|
|
|
47
61
|
For a Workspace that stores no content, `harnessforce init --send-content` writes the content variables as `0`. It prints a message about that and about Collection & retention in the Workspace settings, and exits with code 0. Do not treat this as a failure; show the printed text to the user as it is.
|
|
48
62
|
|
|
63
|
+
If `harnessforce init` ends with the line saying the CLI version is unsupported and exit code 1, run `npm install -g @harnessforce/cli@latest`, then run this step again. If `harnessforce init` fails for any other reason, show what it printed and stop at this step; a failed `harnessforce init` changes neither the keychain nor the settings files.
|
|
64
|
+
|
|
49
65
|
## 6. Import past sessions
|
|
50
66
|
|
|
51
67
|
Run `harnessforce import` and tell the user, as it is, the imported count it prints, along with the breakdown of sessions that were not imported and the guidance. Do not omit the printed reason and the next action even when the count is 0.
|
|
52
68
|
|
|
53
|
-
|
|
69
|
+
Then run `harnessforce status --json`. If `repository.connected` is `false` (the repository of the working directory is not connected), tell the user the following.
|
|
70
|
+
|
|
71
|
+
> This repository is not connected to the GitHub App, so its sessions were not imported. After connecting it, restart Claude Code and run `/harnessforce:setup` to import them.
|
|
54
72
|
|
|
55
|
-
|
|
73
|
+
If `harnessforce import` fails, show its output and go on; importing is not needed for telemetry and can be run later. Before the last line of the ending, show "Importing past sessions failed. Run `harnessforce import` later." If `harnessforce status --json` fails, show its output and go on.
|
|
74
|
+
|
|
75
|
+
## 7. Show the remaining steps
|
|
76
|
+
|
|
77
|
+
From the result of `harnessforce status --json` in step 6, show the steps that are not done (`status` other than `done` in `steps`, and every step in `admin_steps`) in the order of their numbers, each with its title, who does it, and the URL of its page. Use these titles: step 2 "Connect the GitHub App", step 3 "Assign repositories to a project", step 4 "Set up telemetry", step 5 "Wait for your first run". Steps 2 and 3 are done by an owner or admin, and steps 4 and 5 by the user. For a step the user is not responsible for (steps 2 and 3 when the user's `role` is `member`), add "Send this URL to the person responsible."
|
|
78
|
+
|
|
79
|
+
If `has_seat` is `false`, first show "You don't have a developer seat, so the telemetry you send is not stored." If no step remains, show only "Your workspace is ready." If `harnessforce status --json` failed in step 6, show the URL of the Harnessforce Home (the environment variable `HARNESSFORCE_URL`) instead of the steps.
|
|
80
|
+
|
|
81
|
+
## 8. Ask for a restart
|
|
82
|
+
|
|
83
|
+
If the user also uses Codex, tell them first: restart Codex, then run `/hooks` in Codex and trust the harnessforce `SessionStart`, `PostToolUse`, and `Stop` hooks. Codex runs a hook only after the user trusts it, and `harnessforce init` cannot do this for them.
|
|
84
|
+
|
|
85
|
+
Then end with the following.
|
|
56
86
|
|
|
57
87
|
> Harnessforce setup, part 1 of 2, is done. Restart Claude Code, then run `/harnessforce:setup` again in the new session. Part 2 checks that the first event arrived.
|
|
58
88
|
|
|
59
|
-
##
|
|
89
|
+
## 9. Confirm the first event
|
|
90
|
+
|
|
91
|
+
At the start of this session, the plugin hook sent the session to Harnessforce. Run `harnessforce import` again to import the sessions of repositories connected to the GitHub App after step 6; sessions already imported are not sent twice. Tell the user the result as in step 6.
|
|
92
|
+
|
|
93
|
+
Then run `harnessforce status --json`. If step 5 is `done`, show "Your first run arrived." with the URL of the Harnessforce Home (the environment variable `HARNESSFORCE_URL`). If not, show the Home URL and tell the user to check on the waiting screen for the first run that it was received; if nothing arrives after 15 minutes, follow the checks for each cause shown on the waiting screen. Show the steps that are not done in the same way as step 7.
|
|
60
94
|
|
|
61
|
-
|
|
95
|
+
If `harnessforce import` fails, show its output, go on, and show "Importing past sessions failed. Run `harnessforce import` later." before the last line. If `harnessforce status --json` fails, show its output and the Home URL, and still end with the line below: the settings were made in step 5, so not being able to read the status is not a failure of setup.
|
|
62
96
|
|
|
63
97
|
> Harnessforce setup is complete.
|
package/package.json
CHANGED
|
@@ -1003,7 +1003,7 @@ async function postItems(destination, path, items, fetchImpl, timeoutMs = SEND_T
|
|
|
1003
1003
|
// ../../packages/agent-core/src/issue.ts
|
|
1004
1004
|
const isIssueIdentifier = (value) => isToken(value, 300);
|
|
1005
1005
|
// ../../packages/agent-core/src/using-harnessforce.ts
|
|
1006
|
-
const usingHarnessforceBody = "---\nname: using-harnessforce\ndescription: Use when starting a session in an environment with the Harnessforce hook, when starting work on an Issue, or when asked what is recorded or collected. The hook injects this text into the context at session start.\n---\n\n# Using Harnessforce\n\nThis session has the Harnessforce hook installed. Harnessforce links the work of people and AI to Issues and records it. Follow these rules.\n\n## What is recorded\n\n- Session registration: agent, session ID, repository, branch, commit, start time, and the first prompt ID.\n- Work locations: the repository and branch of each Git working tree the session works in. Paths are not sent.\n- Config snapshot: the structure of the configuration in use (Claude Code only).\n- OTel telemetry: what the user chooses to send.\n- For work on an Issue, `record-run` registers the session as a Run and closes it. It records no Plan, Decision, or Definition of Done.\n\n## What is not collected\n\n- Prompts, responses, tool input and output, and the body of code diffs arrive only when the user sends them (`--send-content` or managed settings) and the Workspace stores that category. The members the Workspace chooses can read them. `harnessforce import` never sends them.\n- Never put these contents, secrets, or environment variable values in MCP tool input or in a record.\n\n## Which hook sends what\n\n- SessionStart: session registration and the config snapshot (Codex sends session registration only).\n- UserPromptSubmit: resends on the first prompt (Claude Code only).\n- Stop: sends the work locations at the end of a turn in which they changed.\n- A failing hook never stops the session. When the hook cannot send, it shows a one-line warning. Tell the user when a warning appears.\n\n## Which skill and tool to use, and when\n\n- For work on a specified Issue ID, or when the environment variable `HARNESSFORCE_ISSUE` is set, follow `record-run` and use `start_run`, `get_issue`, and `complete_run`. An agent that cannot load the skill calls the tools in the same order.\n- Pass the value of the `harnessforce session_id:` line in the context to `start_run`. If there are several, use the last one. If the line is missing, do not guess the session ID, and do not call `start_run` or `complete_run`.\n- Use `propose-improvements` for the analysis of `/harnessforce:tune`.\n- When no Issue is specified, do not start recording a Run.\n\n## Red Flags\n\nStop when one of these thoughts comes up.\n\n| Thought | Reality |\n| --- | --- |\n| An Issue was specified, but the work is small, so recording is unnecessary | Work on a specified Issue is recorded regardless of its size |\n| The session ID line is missing, so I will guess it and call `start_run` | Do not guess. The Run would no longer be linked to the session |\n| Summarizing the content before recording would help | Do not pass content to the tool. It goes beyond what is collected |\n| A warning appeared, but I can ignore it | Sending is not working. Tell the user |\n\n## Priority\n\n1. The user's instructions (CLAUDE.md, AGENTS.md, direct requests). If the user tells you to stop recording, stop recording the Run.\n2. This introduction.\n3. Default behavior.\n\n## Subagents\n\nA subagent that was delegated only a specific task by its parent does not register a Run by following this introduction. The parent registers the Run.\n".replace(/\r\n/g, "\n").replace(/^---\n[\s\S]*?\n---\n+/, "").trimEnd();
|
|
1006
|
+
const usingHarnessforceBody = "---\nname: using-harnessforce\ndescription: Use when starting a session in an environment with the Harnessforce hook, when starting work on an Issue, or when asked what is recorded or collected. The hook injects this text into the context at session start.\n---\n\n# Using Harnessforce\n\nThis session has the Harnessforce hook installed. Harnessforce links the work of people and AI to Issues and records it. Follow these rules.\n\n## What is recorded\n\n- Session registration: agent, session ID, repository, branch, commit, start time, and the first prompt ID.\n- Work locations: the repository and branch of each Git working tree the session works in. Paths are not sent.\n- Config snapshot: the structure of the configuration in use (Claude Code only).\n- OTel telemetry: what the user chooses to send.\n- For work on an Issue, `record-run` registers the session as a Run and closes it. It records no Plan, Decision, or Definition of Done.\n\n## What is not collected\n\n- Prompts, responses, tool input and output, and the body of code diffs arrive only when the user sends them (`--send-content` or managed settings) and the Workspace stores that category. The members the Workspace chooses can read them. `harnessforce import` never sends them.\n- Never put these contents, secrets, or environment variable values in MCP tool input or in a record.\n\n## Which hook sends what\n\n- SessionStart: session registration and the config snapshot (Codex sends session registration only).\n- UserPromptSubmit: resends on the first prompt (Claude Code only).\n- Stop: sends the work locations at the end of a turn in which they changed.\n- A failing hook never stops the session. When the hook cannot send, it shows a one-line warning. Tell the user when a warning appears.\n\n## Which skill and tool to use, and when\n\n- For work on a specified Issue ID, or when the environment variable `HARNESSFORCE_ISSUE` is set, follow `record-run` and use `start_run`, `get_issue`, and `complete_run`. An agent that cannot load the skill calls the tools in the same order.\n- Pass the value of the `harnessforce session_id:` line in the context to `start_run`. If there are several, use the last one. If the line is missing, do not guess the session ID, and do not call `start_run` or `complete_run`.\n- Use `propose-improvements` for the analysis of `/harnessforce:tune`.\n- When no Issue is specified, do not start recording a Run on your own. For work that commits changes, follow \"When no Issue is specified\" in `record-run` and ask the user once whether to link it to an existing Issue.\n\n## Red Flags\n\nStop when one of these thoughts comes up.\n\n| Thought | Reality |\n| --- | --- |\n| An Issue was specified, but the work is small, so recording is unnecessary | Work on a specified Issue is recorded regardless of its size |\n| The session ID line is missing, so I will guess it and call `start_run` | Do not guess. The Run would no longer be linked to the session |\n| Summarizing the content before recording would help | Do not pass content to the tool. It goes beyond what is collected |\n| A warning appeared, but I can ignore it | Sending is not working. Tell the user |\n\n## Priority\n\n1. The user's instructions (CLAUDE.md, AGENTS.md, direct requests). If the user tells you to stop recording, stop recording the Run.\n2. This introduction.\n3. Default behavior.\n\n## Subagents\n\nA subagent that was delegated only a specific task by its parent does not register a Run by following this introduction. The parent registers the Run.\n".replace(/\r\n/g, "\n").replace(/^---\n[\s\S]*?\n---\n+/, "").trimEnd();
|
|
1007
1007
|
// ../../packages/agent-core/src/session-context.ts
|
|
1008
1008
|
const sessionContextLine = (sessionId) => `harnessforce session_id: ${sessionId}`;
|
|
1009
1009
|
const sessionContext = (sessionId) => ({ hookSpecificOutput: {
|
|
@@ -1995,7 +1995,7 @@ async function main() {
|
|
|
1995
1995
|
}),
|
|
1996
1996
|
client: {
|
|
1997
1997
|
component: "claude-code-plugin",
|
|
1998
|
-
version: "0.3.
|
|
1998
|
+
version: "0.3.1",
|
|
1999
1999
|
dev: false
|
|
2000
2000
|
},
|
|
2001
2001
|
isPluginAutoUpdateEffective: (cwd) => isPluginAutoUpdateEffective({
|
|
@@ -9,13 +9,26 @@ Use the tools of the Harnessforce MCP server to link the work to the Issue. The
|
|
|
9
9
|
|
|
10
10
|
## At the start of the work
|
|
11
11
|
|
|
12
|
-
1. Pass the value of `harnessforce session_id: <session_id>` in the context as `session_id`, and register the Run with `start_run`. The Harnessforce plugin adds this line to the context at session start. If there are several, use the last one added. The input is the Issue identifier (`issue_identifier`), `agent` (`claude_code`), and `session_id`.
|
|
12
|
+
1. Pass the value of `harnessforce session_id: <session_id>` in the context as `session_id`, and register the Run with `start_run`. The Harnessforce plugin adds this line to the context at session start. If there are several, use the last one added. The input is the Issue identifier (`issue_identifier`), `agent` (`claude_code`), and `session_id`. Do not pass the repository, branch, or commit: the hook registers the same session and fills them in. Keep the returned `run_id` until the end. If the line is missing from the context, follow "When the session ID is missing" below.
|
|
13
13
|
2. Check the Issue with `get_issue`.
|
|
14
14
|
|
|
15
15
|
## When the session ID changes
|
|
16
16
|
|
|
17
17
|
- If the value of the last `harnessforce session_id:` in the context differs from the value you passed to the previous `start_run` (for example after forking the conversation or running `/clear`), call `start_run` once more with the new value before continuing, and use the returned `run_id` for later `complete_run` calls.
|
|
18
18
|
|
|
19
|
+
## When no Issue is specified
|
|
20
|
+
|
|
21
|
+
Ask the user once whether to link the work to an existing Issue, only when all of the following hold. Do not create an Issue: Issues are GitHub Issues.
|
|
22
|
+
|
|
23
|
+
- The user has not given an Issue identifier. If the current branch name contains an identifier (a branch name `gh-<number>` is passed as `<owner>/<repo>#<number>` of the repository) and `get_issue` resolves it, treat it as the specified Issue and do not ask. If `get_issue` returns `not_found`, treat it as no identifier.
|
|
24
|
+
- The work commits changes. Do not ask for research, answering questions, or conversations that only plan.
|
|
25
|
+
- The context has a `harnessforce session_id:` line.
|
|
26
|
+
- You have not asked yet for the last `harnessforce session_id:` value in the context. If the user declines, do not ask again while the value stays the same. After a fork or `/clear` changes the value, you may ask again.
|
|
27
|
+
|
|
28
|
+
To show the candidates, pick up to 3 words from the summary of the work that are likely to appear in an Issue title, and call `list_issues` once per word with `q` set to `-status:done,canceled <word>` and `sort` set to `updated`. Merge the results, remove duplicates, and show at most 5 Issues, most recently updated first. If the user picks one, call `start_run` with that Issue. If there is no candidate or the user picks none, continue the work without calling `start_run`.
|
|
29
|
+
|
|
30
|
+
If `start_run` returns `forbidden` (a view-only token or a view-only Workspace), tell the user the reason as it is, and do not ask again for that session ID.
|
|
31
|
+
|
|
19
32
|
## At the end of the work
|
|
20
33
|
|
|
21
34
|
- Call `complete_run` with the `run_id`.
|
|
@@ -32,7 +32,7 @@ This session has the Harnessforce hook installed. Harnessforce links the work of
|
|
|
32
32
|
- For work on a specified Issue ID, or when the environment variable `HARNESSFORCE_ISSUE` is set, follow `record-run` and use `start_run`, `get_issue`, and `complete_run`. An agent that cannot load the skill calls the tools in the same order.
|
|
33
33
|
- Pass the value of the `harnessforce session_id:` line in the context to `start_run`. If there are several, use the last one. If the line is missing, do not guess the session ID, and do not call `start_run` or `complete_run`.
|
|
34
34
|
- Use `propose-improvements` for the analysis of `/harnessforce:tune`.
|
|
35
|
-
- When no Issue is specified, do not start recording a Run.
|
|
35
|
+
- When no Issue is specified, do not start recording a Run on your own. For work that commits changes, follow "When no Issue is specified" in `record-run` and ask the user once whether to link it to an existing Issue.
|
|
36
36
|
|
|
37
37
|
## Red Flags
|
|
38
38
|
|