add version subcommand, bump to 1.1.0
7 files changed,  +141, -5
M AGENTS.md
+1, -1
1@@ -8,4 +8,4 @@ Use TDD. Break up large files into smaller, cohesive units that implement an ope
2 
3 Use descriptive error messages meant for the user -- **THINK** = what steps does the user need to take to accomplish the command successfully.  Provide guidance on what to do next, not details about the internal structure of the application.
4 
5-The application uses two different APIs - one suitable for a human = `bug new`, `bug edit`, `bug comment`, `bug read`, etc. These should be lenient and help the user achieve their intent.  There is a separate API nested under `bug agent` that has similar functionality but is more strict, suitable for use by an agent to collaborate with the user.  When new features are added, update README.md with instructions for the human and SKILL.md with instructions for the agent.
6+The application uses two different APIs - one suitable for a human = `bug new`, `bug edit`, `bug comment`, `bug read`, etc. These should be lenient and help the user achieve their intent.  There is a separate API nested under `bug agent` that has similar functionality but is more strict, suitable for use by an agent to collaborate with the user.  When new features are added, update README.md with instructions for the human and SKILL.md with instructions for the agent. Updates to SKILL.md must specify a minimum version number (e.g. `(since v1.0.0)`) for each new feature, so agents can run `bug version` to check whether the installed binary supports it.
M README.md
+10, -0
 1@@ -146,6 +146,16 @@ bug remove abc1234                # Same as above (alias)
 2 
 3 Note: Individual comments cannot be removed. Use `bug rm <bug-id>` to remove the entire issue including all comments.
 4 
 5+### Check Version
 6+
 7+Print the version of the installed `bug` binary:
 8+
 9+```bash
10+bug version              # Prints e.g. "bug version 1.0.1"
11+```
12+
13+The version is embedded at build time from the `version` field in `flake.nix`. Agents use this to determine which features are available in the installed binary.
14+
15 ## IDs: Short vs Full
16 
17 Bug IDs are 64-character hex strings, but the CLI accepts shortened prefixes:
M SKILL.md
+19, -3
 1@@ -13,6 +13,8 @@ The `bug` CLI tool provides a dual API for issue tracking:
 2 
 3 **Core principle:** Always use commands under `bug agent` when acting as an agent. These commands are non-interactive, require explicit flags, and use the agent identity created during `bug init`.
 4 
 5+**Check the version first:** Run `bug version` (e.g. `bug version 1.0.1`) before starting work so you know which features are available in the installed binary. The version is embedded at build time from the `version` field in `flake.nix`.
 6+
 7 **Announce at start:** "I'm using the bug-cli-agent skill to collaborate on this issue."
 8 
 9 ## Typical Collaboration Workflow
