amimica

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: MIT

README

Amimica

Amimica

Deterministic, offline code clone detection for Go, JavaScript/TypeScript, and Ruby codebases.

Amimica scans repositories and identifies repetitive code patterns — from exact copy-paste clones to structurally similar but renamed fragments. It reports findings with enough evidence for a human to decide whether and how to refactor.

Works as a standalone CLI and as an MCP server for Claude Code and other MCP-compatible editors.

Quick start

# Clone and build
git clone https://github.com/vinq1911/amimica.git
cd amimica && make build

# Scan a project
./bin/amimica scan /path/to/your/project

# Or install to $GOPATH/bin
make install
amimica scan .

Supported languages

Language Extensions Test detection Generated detection
Go .go *_test.go // Code generated marker
JavaScript .js, .jsx, .mjs .test., .spec., __tests__/ @generated, DO NOT EDIT
TypeScript .ts, .tsx, .mts .test., .spec., __tests__/ @generated, DO NOT EDIT
Ruby .rb, .rake, .gemspec _test.rb, _spec.rb, spec/ DO NOT EDIT, Generated by
Objective-C .m, .mm Tests/, XCTests/ DO NOT EDIT, @generated
C# .cs [Test], [Fact], .Tests/ DO NOT EDIT, *.Designer.cs

All languages are detected automatically by file extension. Mixed-language monorepos work out of the box.

What it detects

Clone type Description How
Exact (Type-1) Identical code ignoring whitespace/comments Normalized hash equality
Renamed (Type-2) Same structure, different identifiers/literals Strong-normalized hash equality
Near-duplicate (Type-3) Structurally similar with small differences Token shingle similarity + MinHash/LSH
Repeated patterns Recurring handler/service/repo scaffolding Normalized block fingerprint clustering

CLI usage

amimica <command> [flags]

Commands:
  scan          Run clone detection analysis
  serve-mcp     Start MCP server for editor/agent integration
  version       Print version and build info
amimica scan
# Scan current directory (all findings)
amimica scan .

# Scan specific paths
amimica scan ./src ./lib ./app

# Limit to top 20 results
amimica scan -n 20 .

# JSON output
amimica scan --output json .

# High-confidence only
amimica scan --min-score 0.5 .

# Exclude test files
amimica scan --exclude-tests .

# Write to file
amimica scan --output json --output-file results.json .

All flags:

Flag Description Default
-n <int> Limit output to N findings (0 = all) 0
--output <fmt> Output format: text, json text
--output-file <path> Write to file instead of stdout stdout
--min-score <float> Minimum score threshold (0.0-1.0) 0.15
--min-lines <int> Minimum lines per region 6
--min-statements <int> Minimum statements per unit 3
--norm-level <level> raw, light, strong, semantic strong
--exclude-tests Skip test files entirely include with penalty
--thorough Enable deeper analysis (slower) off
--no-cache Disable caching cache on
--config <path> Config file path auto-discover
--debug Show pipeline debug info on stderr off

Exit codes:

Code Meaning
0 No findings above threshold
1 Findings detected
2 Configuration or argument error
3 Analysis error

MCP server

Amimica runs as an MCP server for integration with Claude Code, VS Code, and other MCP-compatible clients. The server exposes clone detection as tools that an AI assistant can call during code review, refactoring, or exploration.

Setup
Claude Code

Add to ~/.claude/settings.json (global) or .claude/settings.json (project):

{
  "mcpServers": {
    "amimica": {
      "command": "/absolute/path/to/bin/amimica",
      "args": ["serve-mcp"]
    }
  }
}

With a project-specific config file:

{
  "mcpServers": {
    "amimica": {
      "command": "/absolute/path/to/bin/amimica",
      "args": ["serve-mcp", "--config", ".amimica.yaml"]
    }
  }
}
Other MCP clients

Any MCP client that supports the stdio transport can use Amimica:

amimica serve-mcp [--config <path>] [--log-file <path>]

The server reads JSON-RPC from stdin and writes responses to stdout. Logs go to stderr (suppressed by default during MCP; use --log-file to capture).

Protocol
  • Transport: stdio (JSON-RPC 2.0 over stdin/stdout)
  • Protocol version: 2024-11-05
  • Capabilities: tools
Output codes

MCP output is token-optimized. All tools use short codes:

Clone types:

Code Meaning
EX Exact — identical code
RN Renamed — same structure, different identifiers
ND Near-duplicate — similar with small differences
PT Pattern — recurring structural idiom

Refactor hints (shown as →XX):

Code Meaning
EH Extract helper function
TD Table-driven refactor
IE Interface extraction
GF Generic function
SV Shared validator
AM Adapter/mapper
CD Config-driven

Score fields in explain: conf= confidence, sim= similarity, imp= impact, ref= refactorability.

Tools
scan

Scan directories for code clones. Returns compact summary + scan_id.

