@@ -40,23 +40,14 @@ func getPluginPath(ctx context.Context) (string, error) {
4040}
4141
4242// InstallHooks writes the Entire plugin file to .opencode/plugins/entire.ts.
43- // Returns 1 if the plugin was installed, 0 if already present (idempotent).
43+ // Returns 1 if the plugin was written, 0 if already up-to-date (idempotent).
44+ // If the file exists but content differs (e.g., localDev vs production), it is rewritten.
4445func (a * OpenCodeAgent ) InstallHooks (ctx context.Context , localDev bool , force bool ) (int , error ) {
4546 pluginPath , err := getPluginPath (ctx )
4647 if err != nil {
4748 return 0 , err
4849 }
4950
50- // Check if already installed (idempotent) unless force
51- if ! force {
52- if _ , err := os .Stat (pluginPath ); err == nil {
53- data , readErr := os .ReadFile (pluginPath ) //nolint:gosec // Path constructed from repo root
54- if readErr == nil && strings .Contains (string (data ), entireMarker ) {
55- return 0 , nil // Already installed
56- }
57- }
58- }
59-
6051 // Build the command prefix
6152 var cmdPrefix string
6253 if localDev {
@@ -68,6 +59,15 @@ func (a *OpenCodeAgent) InstallHooks(ctx context.Context, localDev bool, force b
6859 // Generate plugin content from template
6960 content := strings .ReplaceAll (pluginTemplate , entireCmdPlaceholder , cmdPrefix )
7061
62+ // Check if already installed with identical content (idempotent) unless force
63+ if ! force {
64+ if existing , readErr := os .ReadFile (pluginPath ); readErr == nil { //nolint:gosec // Path constructed from repo root
65+ if string (existing ) == content {
66+ return 0 , nil // Already up-to-date
67+ }
68+ }
69+ }
70+
7171 // Ensure directory exists
7272 pluginDir := filepath .Dir (pluginPath )
7373 //nolint:gosec // G301: Plugin directory needs standard permissions
0 commit comments