10@@ -131,7 +133,7 @@ bug agent new --title "CI Failure" --from-file /tmp/description.md
11   - `--from-file <path>`: Read message from a file
12 
13 **Optional flags:**
14-- `--parent <bugID>`: Link the new issue under a parent issue (short or full ID)
15+- `--parent <bugID>`: Link the new issue under a parent issue (short or full ID) (since v1.0.0)
16 
17 **Important:** `--message`, `--stdin`, and `--from-file` are **mutually exclusive**. You must choose exactly one method to provide the message content.
18 
19@@ -248,7 +250,7 @@ bug agent edit abc1234 --parent def5678
20   - `--message "..."`: Provide message as a command-line string
21   - `--stdin`: Read message from standard input
22   - `--from-file <path>`: Read message from a file
23-- `--parent <bugID>`: Parent issue short or full ID (optional, issues only; at least one of `--title`, message content, or `--parent` must be provided)
24+- `--parent <bugID>`: Parent issue short or full ID (optional, issues only; at least one of `--title`, message content, or `--parent` must be provided) (since v1.0.0)
25 
26 **Note:** A parent link can only be added when the issue has none; parent links cannot be changed or removed afterwards. Links that would close a dependency cycle are rejected.
27 
28@@ -310,7 +312,7 @@ New findings:
29 EOF
30 ```
31 
32-### Tracking Epics and Subtasks with Parent Links
33+### Tracking Epics and Subtasks with Parent Links (since v1.0.0)
34 
35 Use `--parent` to group subtasks under a parent epic or tracking issue. In `bug ls`, children nest under their parent with tree markers (`├─`, `└─`).
36 
37@@ -370,6 +372,20 @@ bug agent remove abc1234
38 
39 **Note:** Individual comments cannot be removed. Use this to remove the entire issue.
40 
41+### bug version
42+
43+Print the version of the installed `bug` binary.
44+
45+```bash
46+bug version
47+```
48+
49+**Output:** `bug version <version>` (e.g. `bug version 1.0.1`), matching the `version` field in `flake.nix`.
50+
51+**Use this to:**
52+- Check which features are available before starting work
53+- Report the binary version when debugging unexpected behavior
54+
55 ## Important Notes
56 
57 ### Agent Identity
M flake.nix
+1, -1
1@@ -12,7 +12,7 @@
2         pkgs = nixpkgs.legacyPackages.${system};
3 
4         # Read the version from go.mod or use a default
5-        version = "1.0.1";
6+        version = "1.1.0";
7 
8         # Build the bug CLI tool
9         bug = pkgs.buildGoModule {
M main.go
+1, -0
1@@ -2123,6 +2123,7 @@ func init() {
2 	rootCmd.AddCommand(termCmd)  // NEW: Add term command
3 	rootCmd.AddCommand(openCmd)  // NEW: Add open command
4 	rootCmd.AddCommand(closeCmd) // NEW: Add close command
5+	rootCmd.AddCommand(versionCmd)
6 
7 	// Add agent command with its subcommands
8 	agentCmd.AddCommand(agentNewCmd)
A version.go
+36, -0
 1@@ -0,0 +1,36 @@
 2+package main
 3+
 4+import (
 5+	"fmt"
 6+
 7+	"github.com/spf13/cobra"
 8+)
 9+
10+// version is set at build time via ldflags (-X main.version=...).
11+// Defaults to "dev" for local go builds.
12+var version = "dev"
13+
14+// formatVersion returns the user-facing version string.
15+func formatVersion() string {
16+	return fmt.Sprintf("bug version %s", version)
17+}
18+
19+func runVersion(cmd *cobra.Command) error {
20+	cmd.Println(formatVersion())
21+	return nil
22+}
23+
24+var versionCmd = &cobra.Command{
25+	Use:   "version",
26+	Short: "Print the bug CLI version",
27+	Long: `Print the version of the bug CLI.
28+
29+The version is embedded at build time from the version field in flake.nix.
30+This helps agents know which features are available in the installed binary.
31+
32+Example:
33+  bug version`,
34+	RunE: func(cmd *cobra.Command, args []string) error {
35+		return runVersion(cmd)
36+	},
37+}
A version_test.go
+73, -0
 1@@ -0,0 +1,73 @@
 2+package main
 3+
 4+import (
 5+	"bytes"
 6+	"strings"
 7+	"testing"
 8+)
 9+
10+func executeCommand(args ...string) (string, error) {
11+	buf := new(bytes.Buffer)
12+	rootCmd.SetOut(buf)
13+	rootCmd.SetErr(buf)
14+	rootCmd.SetArgs(args)
15+	defer rootCmd.SetArgs([]string{})
16+	out, err := func() (string, error) {
17+		err := rootCmd.Execute()
18+		return buf.String(), err
19+	}()
20+	return out, err
21+}
22+
23+func TestVersionCommandRegistered(t *testing.T) {
24+	found := false
25+	for _, cmd := range rootCmd.Commands() {
26+		if cmd.Name() == "version" {
27+			found = true
28+			break
29+		}
30+	}
31+	if !found {
32+		t.Fatalf("expected 'version' subcommand to be registered on rootCmd")
33+	}
34+}
35+
36+func TestVersionOutputFormat(t *testing.T) {
37+	out, err := executeCommand("version")
38+	if err != nil {
39+		t.Fatalf("version command failed: %v", err)
40+	}
41+	trimmed := strings.TrimSpace(out)
42+	if !strings.HasPrefix(trimmed, "bug version ") {
43+		t.Errorf("expected output to start with %q, got %q", "bug version ", trimmed)
44+	}
45+	ver := strings.TrimSpace(strings.TrimPrefix(trimmed, "bug version "))
46+	if ver == "" {
47+		t.Errorf("version string is empty, got %q", trimmed)
48+	}
49+}
50+
51+func TestVersionReflectsVersionVar(t *testing.T) {
52+	orig := version
53+	version = "9.9.9-test"
54+	defer func() { version = orig }()
55+
56+	out, err := executeCommand("version")
57+	if err != nil {
58+		t.Fatalf("version command failed: %v", err)
59+	}
60+	expected := "bug version 9.9.9-test"
61+	if strings.TrimSpace(out) != expected {
62+		t.Errorf("expected %q, got %q", expected, strings.TrimSpace(out))
63+	}
64+}
65+
66+func TestFormatVersion(t *testing.T) {
67+	orig := version
68+	version = "1.0.1"
69+	defer func() { version = orig }()
70+
71+	if got := formatVersion(); got != "bug version 1.0.1" {
72+		t.Errorf("formatVersion() = %q, want %q", got, "bug version 1.0.1")
73+	}
74+}