- Replace raw fs.readFileSync with readFile() from utils in
check-console-log.js and post-edit-console-warn.js to eliminate
TOCTOU race conditions (file deleted between existsSync and read)
- Remove redundant existsSync in post-edit-format.js (exec already
handles missing files via its catch block)
- Resolve path upfront in post-edit-typecheck.js before tsconfig walk
- Add type guard in getGitModifiedFiles() to skip non-string and
empty patterns before regex compilation
- New skills: api-design, database-migrations, deployment-patterns
- validate-hooks.js: validate inline JS syntax in node -e hook commands
- utils.test.js: edge case tests for findFiles with null/undefined inputs
- README: update skill count to 35, add new skills to directory tree
- Guard findFiles() against null/undefined dir and pattern parameters
(previously crashed with TypeError on .replace() or fs.existsSync())
- Wrap countInFile() and grepFile() regex construction in try-catch to
handle invalid regex strings like '(unclosed' (previously crashed with
SyntaxError: Invalid regular expression)
- Add try-catch to replaceInFile() with descriptive error logging
- Add 1MB size limit to readStdinJson() matching the PostToolUse hooks
(previously had unbounded stdin accumulation)
- Improve ensureDir() error message to include the directory path
- Add 128-char length limit to setAlias() to prevent oversized alias
names from inflating the JSON store
- Update utils.d.ts with new maxSize option on ReadStdinJsonOptions
- Wrap JSON.parse in try-catch for all 6 inline hooks in hooks.json
(dev-server blocker, tmux reminder, git-push reminder, doc blocker,
PR create logger, build analysis) — previously unguarded JSON.parse
would crash on empty/malformed stdin, preventing data passthrough
- Add config parse error logging to evaluate-session.js
- Fix plugin.schema.json: author can be string or {name,url} object,
add version (semver pattern), homepage, keywords, skills, agents
- Fix package-manager.schema.json: add setAt (date-time) field and
make packageManager required to match actual code behavior
- Fix renameAlias() leaving orphaned newAlias key on save failure,
causing in-memory data corruption with both old and new keys present
- Add sessionPath validation to setAlias() to reject empty/null paths
- Guard getSessionById() against empty string matching all sessions
(startsWith('') is always true in JavaScript)
- Fix suggest-compact.js NaN comparison when COMPACT_THRESHOLD env var
is set to a non-numeric value — falls back to 50 instead of silently
disabling the threshold check
- Sync suggest-compact.js to .cursor/ copy
- Validate language names in install.sh to prevent path traversal via
malicious args like ../../etc (only allow [a-zA-Z0-9_-])
- Replace silent catch in check-console-log.js with stderr logging so
hook failures are visible to the user for debugging
- Escape backticks in session-end.js user messages to prevent markdown
structure corruption in session files
- Add try-catch around readFileSync in validate-agents, validate-commands,
validate-skills to handle TOCTOU races and file read errors
- Add validate-hooks.js and all test suites to package.json test script
(was only running 4/5 validators and 0/4 test files)
- Fix shell variable injection in observe.sh: use os.environ instead of
interpolating $timestamp/$OBSERVATIONS_FILE into Python string literals
- Fix $? always being 0 in start-observer.sh: capture exit code before
conditional since `if !` inverts the status
- Add OLD_VERSION validation in release.sh and use pipe delimiter in sed
to avoid issues with slash-containing values
- Add jq dependency check in evaluate-session.sh before parsing config
- Sync .cursor/ copies of all modified shell scripts
- Expand AgentShield ecosystem section with Opus 4.6 three-agent pipeline
details, 5 scan categories, and 4 output formats
- Add hackathon badge to header stats
- Add sponsors section before star history
Add .d.ts type definitions for all four library modules:
- utils.d.ts: Platform detection, file ops, hook I/O, git helpers
- package-manager.d.ts: PM detection with PackageManagerName union type,
DetectionSource union, and typed config interfaces
- session-manager.d.ts: Session CRUD with Session, SessionMetadata,
SessionStats, and SessionListResult interfaces
- session-aliases.d.ts: Alias management with typed result interfaces
for set, delete, rename, and cleanup operations
These provide IDE autocomplete and type-checking for TypeScript
consumers of the npm package without converting the source to TS.
- Rename opencode-ecc to ecc-universal across package.json, index.ts,
README.md, and MIGRATION.md for consistent branding
- Add .npmignore to exclude translation READMEs, release scripts, and
plugin dev notes from npm package
- Remove duplicate getAliasesPath() from utils.js (only used in
session-aliases.js which has its own copy)
- session-aliases.js: validate cleanupAliases param is a function,
check saveAliases return value, guard resolveAlias against empty input
- Sync .cursor/skills/strategic-compact/suggest-compact.sh with the
fixed main version (CLAUDE_SESSION_ID instead of $$)
- Add hooks/README.md: comprehensive hook documentation with input schema,
customization guide, 4 ready-to-use hook recipes, and cross-platform notes
- Expand planner agent with full worked example (Stripe subscriptions plan)
and sizing/phasing guidance (119 → 212 lines)
- Add Django REST API example config (DRF + Celery + pytest + Factory Boy)
- Update README directory tree with new files
Core library fixes:
- session-manager.js: wrap all statSync calls in try-catch to prevent
TOCTOU crashes when files are deleted between readdir and stat
- session-manager.js: use birthtime||ctime fallback for Linux compat
- session-manager.js: remove redundant existsSync before readFile
- utils.js: fix findFiles TOCTOU race on statSync inside readdir loop
Hook improvements:
- Add 1MB stdin buffer limits to all PostToolUse hooks to prevent
unbounded memory growth from large payloads
- suggest-compact.js: use fd-based atomic read+write for counter file
to reduce race window between concurrent invocations
- session-end.js: log when transcript file is missing, check
replaceInFile return value for failed timestamp updates
- start-observer.sh: log claude CLI failures instead of silently
swallowing them, check observations file exists before analysis
Test fixes:
- Fix blocking hook tests to send matching input (dev server command)
and expect correct exit code 2 instead of 1
- Sync .cursor/observe.sh with corrected main version (use stdin pipe
instead of broken heredoc json.loads pattern)
- Fix suggest-compact.sh to use CLAUDE_SESSION_ID instead of $$ which
gives a new PID per invocation, preventing counter from incrementing
The prompt no longer lists "Available package managers" (which required
spawning processes) — it now shows "Supported package managers" and
mentions lock file detection as a configuration option.
All 69 tests pass.
Move three complex inline hooks from hooks.json into proper external
scripts in scripts/hooks/:
- post-edit-format.js: Prettier auto-formatting (was 1 minified line)
- post-edit-typecheck.js: TypeScript check (was 1 minified line with
unbounded directory traversal, now capped at 20 levels)
- post-edit-console-warn.js: console.log warnings (was 1 minified line)
Benefits:
- Readable, documented, and properly error-handled
- Testable independently via stdin
- Consistent with other hooks (all use external scripts now)
- Adds timeouts to Prettier (15s) and tsc (30s) to prevent hangs
utils.js:
- Fix countInFile: enforce global flag on regex to prevent silent
under-counting (match() without /g returns only first match)
- Add 5s timeout to readStdinJson to prevent hooks hanging forever
- Handle EEXIST race condition in ensureDir
- Pre-compile regex patterns in getGitModifiedFiles to avoid N*M
compilations and catch invalid patterns before filtering
- Add JSDoc documentation to all improved functions
session-manager.js:
- Fix getSessionById triple file read: pass pre-read content to
getSessionStats instead of re-reading from disk
- Allow getSessionStats to accept content string directly
session-aliases.js:
- Wrap temp file cleanup in try/catch to prevent cascading errors
check-console-log.js:
- Refactor to use shared utils (isGitRepo, getGitModifiedFiles, log)
instead of raw execSync calls
- Add exclusion patterns for test files, config files, and scripts/
where console.log is intentional
session-end.js:
- Log count of skipped unparseable transcript lines for diagnostics
suggest-compact.js:
- Guard against NaN from corrupted counter files
package-manager.js:
- Remove dead fallbackOrder parameter (unused after #162 fix)
getAvailablePackageManagers() spawned where.exe/which for each package
manager (npm, pnpm, yarn, bun). During SessionStart hooks, these 4+
child processes combined with Bun's own initialization exceeded the
spawn limit on Windows, freezing the terminal.
Fix: Remove process spawning from the hot path. Steps 1-5 of detection
(env var, project config, package.json, lock file, global config) already
cover all file-based detection. If none match, default to npm without
spawning. Also fix getSelectionPrompt() to list supported PMs without
checking availability.
session-end.js: Extract meaningful summaries from CLAUDE_TRANSCRIPT_PATH
instead of writing blank template files. Pulls user messages, tools used,
and files modified from the session transcript JSONL.
session-start.js: Output the latest session summary to stdout (via the
output() helper) so it gets injected into Claude's conversation context,
instead of only logging to stderr which just shows briefly in the terminal.
Replace relative require('./scripts/lib/...') with dynamic path resolution
using CLAUDE_PLUGIN_ROOT env var (set by Claude Code for plugins) with
fallback to ~/.claude/ for manual installations. This fixes /sessions
command failing when ECC is installed as a plugin.
* fix: resolve multiple reported issues (#205, #182, #188, #172, #173)
- fix(observe.sh): replace triple-quote JSON parsing with stdin pipe to
prevent ~49% parse failures on payloads with quotes/backslashes/unicode
- fix(hooks.json): correct matcher syntax to use simple tool name regexes
instead of unsupported logical expressions; move command/path filtering
into hook scripts; use exit code 2 for blocking hooks
- fix(skills): quote YAML descriptions containing colons in 3 skill files
and add missing frontmatter to 2 skill files for Codex CLI compatibility
- feat(rules): add paths: filters to all 15 language-specific rule files
so they only load when working on matching file types
- fix(agents): align model fields with CONTRIBUTING.md recommendations
(opus for planner/architect, sonnet for reviewers/workers, haiku for
doc-updater)
* ci: use AgentShield GitHub Action instead of npx
Switch from npx ecc-agentshield to uses: affaan-m/agentshield@v1
for proper GitHub Action demo and marketplace visibility.
New skill: /security-scan wraps ecc-agentshield to audit .claude/ configs
for vulnerabilities, misconfigs, and injection risks.
Covers: CLAUDE.md secrets, settings.json permissions, MCP server risks,
hook injection, agent tool restrictions. Produces A-F security grade.
Also adds AgentShield section to Ecosystem Tools in README with
links to GitHub repo and npm package.
The .opencode/ directory was missing from the files array, so the npm
package only shipped Claude Code and Cursor configs. Selectively include
.opencode/ subdirectories to avoid bundling node_modules and dist.
Add complete .cursor/ directory with rules, agents, skills, commands,
and MCP config adapted for Cursor's format. This makes ecc-universal
a truly cross-IDE package supporting Claude Code, Cursor, and OpenCode.
- 27 rule files with YAML frontmatter (description, globs, alwaysApply)
- 13 agent files with full model IDs and readonly flags
- 30 skill directories (identical Agent Skills standard, no translation)
- 31 command files (5 multi-* stubbed for missing codeagent-wrapper)
- MCP config with Cursor env interpolation syntax
- README.md and MIGRATION.md documentation
- install.sh --target cursor flag for project-scoped installation
- package.json updated with .cursor/ in files and cursor keywords
Adding awesome-agent-skills as a related resource.
A curated list of 40+ AI Agent Skills with cross-platform installer (bash/PowerShell), supporting Cursor, Claude Code, Copilot, Windsurf, Codex, and OpenCode.
GitHub: https://github.com/JackyST0/awesome-agent-skills
- Remove trailing whitespace from inline code
- Add blank line before table
- Fix heading levels to ensure proper hierarchy
- Convert bare URLs to markdown links
- Fix PluginContext → PluginInput type rename in @opencode-ai/plugin
- Import tool from @opencode-ai/plugin/tool subpath (fixes broken barrel export)
- Update client.app.log() calls to use new options-object API signature
- Stringify tool execute return values (SDK now requires Promise<string>)
- Add .js extensions to relative imports for NodeNext module resolution
- Update README star count (42K+) and contributor count (24)