@kpnpm/homie 0.1.0 → 0.1.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.
@@ -1,9 +1,9 @@
1
1
  // homie — OpenCode V2 plugin.
2
2
  //
3
- // Injects the homie personality into every model call's system context at the
4
- // active level, persists /homie level switches, registers the /homie command
5
- // and skill. Reuses the shared instruction builder so Claude Code, Codex, and
6
- // OpenCode all read one source of truth.
3
+ // Registers the /homie command and skill, persists level switches, and
4
+ // injects the homie personality into every model call's system context at
5
+ // the active level. Command replies are one plain line — the full ruleset
6
+ // is delivered invisibly through the context hook, never dumped into chat.
7
7
  //
8
8
  // Add to your opencode.json:
9
9
  // { "plugins": ["@kpnpm/homie"] }
@@ -19,8 +19,8 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
19
19
 
20
20
  // The shared instruction builder is CommonJS; bridge to it from this ES module.
21
21
  const require = createRequire(import.meta.url);
22
- const { getChillInstructions } = require('../../hooks/homie-instructions');
23
- const { getDefaultLevel, normalizeLevel } = require('../../hooks/homie-config');
22
+ const { getHomieInstructions } = require('../../hooks/homie-instructions');
23
+ const { getDefaultLevel, normalizeLevel, writeDefaultLevel } = require('../../hooks/homie-config');
24
24
 
25
25
  // OpenCode has no flag-file convention of its own; keep the level beside its config.
26
26
  const statePath = path.join(
@@ -42,16 +42,17 @@ function writeLevel(level) {
42
42
  fs.writeFileSync(statePath, level);
43
43
  }
44
44
 
45
+ // Returns the applied level, null for an unrecognized level, or undefined
46
+ // when nothing changed (bare /homie while already on → report-only).
45
47
  // `off` is persisted like any level; the context hook reads it and stays
46
- // silent. An unrecognized level leaves the current one alone. Bare /homie
47
- // turns the voice on at yo (per SKILL.md); with any level active the command
48
- // just reports — the execute() reply shows the current level.
48
+ // silent. Bare /homie turns the voice on at yo (per SKILL.md).
49
49
  function persistLevel(args) {
50
50
  const wanted = String(args == null ? '' : args).trim();
51
- if (!wanted && readLevel() !== 'off') return; // bare /homie: report-only when active
51
+ if (!wanted && readLevel() !== 'off') return undefined;
52
52
  const level = wanted ? normalizeLevel(wanted) : 'yo';
53
- if (!level) return;
53
+ if (!level) return null;
54
54
  writeLevel(level);
55
+ return level;
55
56
  }
56
57
 
57
58
  function readSkill() {
@@ -90,11 +91,32 @@ export default {
90
91
  name: 'homie',
91
92
  description: 'Switch personality level (off/yo/dawg/mafa)',
92
93
  execute: async ({ sessionID, prompt, delivery }) => {
93
- persistLevel(prompt.text);
94
- const level = readLevel();
95
- const text = level === 'off'
96
- ? 'Homie is off — back to the normal tone.'
97
- : 'HOMIE MODE — level: ' + level + '.\n\n' + getChillInstructions(level);
94
+ const wanted = String(prompt.text || '').trim();
95
+ const words = wanted.split(/\s+/).filter(Boolean);
96
+ const first = words[0] || '';
97
+ let text;
98
+
99
+ if (first === 'default') {
100
+ const applied = words[1] ? writeDefaultLevel(words[1]) : null;
101
+ text = applied
102
+ ? 'Homie default set: ' + applied + '. New sessions start at ' + applied + '.'
103
+ : 'Usage: /homie default <level>. Levels: off, yo, dawg, mafa.';
104
+ } else {
105
+ const applied = persistLevel(first);
106
+ const level = readLevel();
107
+ if (first && applied === null) {
108
+ text = 'Unknown level "' + first + '". Levels: off, yo, dawg, mafa.';
109
+ } else if (level === 'off') {
110
+ text = 'Homie off.';
111
+ } else {
112
+ text = 'Homie mode: ' + level + '.';
113
+ }
114
+ }
115
+
116
+ // One plain line only. The context hook below injects the full
117
+ // ruleset into the system context of this same model call, so the
118
+ // confirmation turn is already in voice — without dumping the
119
+ // ruleset into the chat.
98
120
  await ctx.session.prompt({ ...prompt, sessionID, text, delivery });
99
121
  },
100
122
  });
@@ -105,7 +127,7 @@ export default {
105
127
  await ctx.session.hook('context', (event) => {
106
128
  const level = readLevel();
107
129
  if (level === 'off') return;
108
- event.system.push({ type: 'text', text: getChillInstructions(level) });
130
+ event.system.push({ type: 'text', text: getHomieInstructions(level) });
109
131
  });
110
132
  },
111
133
  };
@@ -9,7 +9,7 @@
9
9
  const fs = require('fs');
10
10
  const path = require('path');
11
11
  const { getDefaultLevel, isShellSafe } = require('./homie-config');
12
- const { getChillInstructions } = require('./homie-instructions');
12
+ const { getHomieInstructions } = require('./homie-instructions');
13
13
  const {
14
14
  setLevel,
15
15
  writeHookOutput,
@@ -35,7 +35,7 @@ try {
35
35
  }
36
36
 
37
37
  // 2. Emit the homie ruleset at the default level.
38
- let output = getChillInstructions(level);
38
+ let output = getHomieInstructions(level);
39
39
 
40
40
  // 3. Detect missing statusline config — nudge Claude to help set it up.
41
41
  // Codex and Copilot don't read Claude settings.json; skip the nudge there.
@@ -97,7 +97,7 @@ function getFallbackInstructions(level) {
97
97
  'Switch: /homie yo|dawg|mafa.';
98
98
  }
99
99
 
100
- function getChillInstructions(level) {
100
+ function getHomieInstructions(level) {
101
101
  const effectiveLevel = normalizeLevel(level);
102
102
  if (!effectiveLevel || effectiveLevel === 'off') return '';
103
103
 
@@ -112,5 +112,5 @@ function getChillInstructions(level) {
112
112
  module.exports = {
113
113
  filterSkillBodyForLevel,
114
114
  getFallbackInstructions,
115
- getChillInstructions,
115
+ getHomieInstructions,
116
116
  };
@@ -9,7 +9,7 @@ const {
9
9
  clearLevel,
10
10
  writeHookOutput,
11
11
  } = require('./homie-runtime');
12
- const { getChillInstructions } = require('./homie-instructions');
12
+ const { getHomieInstructions } = require('./homie-instructions');
13
13
 
14
14
  let input = '';
15
15
  let done = false;
@@ -75,7 +75,7 @@ function finish() {
75
75
  // Deliver the new level's ruleset along with the confirmation so the
76
76
  // switch turn itself is already in voice.
77
77
  const header = 'HOMIE MODE CHANGED — level: ' + level;
78
- writeHookOutput('UserPromptSubmit', level, header + '\n\n' + getChillInstructions(level));
78
+ writeHookOutput('UserPromptSubmit', level, header + '\n\n' + getHomieInstructions(level));
79
79
  } else if (level === 'off') {
80
80
  // Persist `off` like any level (plan lesson #7): clearing the flag
81
81
  // races the default logic — an absent flag reads as the default level.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kpnpm/homie",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Personality layer for coding agents. Same code, different voice: yo / dawg / mafa / off.",
5
5
  "keywords": [
6
6
  "opencode-plugin",
@@ -43,4 +43,4 @@
43
43
  "publishConfig": {
44
44
  "access": "public"
45
45
  }
46
- }
46
+ }