Input: paths (string[], default [".""]), min_score (number), max_results (int)

Example output:

53 files 253 funcs 112ms | 17 clones | sid:scan-1
#1 0.72 ND 2r →EH
  internal/trunk/store.go:349-373 syncTrunkList
  internal/trunk/store.go:376-400 syncOperatorList
#2 0.67 ND 2r →EH
  internal/events/events.go:34-49 ToMap
  internal/events/events.go:63-77 ToMap
+12 more → list_findings sid:scan-1

Reading: #1 0.72 ND 2r →EH = finding #1, score 0.72, near-duplicate, 2 regions, suggest extract-helper.

list_findings

Paginated findings from a scan with IDs for follow-up.

Input: scan_id (required), min_score, limit (default 20), offset

Example output:

#6 F-0f7071ff85 0.68 RN 2r →EH
  rtp.go:277-303 decodePCMA
  codecs/pcma.go:12-38 DecodePCMA
explain_finding

Detailed breakdown of one finding. Normalized form truncated by default.

Input: scan_id (required), finding_id (required), verbose (bool, default false — set true for full normalized form)

Example output:

F-73696bd249 ND 0.72 conf=0.80 sim=1.00 imp=0.33 ref=1.00
  internal/trunk/store.go:349-373 syncTrunkList
  internal/trunk/store.go:376-400 syncOperatorList
norm: ($R * TrunkStore) func $FUNC ($P0 $V0.Context) (error) {$V1, $V2 := $R.db.DB.QueryContext... (set verbose:true for full)
hint: EH 75% Two regions with identical normalized structure. Extract a shared helper function.
penalties: only 2 members(×0.9)
compare_regions

Side-by-side source code from two regions.

Input: file_a, start_line_a, end_line_a, file_b, start_line_b, end_line_b (all required)

MCP workflow
  1. scan with paths: ["."] → get scan_id
  2. list_findings with scan_id, min_score: 0.5 → browse results with finding IDs
  3. explain_finding with finding_id → understand the clone
  4. compare_regions with file paths and line numbers → see actual code
  5. Suggest refactoring based on clone type and hints
Session model
  • Scan results are stored in memory for the lifetime of the MCP session
  • Each scan call returns a unique scan_id — subsequent tools reference it
  • Multiple scans can coexist (e.g., scan different directories)
  • Results are ephemeral — they're gone when the server stops
Error handling

Tool errors are returned as MCP tool results with isError: true, not as JSON-RPC errors. This allows the AI to read and react to the error message.

Common errors:

  • "scan_id not found" — run scan first
  • "finding_id not found" — check the ID from list_findings
  • "read <file>: no such file" — path doesn't exist

Ignoring findings

Add an amimica-ignore comment above any function to exclude it from analysis:

// amimica-ignore: intentionally duplicated for performance
func handleSpecialCase(ctx context.Context) error {
// amimica-ignore
function legacyHandler(req: Request) {
# amimica-ignore
def process(document)

The comment must appear within 2 lines above the function definition. An optional reason after the colon is for documentation only.


Configuration

Create .amimica.yaml in your project root (or ~/.config/amimica/config.yaml for global defaults):

version: 1

analysis:
  normalization_level: strong   # raw | light | strong | semantic
  min_statements: 3
  min_lines: 6
  window_size: 5

scoring:
  min_score: 0.15
  max_findings: 0               # 0 = no limit

paths:
  exclude:
    - "vendor/**"
    - "**/*.pb.go"
    - "**/*.min.js"
    - "**/*.bundle.js"
    - "**/dist/**"
  include_tests: true           # test files included with score penalty
  include_vendor: false
  follow_symlinks: false

Environment variables override config: AMIMICA_ANALYSIS_NORMALIZATION_LEVEL=semantic


How it works

Discovery → Parser → Normalizer → Extractor → Fingerprinter → Matcher → Scorer → Reporter
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            Language-specific (per language)
                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                              Language-agnostic (shared pipeline)
  1. Discovery finds source files by extension, skips minified/bundled files, applies include/exclude patterns
  2. Parser tokenizes source (Go uses go/parser; JS/TS and Ruby use built-in tokenizers)
  3. Normalizer transforms tokens at 4 levels:
    • Raw: strip comments/whitespace
    • Light: replace literals with $STR, $INT, $FLOAT
    • Strong: replace identifiers with positional placeholders $V0, $P0, $R
    • Semantic: abstract selectors and type names
  4. Extractor segments into analysis units (functions, sliding statement windows)
  5. Fingerprinter computes SHA-256 hashes, 7-token shingles, 128-function MinHash signatures
  6. Matcher groups exact matches by hash, uses 16-band LSH for approximate matches, clusters with union-find
  7. Scorer ranks findings by weighted composite (confidence, similarity, impact, refactorability), applies penalties, merges overlapping windows, deduplicates against function-level matches
  8. Reporter formats output as terminal text or JSON

Skills for Claude Code

The skills/ directory contains Claude Code skill files that teach Claude how to use Amimica:

# Install skills globally
cp skills/*.md ~/.claude/skills/

# Or link them
ln -s $(pwd)/skills/*.md ~/.claude/skills/

Available skills:

  • amimica-scan.md — CLI and MCP usage reference
  • amimica-mcp-setup.md — Step-by-step MCP server configuration

Development

make help          # Show all targets
make build         # Build binary to bin/amimica
make install       # Install to $GOPATH/bin
make test          # Tests with race detection
make test-cover    # Coverage report
make check         # fmt + vet + test
make doctor        # Check dev environment
make run ARGS="scan ."  # Build and run

Requirements

  • Go 1.25+ (to build from source)
  • golangci-lint (optional, for make lint)

Contributing

All contributions are welcome! Bug fixes, new language support, detection improvements, documentation — open a PR.

# Fork, clone, create a branch
git checkout -b my-feature

# Make changes, then verify
make check          # fmt + vet + test
make run ARGS="scan ."  # smoke test

# Push and open a PR
git push origin my-feature

If you're adding a new language, see internal/lang/ for the Language interface and existing implementations (Go, JS/TS, Ruby) as examples.

License

MIT

Directories

Path Synopsis
cmd
amimica command
Command amimica is a deterministic, offline code clone detection tool for Go codebases.
Command amimica is a deterministic, offline code clone detection tool for Go codebases.
internal
app
Package app implements the CLI command handlers.
Package app implements the CLI command handlers.
config
Package config handles loading, defaulting, environment override, and validation of the Amimica configuration file (.amimica.yaml or ~/.config/amimica/config.yaml).
Package config handles loading, defaulting, environment override, and validation of the Amimica configuration file (.amimica.yaml or ~/.config/amimica/config.yaml).
discovery
Package discovery walks repositories to find source files for analysis.
Package discovery walks repositories to find source files for analysis.
engine
Package engine orchestrates the clone detection pipeline: discovery -> parsing/normalization/extraction -> fingerprinting -> matching -> scoring.
Package engine orchestrates the clone detection pipeline: discovery -> parsing/normalization/extraction -> fingerprinting -> matching -> scoring.
extract
Package extract segments parsed and normalized Go ASTs into analysis units: whole functions, statement windows, and inner blocks.
Package extract segments parsed and normalized Go ASTs into analysis units: whole functions, statement windows, and inner blocks.
fingerprint
Package fingerprint computes hash-based fingerprints for normalized code units.
Package fingerprint computes hash-based fingerprints for normalized code units.
fsguard
Package fsguard implements path sandboxing and security validation for file system access.
Package fsguard implements path sandboxing and security validation for file system access.
lang
Package lang defines the Language interface that abstracts language-specific parsing, normalization, and extraction.
Package lang defines the Language interface that abstracts language-specific parsing, normalization, and extraction.
lang/csharp
Package csharp implements the Language interface for C# source files.
Package csharp implements the Language interface for C# source files.
lang/golang
Package golang implements the Language interface for Go source files.
Package golang implements the Language interface for Go source files.
lang/javascript
Package javascript implements the Language interface for JavaScript, TypeScript, JSX, and TSX files.
Package javascript implements the Language interface for JavaScript, TypeScript, JSX, and TSX files.
lang/objc
Package objc implements the Language interface for Objective-C source files.
Package objc implements the Language interface for Objective-C source files.
lang/ruby
Package ruby implements the Language interface for Ruby source files.
Package ruby implements the Language interface for Ruby source files.
logging
Package logging provides a thin wrapper around Go's structured logging package (log/slog).
Package logging provides a thin wrapper around Go's structured logging package (log/slog).
match
Package match groups normalized units into clone classes using exact hash matching and approximate similarity via MinHash/LSH.
Package match groups normalized units into clone classes using exact hash matching and approximate similarity via MinHash/LSH.
mcp
Package mcp implements an MCP (Model Context Protocol) server that exposes Amimica's clone detection as tools for editor and agent integration.
Package mcp implements an MCP (Model Context Protocol) server that exposes Amimica's clone detection as tools for editor and agent integration.
model
Package model defines the core shared data types used throughout the Amimica code clone detection pipeline.
Package model defines the core shared data types used throughout the Amimica code clone detection pipeline.
normalize
Package normalize transforms Go AST nodes into normalized token sequences at multiple levels of abstraction.
Package normalize transforms Go AST nodes into normalized token sequences at multiple levels of abstraction.
parser
Package parser wraps Go's go/parser to produce ASTs from source files with error tolerance.
Package parser wraps Go's go/parser to produce ASTs from source files with error tolerance.
report
Package report formats analysis findings for output.
Package report formats analysis findings for output.
score
Package score assigns quality scores to clone findings and filters noise.
Package score assigns quality scores to clone findings and filters noise.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL