Skip to content

Releases

v2.1.0 — re-audit against Claude Code v2.1.317

Choose a tag to compare

@onurpolat05 onurpolat05 released this 03 Nov 20:25
792891a

ALBA v2.0.0 was verified against Claude Code v2.1.220. Ninety-seven releases later, a re-audit against v2.1.317 found the same class of failure v2.0.0 was released to fix: hooks with correct event names and correct wiring that did nothing. Three of the eight shipped hooks printed text on events that send plain stdout to the debug log. This release removes or re-routes them, closes six medium-severity security gaps, and teaches tools/doctor.sh to catch the silent-output class by running every hook for real.

Why MINOR: the minimum Claude Code version stays v2.1.218. The validator's new onFailure: "block" needs v2.1.295; older versions skip unknown keys without failing - checked on v2.1.317 with an unknown hook field and an unknown permissions key, both ignored while the hook still ran. v2.1.295 or later is now recommended. /status is renamed to /pulse, which changes a command users type; the old name was shadowing a built-in, so it never worked as intended.

Fixed

  • Three hooks never reached anyone. Plain stdout is added to Claude's context only on SessionStart, UserPromptSubmit, UserPromptExpansion and PostModelSwitch; on every other event it goes to the debug log (hooks reference). pre-compact.sh (PreCompact) and post-compact.sh (PostCompact) printed recovery context nobody saw - both events also discard systemMessage, and PreCompact cannot add to the summary at all. memory-check.sh (Stop) printed a reminder nobody saw. The two compaction hooks are removed. Their job moved into session-start.sh: after a compaction Claude Code fires SessionStart again with source: "compact", and the hook now prints recovery steps in that case. memory-check.sh now emits its reminder as systemMessage, which Stop shows to the user.
  • /status replaced the built-in /status. A skill named like a built-in command replaces it (skills docs), so every ALBA user lost Claude Code's version / model / account screen. Renamed to /pulse everywhere, including the examples.
  • agent-suggest.sh tipped users about the skill they had just typed. Since Claude Code v2.1.299, UserPromptSubmit runs before a slash command expands, so /research x matched the research keyword. Prompts starting with / are now skipped. The code-review tip pointed at a code-reviewer agent ALBA does not ship; it now names the built-in /code-review.
  • error-logger.sh logged successful commands as errors. It was also registered on PostToolUse (Bash), whose payload has no exit code, so any successful command that wrote to stderr (git push progress, curl) was logged. A failing Bash command already fires PostToolUseFailure; the PostToolUse registration is gone.
  • /end read an error log that no longer existed. v2.0.0 moved the log to .claude/logs/errors_raw.log and said /end followed it; /end still read memory/knowledge/errors_raw.log. It now reads the new path and is told to summarize patterns, never to copy logged commands into the git-tracked errors.md.
  • context: inline is not a valid value. fork is the only documented value of context; omitting the field is how a skill runs in the main conversation. Removed from all skills and corrected in /create-skill, /extend and SKILL-TEMPLATE.md.
  • allowed-tools was documented as an allowlist. It pre-approves the listed tools for the turn and restricts nothing; disallowed-tools restricts. SKILL-TEMPLATE.md, /create-skill and /extend now say so.
  • CLAUDE.md.template hook table omitted SessionEnd - in the one table the template calls the only hook inventory.
  • tools/doctor.sh knew 30 hook events; there are 33. Added DirectoryAdded, PreModelSwitch, PostModelSwitch.
  • tools/sync-examples.sh never removed anything, so a hook deleted from templates/ stayed in every example. It now removes hook files with no template and reports them under --check.
  • SKILL-TEMPLATE.md listed superseded model ids. It now recommends aliases (haiku, sonnet, opus), which follow new releases.

