@rmyndharis/aimhooman 0.1.0
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/.agents/rules/aimhooman.md +53 -0
- package/.claude-plugin/marketplace.json +23 -0
- package/.claude-plugin/plugin.json +9 -0
- package/.clinerules/aimhooman.md +53 -0
- package/.codex-plugin/plugin.json +37 -0
- package/.cursor/rules/aimhooman.mdc +59 -0
- package/.gemini/settings.json +7 -0
- package/.github/copilot-instructions.md +53 -0
- package/.github/hooks/aimhooman.json +22 -0
- package/.kiro/steering/aimhooman.md +53 -0
- package/.windsurf/rules/aimhooman.md +57 -0
- package/AGENTS.md +53 -0
- package/CHANGELOG.md +153 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +144 -0
- package/GEMINI.md +53 -0
- package/LICENSE +21 -0
- package/README.md +472 -0
- package/SECURITY.md +74 -0
- package/bin/aimhooman.mjs +1589 -0
- package/docs/design/agent-portability.md +73 -0
- package/docs/design/frictionless-enforcement.md +135 -0
- package/docs/hosts.json +164 -0
- package/docs/logo/aimhooman-logo.png +0 -0
- package/docs/logo/aimhooman.png +0 -0
- package/hooks/hooks.json +29 -0
- package/package.json +77 -0
- package/rules/attribution.json +142 -0
- package/rules/markers.json +88 -0
- package/rules/paths.json +407 -0
- package/rules/secrets.json +90 -0
- package/schemas/overrides.schema.json +134 -0
- package/schemas/project-policy.schema.json +12 -0
- package/schemas/rule-pack.schema.json +126 -0
- package/schemas/scan-report.schema.json +165 -0
- package/skills/aimhooman/SKILL.md +65 -0
- package/src/args.mjs +72 -0
- package/src/atomic-write.mjs +285 -0
- package/src/codex-manifest.mjs +65 -0
- package/src/exclude.mjs +125 -0
- package/src/git-environment.mjs +5 -0
- package/src/git-path.mjs +5 -0
- package/src/githooks.mjs +813 -0
- package/src/gitx.mjs +721 -0
- package/src/history-scan.mjs +295 -0
- package/src/hook.mjs +2602 -0
- package/src/policy-resolver.mjs +200 -0
- package/src/report.mjs +63 -0
- package/src/rules.mjs +509 -0
- package/src/ruleset-text.mjs +29 -0
- package/src/scan-session.mjs +152 -0
- package/src/scan-target.mjs +697 -0
- package/src/scan.mjs +325 -0
- package/src/state.mjs +360 -0
package/README.md
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="docs/logo/aimhooman-logo.png" alt="aimhooman - AI works. Hoomans ship." width="120">
|
|
4
|
+
</div>
|
|
5
|
+
|
|
6
|
+
<h1 align="center">AI’m Hooman</h1>
|
|
7
|
+
|
|
8
|
+
<p align="center">"beep boop ... ai'm hooman"</p>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<img src="https://img.shields.io/github/actions/workflow/status/rmyndharis/aimhooman/test.yml?branch=main&label=CI" alt="CI">
|
|
12
|
+
<img src="https://img.shields.io/badge/version-v0.1.0-blue" alt="v0.1.0">
|
|
13
|
+
<img src="https://img.shields.io/badge/node-%E2%89%A522.8-339933?logo=node.js&logoColor=white" alt="Node 22.8+">
|
|
14
|
+
<img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="Zero dependencies">
|
|
15
|
+
<img src="https://img.shields.io/badge/license-MIT-111111" alt="MIT">
|
|
16
|
+
<img src="https://img.shields.io/npm/dm/@rmyndharis/aimhooman?label=downloads" alt="Downloads">
|
|
17
|
+
<img src="https://img.shields.io/github/stars/rmyndharis/aimhooman?style=social" alt="GitHub Stars">
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">aimhooman: <i>AI works. Hoomans ship.</i></p>
|
|
21
|
+
|
|
22
|
+
<b>aimhooman</b> is a vendor-neutral guard that keeps AI coding agents from leaving their
|
|
23
|
+
fingerprints in your Git history: session files that were never meant to be
|
|
24
|
+
committed, secrets, and unwanted AI attribution in commit messages. Its host adapters
|
|
25
|
+
and Git hooks catch known cases before a commit and make review decisions visible.
|
|
26
|
+
<br/>
|
|
27
|
+
|
|
28
|
+
> **Human-owned, not human-washed.** aimhooman removes tooling residue and sets
|
|
29
|
+
> human ownership. It does not fake authorship or strip disclosure your policy
|
|
30
|
+
> requires.
|
|
31
|
+
|
|
32
|
+
## TL;DR
|
|
33
|
+
|
|
34
|
+
Keep AI session files, secrets, and stray `Co-authored-by:` lines out of your Git
|
|
35
|
+
history — without a per-tool ignore list and without faking who wrote the code.
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
npm install -g @rmyndharis/aimhooman
|
|
39
|
+
aimhooman init # git hooks + local excludes; normally no worktree files
|
|
40
|
+
git commit -m "ship it" # guarded automatically
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Repair-first by default. Any block that cannot be repaired, or any incomplete
|
|
44
|
+
scan, stops before the branch ref changes. Zero runtime dependencies. Runs on
|
|
45
|
+
Node 22.8+.
|
|
46
|
+
|
|
47
|
+
Want it inside Claude Code, Codex, Copilot, Cursor, and friends? See
|
|
48
|
+
[Use it in your AI coding tool](#use-it-in-your-ai-coding-tool).
|
|
49
|
+
|
|
50
|
+
## The problem
|
|
51
|
+
|
|
52
|
+
<p align="center">
|
|
53
|
+
<img src="docs/logo/aimhooman.png" alt="aimhooman - AI works. Hoomans ship." width="720">
|
|
54
|
+
</p>
|
|
55
|
+
Your AI agent works in your repo and quietly leaves state behind: `.claude/session.json`,
|
|
56
|
+
chat history, caches, and `Co-authored-by:` an AI. One `git add -A` later, it is in
|
|
57
|
+
your history. Ignore lists are per-tool and never complete, and a local git hook is
|
|
58
|
+
one `--no-verify` away from being skipped.
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
## How it works
|
|
62
|
+
|
|
63
|
+
One detection core, many enforcement surfaces. On the default profile, the ordinary
|
|
64
|
+
commit path repairs hygiene findings when it can. `commit-msg` checks the pinned
|
|
65
|
+
would-be tree, and the final ref boundary independently scans every commit introduced
|
|
66
|
+
to `HEAD` or a branch. Any remaining block or incomplete scan stops. `strict` blocks
|
|
67
|
+
instead of repairing.
|
|
68
|
+
|
|
69
|
+
```mermaid
|
|
70
|
+
flowchart TD
|
|
71
|
+
SESS([Session start]) -. once .-> EXCL["Auto-exclude known<br/>AI artifacts in .git/info/exclude"]
|
|
72
|
+
AGENT([Agent calls a tool]) -. proactive .-> ADV["PreToolUse parses the command,<br/>resolves repo/policy, and checks bypass risk"]
|
|
73
|
+
RUN([You run the CLI]) -. on demand .-> CLI["check · fix · explain"]
|
|
74
|
+
|
|
75
|
+
COMMIT([Ordinary git commit or merge]) --> PRE["pre-commit / pre-merge-commit<br/>run predecessor, resolve staged policy,<br/>scan exact index"]
|
|
76
|
+
DIRECT([Sequencer or direct ref path<br/>cherry-pick · rebase · fetch · worktree · update-ref]) --> REF
|
|
77
|
+
PRE -->|clean: safe repair| MSG["commit-msg snapshots would-be tree,<br/>runs predecessor, then checks<br/>the message and pinned full tree"]
|
|
78
|
+
PRE -->|strict violation, incomplete scan,<br/>or failed repair| BLOCK([Operation stops])
|
|
79
|
+
MSG -->|message and tree accepted| REF["reference-transaction prepared<br/>full-scans every introduced commit"]
|
|
80
|
+
MSG -->|unsafe or unrepairable| BLOCK
|
|
81
|
+
REF -->|accepted| SHIP([Ref update commits])
|
|
82
|
+
REF -->|violation or incomplete scan| BLOCK
|
|
83
|
+
|
|
84
|
+
classDef entry fill:#f8fafc,stroke:#94a3b8,color:#0f172a,stroke-width:1.5px
|
|
85
|
+
classDef hook fill:#eef2ff,stroke:#6366f1,color:#312e81,stroke-width:2px
|
|
86
|
+
classDef ok fill:#ecfdf5,stroke:#10b981,color:#064e3b,stroke-width:1.5px
|
|
87
|
+
classDef stop fill:#fef2f2,stroke:#ef4444,color:#7f1d1d,stroke-width:2px
|
|
88
|
+
|
|
89
|
+
class SESS,AGENT,RUN,COMMIT,DIRECT entry
|
|
90
|
+
class PRE,MSG,REF hook
|
|
91
|
+
class SHIP ok
|
|
92
|
+
class BLOCK stop
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- **Prevent:** on session start, known AI artifacts are written into `.git/info/exclude`
|
|
96
|
+
(local, never your `.gitignore`), so they never even show in `git status`.
|
|
97
|
+
- **Catch:** if one slips through, `pre-commit` unstages it and `commit-msg` removes
|
|
98
|
+
complete, exact high-confidence attribution lines. Broader candidates are reported
|
|
99
|
+
without editing the message. An unterminated exact final line stops unchanged because
|
|
100
|
+
a byte-safe repair cannot be proved.
|
|
101
|
+
- **Advise:** the plugin's `PreToolUse` reports paths before Git runs. It denies a
|
|
102
|
+
protected commit/ref operation on every profile when the hook JSON is empty,
|
|
103
|
+
invalid, or not an object, a required managed guard is missing, or hook/receiver
|
|
104
|
+
indirection makes the final ref check unprovable. An unknown executor argument
|
|
105
|
+
shape is denied on `strict`; `strict` also rejects uncertain execution and bypasses.
|
|
106
|
+
- **Block:** `strict` cancels ordinary commits instead of repairing them. On every
|
|
107
|
+
profile, the pinned-tree and final ref guards stop a commit that still contains a
|
|
108
|
+
block finding or cannot be checked completely.
|
|
109
|
+
|
|
110
|
+
## By the numbers
|
|
111
|
+
|
|
112
|
+
| | |
|
|
113
|
+
| --- | --- |
|
|
114
|
+
| Enforcement | repair-first ordinary commits; fail-closed final ref check; strict hard-blocking |
|
|
115
|
+
| Policy profiles | 3 (clean, strict, compliance) |
|
|
116
|
+
| Runtime dependencies | 0 (runs on Node, ships as source) |
|
|
117
|
+
| Worktree files added by `init` | Normally 0; an existing worktree-relative `core.hooksPath` stays in use |
|
|
118
|
+
|
|
119
|
+
## Install
|
|
120
|
+
|
|
121
|
+
Node 22.8+ and Git 2.28+, zero runtime dependencies, ships as source. Git 2.28
|
|
122
|
+
is required for the prepared-phase reference transaction guard that checks
|
|
123
|
+
cherry-pick, revert, rebase, `git am`, and other ref-producing flows.
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
npm install -g @rmyndharis/aimhooman
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Guard a repository:
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
aimhooman init # git hooks + local excludes; normally no worktree files
|
|
133
|
+
aimhooman status
|
|
134
|
+
aimhooman uninstall # restore hooks/excludes; keep local policy state
|
|
135
|
+
aimhooman uninstall --purge-state # also delete common Git-directory state
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
For commits you make at the terminal (outside your AI tool), one global setup guards
|
|
139
|
+
eligible non-bare repositories that do not override `core.hooksPath` locally:
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
aimhooman init --global --yes # advanced: change core.hooksPath after confirmation
|
|
143
|
+
aimhooman uninstall --global # unset it
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Global `core.hooksPath` changes Git behavior for repositories that inherit it and can
|
|
147
|
+
replace their default hook directory. A local or worktree-scoped override takes
|
|
148
|
+
precedence. Bare repositories are outside the worktree/index policy boundary and the
|
|
149
|
+
global dispatchers leave them unchanged. `status` shows both local and global values.
|
|
150
|
+
Prefer repository `init` unless the global ordering is understood.
|
|
151
|
+
|
|
152
|
+
When `core.hooksPath` is set, Git reads hooks only from that effective directory and
|
|
153
|
+
ignores `.git/hooks`. Repository `init` installs and chains predecessors only when
|
|
154
|
+
that directory is absent or is proven to be owned by the repository. It refuses to
|
|
155
|
+
modify a global, shared, or external hook directory. In that case, integrate
|
|
156
|
+
aimhooman into the existing hook manager or remove the override before retrying.
|
|
157
|
+
|
|
158
|
+
Repository `init` installs `pre-commit`, `pre-merge-commit`, `commit-msg`, and
|
|
159
|
+
`reference-transaction`, and preserves an existing hook as a predecessor. For
|
|
160
|
+
`commit-msg`, aimhooman pins the would-be tree before the predecessor runs, so a later
|
|
161
|
+
index change cannot select a weaker policy. The prepared reference transaction is the
|
|
162
|
+
last local check for cherry-pick, revert, rebase, `git am`, fetch/worktree branch
|
|
163
|
+
creation, and direct branch-ref updates. Every profile stops if a predecessor removes
|
|
164
|
+
a required guard; the first running dispatcher that detects the loss aborts the
|
|
165
|
+
operation.
|
|
166
|
+
|
|
167
|
+
## Use it in your AI coding tool
|
|
168
|
+
|
|
169
|
+
Claude Code runs the installed plugin hook in each session. Codex runs it only after
|
|
170
|
+
the user trusts the hook with `/hooks`, and the Copilot repository hook runs only when
|
|
171
|
+
`aimhooman` is available on `PATH`. None of those host hooks replaces the Git-boundary
|
|
172
|
+
guard: install that guard with `aimhooman init` (or the global setup). Instruction-tier
|
|
173
|
+
hosts only load the ruleset until the Git guard is installed.
|
|
174
|
+
|
|
175
|
+
Claude Code:
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
/plugin marketplace add rmyndharis/aimhooman
|
|
179
|
+
/plugin install aimhooman@aimhooman
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Codex:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
codex plugin marketplace add rmyndharis/aimhooman
|
|
186
|
+
# start Codex, open /plugins, select the aimhooman marketplace,
|
|
187
|
+
# install aimhooman, enable it, then start a new session
|
|
188
|
+
/hooks
|
|
189
|
+
# review and trust the aimhooman SessionStart and PreToolUse hooks
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Codex CLI 0.144.3 or newer is the supported baseline, last checked on
|
|
193
|
+
2026-07-15. Until `/hooks` shows the plugin hooks as trusted, Codex skips them.
|
|
194
|
+
Run `aimhooman status` and `aimhooman doctor` after `aimhooman init`; the Git
|
|
195
|
+
hooks are the final commit boundary because PreToolUse does not see every shell
|
|
196
|
+
execution path.
|
|
197
|
+
|
|
198
|
+
GitHub Copilot CLI:
|
|
199
|
+
|
|
200
|
+
```sh
|
|
201
|
+
npm install -g @rmyndharis/aimhooman
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
The Copilot repository hook (`.github/hooks/aimhooman.json`) calls the `aimhooman`
|
|
205
|
+
binary from PATH; it is advisory until you install the Git guard with
|
|
206
|
+
`aimhooman init`. The npm install does not add host files to a repository
|
|
207
|
+
automatically.
|
|
208
|
+
|
|
209
|
+
Cursor, Cline, Windsurf, Kiro, Gemini, and Antigravity use the instruction files
|
|
210
|
+
listed below. Other agents can use `AGENTS.md` or the packaged skill after their
|
|
211
|
+
own instruction-loading contract is checked. Full matrix:
|
|
212
|
+
[docs/design/agent-portability.md](docs/design/agent-portability.md).
|
|
213
|
+
|
|
214
|
+
| Host | File |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| Claude Code / Codex | `.claude-plugin/` / `.codex-plugin/` + `hooks/hooks.json` |
|
|
217
|
+
| GitHub Copilot | `.github/hooks/aimhooman.json`, `.github/copilot-instructions.md` |
|
|
218
|
+
| Cursor | `.cursor/rules/aimhooman.mdc` |
|
|
219
|
+
| Cline | `.clinerules/aimhooman.md` |
|
|
220
|
+
| Windsurf | `.windsurf/rules/aimhooman.md` |
|
|
221
|
+
| Kiro | `.kiro/steering/aimhooman.md` |
|
|
222
|
+
| Gemini CLI / Code Assist | `.gemini/settings.json`, `GEMINI.md` |
|
|
223
|
+
| Google Antigravity | `.agents/rules/aimhooman.md` (set the rule to Always On) |
|
|
224
|
+
| Any agent | `AGENTS.md` or `skills/aimhooman/SKILL.md` |
|
|
225
|
+
|
|
226
|
+
Instruction-tier files are templates in this source repository: copy the adapter you
|
|
227
|
+
need into the target project. Installing the npm CLI does not modify host instruction
|
|
228
|
+
files automatically.
|
|
229
|
+
|
|
230
|
+
## What it catches
|
|
231
|
+
|
|
232
|
+
- **AI session/state artifacts**: examples include `.claude/session*.json`,
|
|
233
|
+
`.claude/history*`, `.claude/projects/`, `.codex/sessions/`, `.codex/logs/`,
|
|
234
|
+
`.copilot/`, `.cursor/chats/`, `.aider.*`, `.specstory/`,
|
|
235
|
+
`.continue/sessions/`, `.playwright-mcp/`, `.remember/`, `.superpowers/`, and
|
|
236
|
+
`.agent/`. [`rules/paths.json`](rules/paths.json) is the complete catalog.
|
|
237
|
+
- **Secrets**: a real `.env` (not `.env.example`), private-key content,
|
|
238
|
+
`.aws/credentials`, service-account private keys, recognized AWS secret/session
|
|
239
|
+
assignments, and provider token prefixes for GitHub, GitLab, npm, and Slack.
|
|
240
|
+
Public certificates are allowed.
|
|
241
|
+
- **AI attribution** in commit messages: known AI `Co-authored-by:` identities,
|
|
242
|
+
exact "Generated with/by ..." lines, and AI-service noreply attribution trailers.
|
|
243
|
+
- **AI markers** left in code: corner-cut tooling markers (ponytail/caveman/yagni-oneliner) and
|
|
244
|
+
AI authorship comments (e.g. "generated by copilot/claude/chatgpt") in the staged content.
|
|
245
|
+
- **Review-required** files: `.aimhooman.json`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`,
|
|
246
|
+
`.github/copilot-instructions.md`.
|
|
247
|
+
|
|
248
|
+
The Antigravity instruction directory `.agents/` is distinct from local state under
|
|
249
|
+
`.agent/`.
|
|
250
|
+
|
|
251
|
+
## Profiles
|
|
252
|
+
|
|
253
|
+
Set at init, e.g. `aimhooman init --profile strict`.
|
|
254
|
+
|
|
255
|
+
- **clean** (default): repair-first on the ordinary commit path — AI artifacts are excluded or
|
|
256
|
+
unstaged, and complete exact high-confidence attribution lines are removed. Instruction
|
|
257
|
+
files, code markers, and broader attribution candidates stay visible as reviews. A block
|
|
258
|
+
that remains after repair, a repair failure, or an incomplete scan stops the operation.
|
|
259
|
+
- **strict**: hard enforcement — violations cancel the commit (exit 10) until you allow them.
|
|
260
|
+
- **compliance**: repair-first like `clean`, but **keeps** any AI attribution your policy
|
|
261
|
+
requires (no stripping).
|
|
262
|
+
|
|
263
|
+
The bundled agent instructions set a stricter authoring rule: agents must not add AI
|
|
264
|
+
attribution in the first place. Profiles control what the mechanical scanner does if
|
|
265
|
+
that instruction is missed. A repository may adopt the same authoring rule while still
|
|
266
|
+
using `clean` for automatic repair, or commit a strict team profile when every match
|
|
267
|
+
must veto the commit.
|
|
268
|
+
|
|
269
|
+
### Versioned team policy
|
|
270
|
+
|
|
271
|
+
Commit `.aimhooman.json` when every clone should use the same baseline:
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"schema_version": 1,
|
|
276
|
+
"profile": "strict"
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The project policy takes precedence over the per-clone profile written by `init`.
|
|
281
|
+
An individual `check` may escalate to `--profile strict`, but cannot weaken or replace
|
|
282
|
+
the team profile. Malformed project policy fails closed with an actionable error;
|
|
283
|
+
personal allow/deny exceptions and local rule packs remain in the common Git directory
|
|
284
|
+
under `aimhooman/`.
|
|
285
|
+
Under `strict`, policy files and agent instructions produce review-required findings.
|
|
286
|
+
The product's `review` and `policy-review` commands record local, object-bound decisions;
|
|
287
|
+
an ordinary path allow cannot satisfy either finding.
|
|
288
|
+
|
|
289
|
+
This personal repository does not use GitHub approvals, required reviewers, or
|
|
290
|
+
`CODEOWNERS`. For a protected-path change, CI verifies the pinned repository and owner
|
|
291
|
+
login plus numeric IDs through the GitHub API, then inspects the exact workflow-run
|
|
292
|
+
attempt. GitHub must attribute both `actor` and `triggering_actor`, including their
|
|
293
|
+
numeric IDs, to that owner. CI then binds the
|
|
294
|
+
authorization to the exact head, transition commit, path, resulting blob and regular-file
|
|
295
|
+
mode, or deletion tombstone. A strict-policy migration also binds its old and new policy
|
|
296
|
+
objects. A different attempt, commit, path result, mode, or policy transition needs fresh
|
|
297
|
+
authorization. A non-owner change fails closed; there is no reviewer or `CODEOWNERS`
|
|
298
|
+
fallback. The owner account and its credentials are the trust root, so this is owner
|
|
299
|
+
authorization, not independent review.
|
|
300
|
+
|
|
301
|
+
## Overrides
|
|
302
|
+
|
|
303
|
+
Every decision has a rule ID, so you can resolve a finding narrowly:
|
|
304
|
+
|
|
305
|
+
```sh
|
|
306
|
+
aimhooman allow AGENTS.md --reason "shared team config" # stop flagging this path
|
|
307
|
+
aimhooman deny path/or/rule-id # always block it
|
|
308
|
+
aimhooman explain claude.session-state # why a rule fires
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Overrides live in the repository's common Git directory under
|
|
312
|
+
`aimhooman/overrides.json` (local, never committed), so linked worktrees share them.
|
|
313
|
+
|
|
314
|
+
Secrets are never silenced by a normal path allow — that is deliberate, so a local
|
|
315
|
+
override cannot hide a real leaked key. A file that legitimately contains secret-shaped
|
|
316
|
+
text (documentation that quotes a key header, a detection test fixture) needs an
|
|
317
|
+
explicit, auditable acknowledgment instead:
|
|
318
|
+
|
|
319
|
+
```sh
|
|
320
|
+
aimhooman allow docs/key-format.md --scope secret-path --reason "documents the header"
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
```sh
|
|
324
|
+
aimhooman override list --json
|
|
325
|
+
aimhooman override remove AGENTS.md
|
|
326
|
+
aimhooman override reset --all
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Commands
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
aimhooman init | status | check | audit | scan | explain | allow | deny | override | review | policy-review | fix | doctor | uninstall | version
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
`check` accepts one Git target (`--staged`, `--tracked`, `--commit <rev>`, or
|
|
336
|
+
`--range <base>...<head>`), plus `--message <file>`, `--profile`, and `--json`.
|
|
337
|
+
Commit and range targets read commit messages from Git automatically. A range scans each
|
|
338
|
+
introduced commit, so a bad file added and deleted before the endpoint is still reported.
|
|
339
|
+
Use an all-zero object ID as the base when there is no prior commit; this includes the root
|
|
340
|
+
commit. Deleting an ordinary forbidden path is not itself a finding, while removing or
|
|
341
|
+
lowering a versioned strict project policy still needs a bound policy review.
|
|
342
|
+
`audit` and `scan` are aliases for a full tracked-index scan.
|
|
343
|
+
`init --global --yes` and `uninstall --global` manage the advanced terminal-Git guard;
|
|
344
|
+
`uninstall --global` cannot be combined with the local `--purge-state` option.
|
|
345
|
+
`fix` follows the active profile: clean writes an exact safe repair, compliance makes no
|
|
346
|
+
change, and strict previews unless `--apply` is supplied.
|
|
347
|
+
|
|
348
|
+
Machine reports use `schema_version: 1` and include target policy identity, completeness,
|
|
349
|
+
scan statistics, commit and object metadata. Schemas are published in [`schemas/`](schemas/).
|
|
350
|
+
|
|
351
|
+
Add your own per-repository detection with local rule packs in the common Git directory
|
|
352
|
+
under `aimhooman/rules/*.json`
|
|
353
|
+
(the structural schema is in [`schemas/rule-pack.schema.json`](schemas/rule-pack.schema.json);
|
|
354
|
+
local rules only add detection — they can't weaken
|
|
355
|
+
a built-in block). Within one rule, local content patterns are capped at 32 expressions,
|
|
356
|
+
512 characters per expression, and 4,096 characters total. Path and exception scopes
|
|
357
|
+
share the same glob count, per-expression, and total limits. They use a flat subset: literals,
|
|
358
|
+
character classes, anchors, dot, escapes, and fixed `{n}` repeats. Groups, alternation,
|
|
359
|
+
lookaround, backreferences, and variable quantifiers are rejected. A local expression
|
|
360
|
+
does not run on a line longer than 16,384 characters; that skip is reported and makes the
|
|
361
|
+
scan incomplete. Path rules are case-sensitive by default. Set
|
|
362
|
+
`match.path_case` to `"insensitive"` only for a security name whose meaning is
|
|
363
|
+
case-insensitive, such as `.env`; matching folds that rule's candidate and patterns but
|
|
364
|
+
does not change the Git path or override identity.
|
|
365
|
+
|
|
366
|
+
For an existing repository, start with `aimhooman audit --json`. If a residue path is
|
|
367
|
+
already tracked, remove it from the index with `git rm --cached <path>` and add an
|
|
368
|
+
appropriate ignore/exclude. If a secret was committed, rotate it first; history cleanup
|
|
369
|
+
is deliberately outside aimhooman's scope.
|
|
370
|
+
|
|
371
|
+
## Exit codes
|
|
372
|
+
|
|
373
|
+
| Code | Meaning |
|
|
374
|
+
| --- | --- |
|
|
375
|
+
| 0 | clean, or non-blocking review |
|
|
376
|
+
| 10 | policy violation (block) |
|
|
377
|
+
| 11 | review-required on a non-clean profile |
|
|
378
|
+
| 20 | usage, configuration, or rule-pack error |
|
|
379
|
+
| 30 | Git or I/O error |
|
|
380
|
+
| 31 | scan incomplete because a content or output budget was reached |
|
|
381
|
+
|
|
382
|
+
## FAQ
|
|
383
|
+
|
|
384
|
+
**Is this a way to hide AI use?** No. aimhooman removes operational residue and
|
|
385
|
+
establishes human ownership. It never changes author, committer, signature, or
|
|
386
|
+
timestamp, and the compliance profile keeps any disclosure your policy requires.
|
|
387
|
+
|
|
388
|
+
**Will it cancel my commits?** On the default `clean` profile, aimhooman first tries to
|
|
389
|
+
exclude or unstage hygiene artifacts and safely remove exact attribution lines. The
|
|
390
|
+
commit proceeds only if no block remains and every scan completes. A pre-existing
|
|
391
|
+
tracked block, failed unstage/repair, unterminated exact attribution, secret, or scan
|
|
392
|
+
budget failure stops the operation. `strict` cancels findings instead of repairing.
|
|
393
|
+
|
|
394
|
+
**Does it slow commits down?** The staged check runs locally with no network and reads
|
|
395
|
+
Git objects in batches. Text-oriented rules skip binary files, but byte-safe secret
|
|
396
|
+
signatures still run over their raw bytes. Size and total budgets are visible in
|
|
397
|
+
reports. Files over 2 MiB or a scan over 64 MiB make the scan incomplete; direct checks
|
|
398
|
+
and Git pre-commit guards stop on every profile instead of claiming that content was checked.
|
|
399
|
+
|
|
400
|
+
**Can the agent bypass it?** Any local tool can ultimately be bypassed by a user with
|
|
401
|
+
commit access. On every profile, the agent guard rejects empty, invalid, or non-object
|
|
402
|
+
hook JSON, unresolved Git subcommands/aliases, missing managed final guards, and hook
|
|
403
|
+
or receive-pack indirection around protected ref mutations. An unknown executor
|
|
404
|
+
argument shape is denied on `strict`; `strict` additionally rejects
|
|
405
|
+
`--no-verify` and uncertain commit execution. The Git hook remains the source of truth
|
|
406
|
+
for ordinary commits. Git hooks are not a sandbox: an editor or
|
|
407
|
+
another local program started during a commit has the same filesystem access and can
|
|
408
|
+
change a later hook. The strict agent guard rejects explicit editor overrides, commits
|
|
409
|
+
that would open an editor, and commits with an active foreign `prepare-commit-msg` hook.
|
|
410
|
+
It still cannot prove that every program already selected by local Git config is safe.
|
|
411
|
+
Commands assembled from files, encoded data, or network input may also be invisible to
|
|
412
|
+
its non-executing shell parser (POSIX shells — bash, sh, zsh, dash, ksh — and
|
|
413
|
+
`git.exe`; command nesting, pipelines, background jobs, and non-POSIX executors
|
|
414
|
+
such as PowerShell or fish are classified uncertain and, on `strict`, denied
|
|
415
|
+
with a retry instruction). Repository selection written in non-POSIX shell syntax
|
|
416
|
+
is denied before policy lookup on every profile. Guarded Git changes, including
|
|
417
|
+
`add`, commit, and ref updates, also reject shell-expanded targets, any leading-tilde
|
|
418
|
+
target, POSIX targets beginning with exactly `//`, and an explicit split
|
|
419
|
+
`--work-tree`; pass a literal expanded path or run the operation from that repository.
|
|
420
|
+
On Windows, use a native `C:/...` target: POSIX-root
|
|
421
|
+
targets such as `/c/...` and `/tmp`, drive-relative forms such as `C:repo`, and
|
|
422
|
+
incomplete UNC roots are denied because the parser cannot map them to one native
|
|
423
|
+
repository without running the command. Wrappers that can select another cwd or
|
|
424
|
+
filesystem namespace, including `sudo`, `chroot`, `find -execdir`, WSL, and sandbox
|
|
425
|
+
launchers, fail closed on every profile; retry as a direct Git command from the target
|
|
426
|
+
repository. Nested non-POSIX shells and shell launches that explicitly select login,
|
|
427
|
+
interactive, or startup-file behavior fail closed for the same reason. Treat local
|
|
428
|
+
executables and Git config as trusted. For team enforcement, scan the actual PR range
|
|
429
|
+
in CI (a normal CI checkout has no staged changes):
|
|
430
|
+
|
|
431
|
+
`pre-commit` and `commit-msg` do not cover every sequencer or ref movement. The managed
|
|
432
|
+
`reference-transaction` hook therefore checks introduced commits during Git's prepared
|
|
433
|
+
phase and can abort the local ref update. Git 2.54's earlier `preparing` callback is
|
|
434
|
+
accepted for compatibility and checks guard integrity; scanning remains in `prepared`,
|
|
435
|
+
after references are locked.
|
|
436
|
+
CI still scans the exact pushed or PR history:
|
|
437
|
+
local hooks do not govern another clone, server-side updates, or history created before
|
|
438
|
+
the guard was installed.
|
|
439
|
+
Bare repositories have no worktree/index boundary and are not supported by local commands.
|
|
440
|
+
A submodule is a separate repository with separate state and hooks; run `aimhooman init`
|
|
441
|
+
inside each submodule that needs local enforcement.
|
|
442
|
+
|
|
443
|
+
```sh
|
|
444
|
+
git fetch origin main
|
|
445
|
+
aimhooman check --range origin/main...HEAD --profile strict
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
On GitHub Actions, configure `actions/checkout` with `fetch-depth: 0` so the
|
|
449
|
+
triple-dot merge base is available.
|
|
450
|
+
|
|
451
|
+
## Contributing
|
|
452
|
+
|
|
453
|
+
Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for how to add
|
|
454
|
+
rules and host adapters, the test setup, and the commit policy. Please note this
|
|
455
|
+
project has a [code of conduct](CODE_OF_CONDUCT.md); by participating you agree to
|
|
456
|
+
abide by it. To report a security issue, see [SECURITY.md](SECURITY.md).
|
|
457
|
+
Architecture notes live in [docs/design/](docs/design).
|
|
458
|
+
|
|
459
|
+
## License
|
|
460
|
+
|
|
461
|
+
This project is licensed under the **MIT License** – free for personal and commercial use.
|
|
462
|
+
|
|
463
|
+
See [LICENSE](./LICENSE) for details.
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
<br />
|
|
468
|
+
<br />
|
|
469
|
+
|
|
470
|
+
<p align="center">
|
|
471
|
+
Made with ❤️ by <a href="https://github.com/rmyndharis">Yudhi Armyndharis</a> & aimhooman contributors
|
|
472
|
+
</p>
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
aimhooman is itself a security-adjacent tool: it guards repositories against
|
|
4
|
+
AI-tool residue and secrets reaching Git history. This policy covers the
|
|
5
|
+
security of aimhooman itself.
|
|
6
|
+
|
|
7
|
+
## Reporting a vulnerability
|
|
8
|
+
|
|
9
|
+
Please **do not** open a public GitHub issue for security problems.
|
|
10
|
+
|
|
11
|
+
Email **yudhi@rmyndharis.com** with the subject `aimhooman security`. This is
|
|
12
|
+
the currently available private reporting route. Include:
|
|
13
|
+
|
|
14
|
+
- a description of the issue and its impact
|
|
15
|
+
- a minimal reproduction (a command or a small repo)
|
|
16
|
+
- the aimhooman version and Node version
|
|
17
|
+
|
|
18
|
+
We will acknowledge within 72 hours and aim for a fix or mitigation within
|
|
19
|
+
30 days. Coordinated disclosure is preferred; credit is given on request.
|
|
20
|
+
|
|
21
|
+
## Scope
|
|
22
|
+
|
|
23
|
+
**In scope:** the aimhooman codebase — the detection engine, the agent and git
|
|
24
|
+
hooks, the CLI, rule compilation (`globToRegExp`, `compileContent`), and the
|
|
25
|
+
shell-command parser that backs the agent PreToolUse guard (`parseGit` in
|
|
26
|
+
`src/hook.mjs`).
|
|
27
|
+
|
|
28
|
+
**Out of scope:** the contents of the built-in rule packs. False positives in
|
|
29
|
+
which paths are flagged are regular bugs (open a normal issue), not security
|
|
30
|
+
vulnerabilities. aimhooman is a hygiene guard, not a security-enforcement
|
|
31
|
+
mechanism against adversarial threats — a determined actor with commit access
|
|
32
|
+
can always defeat local tooling.
|
|
33
|
+
|
|
34
|
+
## Supported versions
|
|
35
|
+
|
|
36
|
+
Before the first public release, security fixes land on `main`. After publication,
|
|
37
|
+
only the latest minor release will receive security fixes.
|
|
38
|
+
|
|
39
|
+
## Security stance
|
|
40
|
+
|
|
41
|
+
- aimhooman **prevents leaks it has rules for**. It cannot catch novel AI-tool
|
|
42
|
+
artifacts with no rule, and it does not rewrite existing history.
|
|
43
|
+
- The default (`clean`) profile repairs ordinary hygiene findings when it can.
|
|
44
|
+
Invalid local rule packs are skipped with a warning, but corrupt override state,
|
|
45
|
+
incomplete staged-content scans, and unreadable Git targets stop every profile.
|
|
46
|
+
If any blocked path cannot be unstaged or safely repaired, the operation stops.
|
|
47
|
+
The pinned-tree and final-ref guards also stop a remaining or pre-existing tracked
|
|
48
|
+
block. `strict` vetoes instead of attempting clean/compliance repairs and also
|
|
49
|
+
stops review decisions.
|
|
50
|
+
- Local hooks are not a security boundary. Team CI should scan an explicit Git
|
|
51
|
+
range (`aimhooman check --range <base>...<head> --profile strict`), not the
|
|
52
|
+
normally empty staged index of a CI checkout. Ensure the checkout contains
|
|
53
|
+
the merge base (`fetch-depth: 0` on GitHub Actions).
|
|
54
|
+
- A committed `.aimhooman.json` provides the versioned team profile. Invalid
|
|
55
|
+
project policy fails closed; per-clone allow/deny entries remain local and
|
|
56
|
+
should be governed by team process where compliance requires it.
|
|
57
|
+
- This is a personal, owner-only repository with no GitHub approval, required
|
|
58
|
+
reviewer, or `CODEOWNERS` gate. For protected-path changes, CI resolves the
|
|
59
|
+
pinned repository and owner through the GitHub API and fetches the exact
|
|
60
|
+
workflow-run attempt. GitHub must attribute both the actor and triggering actor
|
|
61
|
+
to the owner's login and numeric ID. The resulting decision is bound to the exact head,
|
|
62
|
+
transition commit, path, blob and regular-file mode, or deletion tombstone; a
|
|
63
|
+
policy migration also binds its old and new objects. Non-owner changes fail
|
|
64
|
+
closed with no reviewer fallback. The owner is the trust root, not an independent
|
|
65
|
+
reviewer. These checks verify GitHub attribution, not an interactive human action,
|
|
66
|
+
and cannot defend against malicious or compromised owner credentials.
|
|
67
|
+
- The release pipeline pins actions to immutable commit SHAs and publishes with npm
|
|
68
|
+
build provenance. Pushing a `v*` tag runs the workflow: it installs dependencies,
|
|
69
|
+
runs the test suite, then publishes to npm authenticated by the `NPM_TOKEN` secret
|
|
70
|
+
(use a granular, publish-only, package-scoped npm token with 2FA enabled; rotate it
|
|
71
|
+
regularly). Protect `v*` tags so only the owner can create them and tag update or
|
|
72
|
+
deletion is blocked. Do not publish or move dist-tags manually while a release job
|
|
73
|
+
is pending or running. The npm package is not claimed as available until the release
|
|
74
|
+
workflow completes.
|