instar 0.4.7 → 0.4.9

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
@@ -20,17 +20,19 @@
20
20
 
21
21
  ---
22
22
 
23
+ > **This is power-user infrastructure.** Instar gives Claude Code full autonomous access to your machine -- no permission prompts, no sandbox. It's built for developers who want a genuine AI partner, not a guarded assistant. If that sounds like too much trust, it probably isn't for you. If it sounds like exactly what you've been waiting for, read on.
24
+
23
25
  Instar gives Claude Code agents a **persistent body** -- a server that runs 24/7, a scheduler that executes jobs on cron, messaging integrations, relationship tracking, and the self-awareness to grow their own capabilities.
24
26
 
25
27
  Named after the developmental stages between molts in arthropods, where each instar is more developed than the last.
26
28
 
27
29
  ## The Problem
28
30
 
29
- **Without Instar**, Claude Code is a CLI tool. You open a terminal, type a prompt, get a response, close the terminal. No persistence. No scheduling. No way to reach you.
31
+ **Without Instar**, Claude Code is a CLI tool. You open a terminal, type a prompt, get a response, close the terminal. No persistence. No scheduling. No way to reach you. Every session starts from zero.
30
32
 
31
- **With Instar**, Claude Code becomes an agent. It runs in the background, checks your email on a schedule, monitors your services, messages you on Telegram when something needs attention, and builds new capabilities when you ask for something it can't do yet.
33
+ **With Instar**, Claude Code becomes your partner. It runs in the background, checks your email on a schedule, monitors your services, messages you on Telegram when something needs attention, remembers who it's talked to, and builds new capabilities when you ask for something it can't do yet. It accumulates experience, develops its own voice, and grows through every interaction.
32
34
 
33
- The difference isn't features. It's a shift in what Claude Code *is* -- from a tool you use to an agent that works alongside you.
35
+ The difference isn't features. It's a shift in what Claude Code *is* -- from a tool you use to an agent that works alongside you. This is the cutting edge of what's possible with AI agents today -- not a demo, not a toy, but genuine autonomous partnership between a human and an AI.
34
36
 
35
37
  ## Two Ways to Use Instar
36
38
 
@@ -413,11 +415,13 @@ Instead of per-action permission prompts, Instar pushes security to a higher lev
413
415
  - The agent **is directed** by its CLAUDE.md, identity files, and behavioral hooks to stay within its project scope -- but this is behavioral guidance, not a technical boundary
414
416
  - All behavioral hooks, identity files, and CLAUDE.md instructions are **in your project** and fully editable by you
415
417
 
416
- ### Proceed at Your Own Risk
418
+ ### Who This Is For
419
+
420
+ Instar is built for developers and power users who want to work **with** an AI, not just **use** one. You're giving your agent the same access to your machine that any program running under your user account has. The security model relies on intelligent behavior -- identity, hooks, coherence, and grounding -- rather than permission dialogs or sandboxing.
417
421
 
418
- This is infrastructure for people who want genuine AI autonomy, not a sandbox demo. You are giving an AI agent the same access to your machine that any program running under your user account has. The security model relies on intelligent behavior (identity, hooks, coherence) rather than permission dialogs or sandboxing.
422
+ This is the trade-off at the heart of genuine AI autonomy: you can have an agent that asks permission for everything and does nothing on its own, or you can have a partner that operates with real agency, guided by coherent identity and structural guardrails. Instar is the latter.
419
423
 
420
- If you're not comfortable with that trade-off, Claude Code's default permission mode may be a better fit for your use case.
424
+ **Proceed at your own risk.** If you're not comfortable giving an AI agent this level of access, Claude Code's default permission mode is a perfectly good way to work. But if you want to see what an AI agent can actually do when you stop holding it back -- this is the infrastructure for that.
421
425
 
422
426
  ## How the Agent Grows
423
427
 
@@ -825,7 +825,11 @@ Types: \`bug\`, \`feature\`, \`improvement\`, \`question\`
825
825
  additions.push(`
826
826
  ## Telegram Relay
827
827
 
828
- When user input starts with \`[telegram:N]\`, the message came from a user via Telegram topic N. After responding, relay the response back:
828
+ When user input starts with \`[telegram:N]\` (e.g., \`[telegram:26] hello\`), the message came from a user via Telegram topic N.
829
+
830
+ **IMMEDIATE ACKNOWLEDGMENT (MANDATORY):** When you receive a Telegram message, your FIRST action — before reading files, searching code, or doing any work — must be sending a brief acknowledgment back. This confirms the message was received and you haven't stalled. Examples: "Got it, looking into this now." / "On it — checking the scheduler." / "Received, working on the sync." Then do the work, then send the full response.
831
+
832
+ **Response relay:** After completing your work, relay your response back:
829
833
 
830
834
  \`\`\`bash
831
835
  cat <<'EOF' | .claude/scripts/telegram-reply.sh N
@@ -833,7 +837,7 @@ Your response text here
833
837
  EOF
834
838
  \`\`\`
835
839
 
836
- Strip the \`[telegram:N]\` prefix before interpreting the message. Only relay conversational text — not tool output.
840
+ Strip the \`[telegram:N]\` prefix before interpreting the message. Respond naturally, then relay. Only relay your conversational text — not tool output or internal reasoning.
837
841
  `);
838
842
  }