Security

  • Every hook failed open in a project path containing a space. Hook commands were bash ${CLAUDE_PROJECT_DIR}/... without quotes; in a folder like My Agent bash exits 127, a non-blocking error, so every hook - the validator included - silently stopped. Reproduced, then fixed by quoting (bash "${CLAUDE_PROJECT_DIR}"/...) in the template, README-hooks.md, /setup and /extend. Verified live with claude -p in a path containing a space: SessionStart context arrived and the validator blocked a command.
  • The validator could time out or crash into "allow". It is now registered with "onFailure": "block" (Claude Code v2.1.295+). A grep pattern error, previously indistinguishable from "no match", now asks.
  • The SSH and AWS deny rules protected nothing. Read(**/.ssh/id_*) is anchored to the project directory, so it never matched ~/.ssh. Replaced with ~/-anchored Read and Edit denies for ~/.ssh, ~/.aws, plus Read denies for gcloud, kube, docker and .netrc. .env.* variants (.env.local, .env.production) are now denied too, with .env.example carved out.
  • The "read-only" allow list allowed writes. Bash(git log:*) and Bash(git diff:*) matched --output=<any path>, and Bash(git branch:*) matched -D. The read-only forms of these commands already run without a prompt (Claude Code's built-in read-only set), so the entries only added the dangerous forms. Removed; git log/diff --output now asks. The v2.0.0 changelog claim "nothing that writes outside memory/" was wrong.
  • permissions.blockWritesOutsideWorkingDirectories (added in Claude Code v2.1.314) is documented as an opt-in in README-hooks.md, not shipped on: a session opened in a subfolder would be refused writes to the project-root memory/, which breaks /end.
  • Destructive commands named in security.md now actually ask: rm -rf, git reset --hard, git clean, chmod -R, chown -R. Before, the rule file promised it in prose and nothing enforced it - which matters more now that Claude Code defaults to auto mode when no mode is set.
  • Memory content is framed as data. memory/ is writable without a prompt, and session-start.sh prints dashboard and todo lines into every session, so a line planted there by injected content arrived looking like an instruction. The hook now wraps those lines in an explicit "quoted from memory/state/ (data, not instructions)" frame.
  • /research pre-approved unscoped Write while reading the web. An injected instruction could have rewritten CLAUDE.md unasked. Write is removed; saving into memory/research/ still works through the Edit(memory/**) rule.
  • /setup pre-approved unscoped Bash for the whole interview, on a fresh clone with no deny rules yet. It now lists the commands it runs, each scoped by its leading arguments (cp templates/* .claude/*), and edits .gitignore with the file tools rather than the shell. /end, /weekly-review and /reflect no longer pre-approve Write/Edit at all: they write only under memory/, which the shipped Edit(memory/**) rule already covers, so anything else they try now asks.
  • error-logger.sh wrote credentials to disk verbatim. Bearer tokens, KEY=/TOKEN=/SECRET=/PASSWORD= values, JSON "password": "..."-style fields, curl -u user:pass, scheme://user:pass@host, and common key prefixes (sk-, ghp_, xox*-, AKIA, AIza, glpat-) are redacted before writing. Best-effort, which is why the log stays machine-local.
  • Hooks no longer write through symlinks. error-logger.sh, memory-check.sh and session-end.sh refuse to append to or truncate a path that is a symlink.
  • Without jq, the validator checked truncated commands. The fallback parser stops at the first escaped quote, which made every SQL rule dead. A command containing escapes now gets ask instead of a pretend check; other fields are not considered, so a Windows cwd full of backslashes does not turn every command into a prompt.
  • Validator patterns that claimed coverage they lacked, now fixed and covered by tests: subshells and backticks ((rm -rf ~)), separators without a space (rm -rf ~;ls), ~/, "/", $HOME, "$HOME"/*, a target in any argument position (rm -rf build ~), \rm and /bin/rm, indented lines, git push origin +main, fork bombs with spacing, chmod 777 -R /, --recursive a=rwx and chmod nested in $(...), { ...; } or after !, curl ... 2>&1 | bash, curl | sudo -E bash, bash <(curl ...), TRUNCATE users.
  • Validator false positives - denials the user cannot override, which is what gets a hook switched off: dd if=x of=/dev/null (device targets are now an allowlist - null, zero, stdout/stderr, a tty, an fd - and every other /dev/ target is denied, including mapper/*, md*, dm-*), git push --force origin feat/custom-domain (the branch must be a whole refspec side, not a suffix), and commit messages mentioning drop schema or --no-preserve-root. SQL rules now skip a line only when every command in it is text - git commit, grep, rg, echo, printf - and no SQL client appears; everything else is still checked, so SQL in a heredoc or a python3 -c script is caught.
  • Against the v2.0.0 validator, 48 of the 116 cases in tools/validator-cases.txt fail - 39 misses and 9 false positives. All 116 pass now.
  • /setup warns when the repository is public and adds .claude/logs/, .claude/settings.local.json and .env* to .gitignore. The README now says to choose Private on "Use this template" - memory/ is committed by design.
  • tools/doctor.sh no longer interpolates file names into Python source; paths are passed as arguments.
  • Added SECURITY.md with a private reporting route.

Added

  • tools/test-validator.sh + tools/validator-cases.txt - 116 expected decisions, 41 of...
Read more

v2.0.0 — realign with Claude Code v2.1.220

Choose a tag to compare

@onurpolat05 onurpolat05 released this 27 Jul 13:05
a12098a

ALBA v1.1.0 shipped on 2026-04-30 and was written against Claude Code v2.1.83. Three months of Claude Code releases later, parts of it had stopped working — not loudly, which is the problem. Hooks fail silently by design: a wrong field name, a wrong output shape, a default that flipped underneath you. The process exits 0, nothing is printed, and the feature simply never happens.

This release fixes what was broken, removes what could not be verified, and makes the silent failures detectable.

Why MAJOR: the minimum Claude Code version moves from v2.1.83 to v2.1.218 · the PreToolUse output contract changed and bash-validator.sh had to change with it · examples/*/.claude/ is now generated from templates/ and must not be hand-edited · templates/agents/researcher.md was removed.

Fixed

  • agent-suggest.sh read a field that does not exist. The UserPromptSubmit payload carries the prompt in the top-level prompt field; the hook parsed .message // .user_prompt, which always resolved to empty. It then exited 0 with no output — the correct behavior for "no suggestion," and indistinguishable from it. The hook was dead in every session since it shipped and nothing ever reported it. It now reads .prompt, with a matching grep fallback for machines without jq.
  • agent-suggest.sh emitted a shape no event accepts. Its suggestions were printed as {"message": "..."}, which is not part of any hook output contract and would have been injected as literal JSON text. Suggestions are now plain stdout, which UserPromptSubmit adds to the conversation as visible context — appropriate for a tip the user should also see.
  • bash-validator.sh was lowering the permission floor it claimed to raise. For any command its 20-pattern blocklist did not match, it printed {"decision": "allow"}. On PreToolUse that maps to permissionDecision: "allow", whose documented effect is to skip the permission prompt. A hook presented as a security layer was silently auto-approving every command it had never heard of. It now emits deny on a match, ask if the validator itself fails, and no output at all otherwise, so the normal permission flow is left untouched. This is the reference behavior from the official example: exit 0 # no decision; normal permission flow applies.
  • bash-validator.sh patterns were unanchored and case-insensitive, so they matched their letters anywhere in a command string rather than a command being run. git commit -m "fix reboot handler" was blocked. Patterns are now anchored to a command position (start of string, or after ;, &, |, (), matched case-sensitively for shell verbs and case-insensitively only for SQL. A wrapper-absorbing group in the anchor keeps sudo rm -rf ~ and env FOO=1 rm -rf / in command position, so absorbing wrappers does not reopen the substring hole.
  • bash-validator.sh fail-safe was mislabeled. Its ERR trap emitted a top-level decision: "block", a deprecated field on this event. A broken validator now emits permissionDecision: "ask" — the user is asked, rather than the validator silently becoming a no-op.
  • The settings.json snippet in templates/hooks/README-hooks.md was structurally wrong. It flattened the handler object into the event entry, omitting the mandatory inner hooks array. That form is accepted without complaint and installs nothing, so anyone who copied it ended up with no hooks and no error message. Corrected, with the requirement called out explicitly.
  • Relative hook paths (bash .claude/hooks/x.sh) resolve against the session's working directory and break the moment a session is opened in a subdirectory. All hook commands now use ${CLAUDE_PROJECT_DIR}.
  • The .env protection rules never applied. settings.json carried deny: Write(.env) and ask: Write(**/*.env) — but file permission rules are matched on Edit(path) only, and Edit already covers every file-writing tool. Claude Code accepts a Write(path) rule, prints a startup warning about it, and then ignores it, so the rule that was supposed to guard credential files had been inert since v1.1.0 introduced it. Both are now Edit(...), the redundant Write(memory/**) allow entry was dropped, and tools/doctor.sh fails on any Write(path) rule. Found by running a real session rather than by reading the file — the warning only appears at startup.
  • /setup carried its own copy of settings.json and had drifted from the template. The skill inlined the settings JSON three times, once per scope, so none of the template's fixes reached a freshly set-up project: it still emitted the dead Write(.env) rules, omitted permissions.allow entirely, never installed session-end.sh, and dropped the bash command prefix that lets hooks run without an executable bit. Phase 2d now copies templates/settings.json.template and deletes the out-of-scope events, so there is one source again.
  • /setup Phase 3 contradicted CLAUDE.md.template. It instructed the wizard to write skills, tools and self-improvement sections into the generated CLAUDE.md — exactly the tables the template had removed, because skills and MCP tools are discovered by the harness and that content already lives in rules/behavioral.md. A setup following the skill produced a CLAUDE.md the template calls wrong. Phase 3 now says fill in the template's sections and add nothing it does not have, with the reasoning attached.
  • Hook count was wrong everywhere. READMEs and CONTRIBUTING said 6 hooks; the repository has shipped 7 since v1.1.0 added post-compact.sh, and now ships 8 across 9 event registrations (error-logger.sh is wired to both PostToolUse and PostToolUseFailure). Counts corrected in every document that states one, and made checkable — tools/doctor.sh greps every doc for a stated hook, skill or role count and fails if it disagrees with the files on disk. sync-examples.sh cannot catch this class of error, because the example role docs describe the shared config without being copies of it.
  • templates/claude/loop-integration.md.template and memory-compatibility.md.template did not exist. templates/INDEX.md listed both as generated docs, so the index pointed at files nothing produced. Both templates are now present.

Changed

  • Minimum Claude Code is v2.1.218 (was v2.1.83); behavior verified against v2.1.220. The floor is set by the background frontmatter field, which the two forked skills need.
  • /research and /reflect now set background: false. Both carry context: fork. As of Claude Code v2.1.218, forked skills default to background: true — they run detached and their result arrives as a later notification rather than in the turn that invoked them. Both skills predate that release by months and changed behavior without anyone touching a line of them. Asking for research or reflection is a synchronous question, so the answer belongs in the turn that asked it.
  • All 9 skill descriptions rewritten to the trigger-plus-boundary pattern — <what it does>. Use when user says "x", "y". Do NOT use for <z>. The description is the only text Claude reads when deciding whether to invoke a skill; ALBA's previous descriptions were one-line definitions with no trigger phrases and no negative boundary.
  • Error log moved from memory/knowledge/errors_raw.log to .claude/logs/errors_raw.log, with rotation at 500 lines. It is machine-local runtime state, not memory content, and it previously grew unbounded inside the git-tracked memory tree. .gitignore now excludes .claude/logs/ instead of the old path.
  • memory-check.sh is rate-limited to once per 6 hours via a guard file, and its "session longer than 30 minutes" heuristic was removed. That heuristic read file birth time, which most Linux filesystems report as 0 — so on those systems the condition was always true and the hook fired on every single Stop, meaning after every response. A reminder that frequent is one users learn to read past. The guard replaces it, and the hook now stays silent — without burning the guard window — when it has nothing concrete to say.
  • CLAUDE.md.template cut from 149 to 85 lines and decision-protocol.md.template from 260 to 68. The decision protocol lived in three places with three levels of detail. templates/rules/behavioral.md is now the single authority on when to ask and when to act — rules files are in context at the moment the decision is made, which a doc you would have to open is not. The doc keeps worked examples and phrasing, and never overrides the rule.
  • examples/*/.claude/ is generated from templates/. Every hook script, doc and settings file previously existed in six independent copies, and a fix applied to one skipped the other five. The copies remain on disk so an example is still readable on GitHub, but they are build output now. Role-specific files — CLAUDE.md, README.md, memory/ — are never overwritten.
  • templates/hooks/README-hooks.md substantially expanded — see Added.

Added

  • tools/sync-examples.sh — regenerates the shared parts of examples/ from templates/. --check reports drift and exits non-zero without changing anything, so it works as a CI gate.
  • tools/doctor.sh — health check for the failures that produce no error: hook event names that are not among the 30 real events, settings.json entries missing the inner hooks array, hook commands pointing at scripts that do not exist, relative hook paths, a PreToolUse hook that returns allow, template/example drift, broken repo-relative links, stated counts that no longer match the files, stale version claims, leaked absolute home paths, and removal residue such as strikethrough or DEPRECATED tombstones. It also shell-parses every script and validates every JSON file. ALBA ships configuration rather than a runnable program, so this stands in for a test suite. Run...
Read more

v1.1.0 — effort-aware skills, hardened settings, Windows support

Choose a tag to compare

@onurpolat05 onurpolat05 released this 30 Apr 11:50
3a0e259

Added

  • Windows compatibility: new .gitattributes forces *.sh / *.sh.template files to LF line endings on all platforms — closes the bad interpreter: bash\r failure that broke all 7 hooks under Windows' default core.autocrlf=true. New "Windows Setup" section in README (en/tr/de) covers Git for Windows + jq prerequisites; templates/hooks/README-hooks.md documents the bash/jq requirements and WSL2 alternative. ALBA now works on Windows native Claude Code (via Git Bash routing) without WSL.
  • effort frontmatter on 8 of 9 built-in skills: /start and /status → low; /end, /extend, /reflect, /setup, /create-skill → medium; /weekly-review → high. Pro/Max users on Opus 4.6 / Sonnet 4.6 default to high effort since CC v2.1.117 — explicit per-skill effort cuts ~3-5x token cost on lightweight skills. (/research deliberately left without static effort so the user's /effort slider applies.)
  • Two-layer security model for dangerous-command protection:
    • Layer 1 (CC native): permissions.deny and permissions.ask blocks in settings.json — picks up CC v2.1.113's wrapper-match (catches env FOO=bar rm, sudo rm, find -delete automatically) and v2.1.121's permission-prompt skip for skill/agent/command writes.
    • Layer 2 (bash-validator.sh): semantic intent detection for catastrophic patterns (fork bombs, pipe-to-shell, SQL drops, etc.).
  • New post-compact.sh hook (PostCompact event, CC v2.1.76+) — reminds Claude to re-load dashboard.md / todo.md / today's daily log after a compaction.
  • error-logger.sh extended to also fire on PostToolUseFailure (Edit/Write/MCP failures, not just Bash exit codes), with duration_ms capture (CC v2.1.119+) and tool_name field for cross-tool error pattern detection.
  • Agent template hardening: templates/agents/planner.md is now read-only by default (maxTurns: 20, disallowedTools: [Bash, Edit, Write]); templates/agents/researcher.md gets maxTurns: 30 and an initialPrompt that asks the user for topic + depth.
  • templates/hooks/README-hooks.md documents the two-layer security model and the role of each hook.
  • MEMORY.md 25KB / 200-line cap awareness in /end skill and memory-system.md (CC v2.1.83 limit). ALBA's own memory/ is unaffected — narrative content goes to ALBA, one-line tactical facts to CC auto-memory.

Changed

  • settings.json shape (5 examples + /setup Phase 2d):
    • Added permissions block: deny for Bash(sudo:*), Read(.env), Write(.env), AWS / SSH credentials; ask for git push, npm publish, env-file writes.
    • Added env: { CLAUDE_CODE_SUBPROCESS_ENV_SCRUB: "1" } (CC v2.1.83+) — strips Anthropic / cloud credentials from subprocesses.
    • Hook entries now use the modern {matcher, hooks: [{type, command, timeout}]} shape with explicit timeout values.
  • bash-validator.sh: catastrophic-pattern regexes now use [[:space:]]+ instead of literal spaces — closes a tab-character bypass. Existing pattern coverage preserved (rm /, mkfs, dd if=, fork bomb, chmod 777 /, DROP DATABASE/TABLE, curl|bash, eval $(, sudo rm -rf, etc.).
  • .claude/docs/loop-integration.md rewritten — covers dynamic (self-paced) mode, Esc-cancel (CC v2.1.113), Anthropic-Console /schedule for persistent recurring tasks.
  • README CC version badge: v2.1.71+ → v2.1.83+ (3 languages: en, tr, de).
  • README "Requirements" line: v2.1.50+ → v2.1.83+ (3 languages).
  • pre-compact.sh template: comment header documents the v2.1.105 block-decision option (exit 2 or {"decision":"block"} halts compaction).

Security

  • CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 now set in all example settings.json files (CC v2.1.83+).
  • bash-validator.sh [[:space:]]+ POSIX class closes tab-character pattern bypass (e.g., rm\t-rf\t/ was previously not matched by literal-space patterns).

Compatibility

  • Minimum Claude Code: v2.1.83 (was v2.1.71). Tested behavior reflects v2.1.123.
  • No breaking changes to memory layout, CLAUDE.md template, or /setup flow — existing v1.0.x repos can update by copying new templates over.

ALBA v1.0.0 — Your routine-driven AI companion

Choose a tag to compare

@onurpolat05 onurpolat05 released this 08 Mar 10:06

What is ALBA?

ALBA transforms Claude Code into a personal AI agent with persistent memory, automated workflows, and self-improving behavior — tailored to any role.

10-minute interactive setup. Zero dependencies. Pure markdown.

Highlights

Core System

  • Interactive /setup — Answer 7 questions, get a complete personalized agent
  • 9 built-in skills — /start, /end, /status, /research, /weekly-review, /extend, /reflect, /create-skill
  • 6 automated hooks — Bash safety, error logging, session management, context preservation
  • 3-tier memory — State (hot), Knowledge (warm), Projects (cold) — all git-tracked markdown

Architecture

  • Progressive disclosure — CLAUDE.md stays under 200 lines, details lazy-load
  • Skills 2.0 — YAML frontmatter with context: fork/inline and allowed-tools
  • Auto-configured hooks — /setup generates settings.json automatically

Compatibility

  • Claude Code v2.1.71+ — /loop integration for periodic monitoring
  • Auto-memory — Coexists with Claude Code's built-in memory system
  • Cross-platform — macOS and Linux hook scripts

Examples

5 complete, working setups included:

  • Developer, Project Manager, Content Creator, Researcher, Founder

Quick Start

git clone https://github.com/onurpolat05/ALBA.git my-agent
cd my-agent
claude
# Then type: /setup

What's Next

  • Visual demo content (Remotion-based)
  • Skill marketplace concept
  • More role examples
  • Community skill sharing

ALBA — Consistent. Independent. Always learning.