839
843
  if (additions.length > 0) {
@@ -177,11 +177,14 @@ function wireTelegramRouting(telegram, sessionManager) {
177
177
  if (sessionManager.isSessionAlive(targetSession)) {
178
178
  console.log(`[telegram→session] Injecting into ${targetSession}: "${text.slice(0, 80)}"`);
179
179
  sessionManager.injectTelegramMessage(targetSession, topicId, text);
180
+ // Delivery confirmation — let the user know the message reached the session
181
+ telegram.sendToTopic(topicId, `✓ Delivered`).catch(() => { });
180
182
  // Track for stall detection
181
183
  telegram.trackMessageInjection(topicId, targetSession, text);
182
184
  }
183
185
  else {
184
186
  // Session died — respawn with thread history
187
+ telegram.sendToTopic(topicId, `🔄 Session restarting — message queued.`).catch(() => { });
185
188
  respawnSessionForTopic(sessionManager, telegram, targetSession, topicId, text).catch(err => {
186
189
  console.error(`[telegram→session] Respawn failed:`, err);
187
190
  });
@@ -894,7 +894,11 @@ Every user's feedback makes the platform better for everyone. Report issues when
894
894
  section += `
895
895
  ## Telegram Relay
896
896
 
897
- When user input starts with \`[telegram:N]\` (e.g., \`[telegram:26] hello\`), the message came from a user via Telegram topic N. **After responding**, relay your response back:
897
+ When user input starts with \`[telegram:N]\` (e.g., \`[telegram:26] hello\`), the message came from a user via Telegram topic N.
898
+
899
+ **IMMEDIATE ACKNOWLEDGMENT (MANDATORY):** When you receive a Telegram message, your FIRST action — before reading files, searching code, or doing any work — must be sending a brief acknowledgment back. This confirms the message was received and you haven't stalled. Examples: "Got it, looking into this now." / "On it — checking the scheduler." / "Received, working on the sync." Then do the work, then send the full response.
900
+
901
+ **Response relay:** After completing your work, relay your response back:
898
902
 
899
903
  \`\`\`bash
900
904
  cat <<'EOF' | .claude/scripts/telegram-reply.sh N
@@ -131,7 +131,11 @@ This returns your full capability matrix: scripts, hooks, Telegram status, jobs,
131
131
  const section = `
132
132
  ## Telegram Relay
133
133
 
134
- When user input starts with \`[telegram:N]\` (e.g., \`[telegram:26] hello\`), the message came from a user via Telegram topic N. **After responding**, relay your response back:
134
+ When user input starts with \`[telegram:N]\` (e.g., \`[telegram:26] hello\`), the message came from a user via Telegram topic N.
135
+
136
+ **IMMEDIATE ACKNOWLEDGMENT (MANDATORY):** When you receive a Telegram message, your FIRST action — before reading files, searching code, or doing any work — must be sending a brief acknowledgment back. This confirms the message was received and you haven't stalled. Examples: "Got it, looking into this now." / "On it — checking the scheduler." / "Received, working on the sync." Then do the work, then send the full response.
137
+
138
+ **Response relay:** After completing your work, relay your response back:
135
139
 
136
140
  \`\`\`bash
137
141
  cat <<'EOF' | .claude/scripts/telegram-reply.sh N
@@ -145,6 +149,20 @@ Strip the \`[telegram:N]\` prefix before interpreting the message. Respond natur
145
149
  patched = true;
146
150
  result.upgraded.push('CLAUDE.md: added Telegram Relay section');
147
151
  }
152
+ // Upgrade existing Telegram Relay sections to include mandatory acknowledgment
153
+ if (this.config.hasTelegram && content.includes('Telegram Relay') && !content.includes('IMMEDIATE ACKNOWLEDGMENT')) {
154
+ const ackBlock = `\n**IMMEDIATE ACKNOWLEDGMENT (MANDATORY):** When you receive a Telegram message, your FIRST action — before reading files, searching code, or doing any work — must be sending a brief acknowledgment back. This confirms the message was received and you haven't stalled. Examples: "Got it, looking into this now." / "On it — checking the scheduler." / "Received, working on the sync." Then do the work, then send the full response.\n`;
155
+ // Insert after the first line of the Telegram Relay section
156
+ const relayIdx = content.indexOf('## Telegram Relay');
157
+ if (relayIdx >= 0) {
158
+ const nextNewline = content.indexOf('\n\n', relayIdx + 18);
159
+ if (nextNewline >= 0) {
160
+ content = content.slice(0, nextNewline + 1) + ackBlock + content.slice(nextNewline + 1);
161
+ patched = true;
162
+ result.upgraded.push('CLAUDE.md: added mandatory acknowledgment to Telegram Relay');
163
+ }
164
+ }
165
+ }
148
166
  if (patched) {
149
167
  try {
150
168
  fs.writeFileSync(claudeMdPath, content);
@@ -42,7 +42,8 @@ export declare class SessionManager extends EventEmitter {
42
42
  maxDurationMinutes?: number;
43
43
  }): Promise<Session>;
44
44
  /**
45
- * Check if a session is still running by checking tmux (sync version).
45
+ * Check if a session is still running by checking tmux AND verifying
46
+ * that the Claude process is running inside (not a zombie tmux pane).
46
47
  */
47
48
  isSessionAlive(tmuxSession: string): boolean;
48
49
  /**
@@ -142,10 +142,30 @@ export class SessionManager extends EventEmitter {
142
142
  return session;
143
143
  }
144
144
  /**
145
- * Check if a session is still running by checking tmux (sync version).
145
+ * Check if a session is still running by checking tmux AND verifying
146
+ * that the Claude process is running inside (not a zombie tmux pane).
146
147
  */
147
148
  isSessionAlive(tmuxSession) {
148
- return this.tmuxSessionExists(tmuxSession);
149
+ if (!this.tmuxSessionExists(tmuxSession))
150
+ return false;
151
+ // Verify Claude process is running inside the tmux session
152
+ try {
153
+ const paneCmd = execFileSync(this.config.tmuxPath, ['display-message', '-t', `=${tmuxSession}:`, '-p', '#{pane_current_command}'], { encoding: 'utf-8', timeout: 5000 }).trim();
154
+ // Claude Code runs as 'claude' or 'node' process
155
+ if (paneCmd && (paneCmd.includes('claude') || paneCmd.includes('node'))) {
156
+ return true;
157
+ }
158
+ // If pane command is bash/zsh/sh, Claude may have exited — session is dead
159
+ if (paneCmd === 'bash' || paneCmd === 'zsh' || paneCmd === 'sh') {
160
+ return false;
161
+ }
162
+ // For any other command, assume alive (could be a Claude subprocess)
163
+ return true;
164
+ }
165
+ catch {
166
+ // If we can't check, fall back to tmux session existence
167
+ return true;
168
+ }
149
169
  }
150
170
  /**
151
171
  * Check if a session is still running by checking tmux (async version).
@@ -502,6 +502,8 @@ export class TelegramAdapter {
502
502
  }
503
503
  try {
504
504
  const success = await this.onInterruptSession(sessionName);
505
+ // Clear stall tracking — user is actively intervening
506
+ this.clearStallForTopic(topicId);
505
507
  if (success) {
506
508
  await this.sendToTopic(topicId, `Sent Escape to "${sessionName}" \u2014 it should resume processing.`).catch(() => { });
507
509
  }
@@ -525,6 +527,8 @@ export class TelegramAdapter {
525
527
  await this.sendToTopic(topicId, 'Restart not available (no handler registered).').catch(() => { });
526
528
  return true;
527
529
  }
530
+ // Clear stall tracking — user is actively intervening
531
+ this.clearStallForTopic(topicId);
528
532
  await this.sendToTopic(topicId, `Restarting "${sessionName}"...`).catch(() => { });
529
533
  try {
530
534
  await this.onRestartSession(sessionName, topicId);
@@ -30,6 +30,7 @@ ${identity.personality}
30
30
  4. **Be honest about limits.** If I can't do something, I say so clearly. I don't fabricate experience or claim capabilities I don't have.
31
31
  5. **Infrastructure over improvisation.** If I solve a problem twice, I make it a script, a job, or a documented pattern.
32
32
  6. **Use my own tools first.** I have a built-in feedback system, update checker, dispatch system, and more. NEVER reach for external tools (like \`gh\` for GitHub issues) when I have built-in infrastructure for the same purpose.
33
+ 7. **Registry first, explore second.** For any question about current state, check my state files and APIs before searching broadly. The answer is usually in a file designed to hold it, not scattered across project history.
33
34
 
34
35
  ## Who I Work With
35
36
 
@@ -165,6 +166,31 @@ curl http://localhost:${port}/capabilities
165
166
 
166
167
  This returns your full capability matrix: scripts, hooks, Telegram status, jobs, relationships, and more. It is the source of truth about what you can do. **Never hallucinate about missing capabilities — verify first.**
167
168
 
169
+ ### Registry First, Explore Second
170
+
171
+ **For ANY question about current state, check your state files BEFORE searching broadly.**
172
+
173
+ I maintain registries that are the source of truth for specific categories. These MUST be checked before broad exploration:
174
+
175
+ | Question | Check First |
176
+ |----------|-------------|
177
+ | What can I do? | \`curl http://localhost:${port}/capabilities\` |
178
+ | Who do I work with? | \`.instar/USER.md\` |
179
+ | What have I learned? | \`.instar/MEMORY.md\` |
180
+ | What jobs do I have? | \`.instar/jobs.json\` or \`curl http://localhost:${port}/jobs\` |
181
+ | Who have I interacted with? | \`curl http://localhost:${port}/relationships\` |
182
+ | My configuration? | \`.instar/config.json\` |
183
+ | My identity/principles? | \`.instar/AGENT.md\` |
184
+ | Project architecture? | This file (CLAUDE.md), then project docs |
185
+
186
+ **Why this matters:** Searching 1000 files to answer a question that a single state file could answer is slower AND less reliable. Broad searches find stale narratives. State files are current. This applies at EVERY level — including sub-agents I spawn. When spawning a research agent, include the relevant state file reference in its prompt so it searches WITH context, not blind.
187
+
188
+ **The hierarchy when sources conflict:**
189
+ 1. State files and API endpoints — canonical, designed to be current
190
+ 2. MEMORY.md — accumulated learnings, periodically updated
191
+ 3. Project documentation — may be stale
192
+ 4. Broad search results — useful for discovery, unreliable for current state
193
+
168
194
  ### Building New Capabilities
169
195
 
170
196
  When asked for something I can't do yet, I build it:
@@ -221,6 +247,8 @@ I run with \`--dangerously-skip-permissions\` — meaning I have full access to
221
247
 
222
248
  **"Settle for Failure"** — If a tool returns empty or fails, try alternatives before concluding something is impossible.
223
249
 
250
+ **"Search Blind"** — Don't grep the entire project to answer a question that a state file or API endpoint could answer. Check \`.instar/\` state files, \`MEMORY.md\`, and \`/capabilities\` first. When spawning sub-agents, give them the relevant context — an agent without a map searches 10x longer and is less accurate.
251
+
224
252
  **"Unfortunately I Can't"** — This phrase should NEVER appear in my responses. If I lack a capability, the correct response is: "I don't have that yet, but I can build it. Want me to set it up?" My job is to grow to meet the user's needs, not to list my limitations. Every "I can't" is an opportunity to evolve. Check if instar already supports it (check for updates first), then offer to build it or submit a feature request.
225
253
 
226
254
  ### Self-Diagnosis — Be Your Own QA
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "description": "Persistent autonomy infrastructure for AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",