Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,16 +267,18 @@ stacklit setup cursor # configure Cursor + MCP
```

<details>
<summary>Configuration (stacklit.toml)</summary>
<summary>Configuration (.stacklitrc.json)</summary>

```toml
ignore = ["vendor/", "generated/"]
max_depth = 3

[output]
json = "stacklit.json"
mermaid = "DEPENDENCIES.md"
html = "stacklit.html"
```json
{
"ignore": ["vendor/", "generated/"],
"max_depth": 3,
"output": {
"json": "stacklit.json",
"mermaid": "DEPENDENCIES.md",
"html": "stacklit.html"
}
}
```

</details>
Expand Down
34 changes: 15 additions & 19 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,28 +152,24 @@ The server auto-reloads when `stacklit.json` changes on disk.

## Configuration

Create `stacklit.toml` in your project root (optional):
Create `.stacklitrc.json` in your project root (optional):

```toml
# Paths to ignore on top of .gitignore
ignore = ["vendor/", "generated/", "*.pb.go"]

# Module detection depth (default: 4)
max_depth = 3

# Max modules before collapsing (default: 200)
max_modules = 150

# Max exports per module (default: 10)
max_exports = 15

# Output file names
[output]
json = "stacklit.json"
mermaid = "DEPENDENCIES.md"
html = "stacklit.html"
```json
{
"ignore": ["vendor/", "generated/", "*.pb.go"],
"max_depth": 3,
"max_modules": 150,
"max_exports": 15,
"output": {
"json": "stacklit.json",
"mermaid": "DEPENDENCIES.md",
"html": "stacklit.html"
}
}
```

Keys: `ignore` (extra paths on top of `.gitignore`), `max_depth` (module detection depth, default 4), `max_modules` (collapse threshold, default 200), `max_exports` (per module, default 10), and `output` (override generated file names).

---

## Reading stacklit.json
Expand Down
61 changes: 47 additions & 14 deletions npm/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const os = require('os');
const fs = require('fs');
const path = require('path');
const https = require('https');
const { execSync } = require('child_process');
const { execFileSync } = require('child_process');

const VERSION = '0.3.0';
const REPO = 'glincker/stacklit';
Expand Down Expand Up @@ -77,25 +77,58 @@ async function install() {
return;
}

// Extract
if (archivePath.endsWith('.zip') || url.endsWith('.zip')) {
execSync(`unzip -o "${archivePath}" stacklit.exe -d "${binDir}"`, { stdio: 'ignore' });
} else {
execSync(`tar -xzf "${archivePath}" -C "${binDir}" stacklit`, { stdio: 'ignore' });
}

// Make executable
if (os.platform() !== 'win32') {
fs.chmodSync(binPath, 0o755);
try {
// Extract. execFileSync passes args directly to the binary, so no shell
// quoting of paths is needed. On Windows we hand paths to PowerShell via
// env vars so a single quote in __dirname (e.g. C:\Users\O'Connor\...)
// cannot terminate the script string.
if (url.endsWith('.zip')) {
if (os.platform() === 'win32') {
execFileSync(
'powershell',
[
'-NoProfile',
'-ExecutionPolicy', 'Bypass',
'-Command',
'Expand-Archive -Force -LiteralPath $env:STACKLIT_ARCHIVE -DestinationPath $env:STACKLIT_BINDIR',
],
{
stdio: 'inherit',
env: { ...process.env, STACKLIT_ARCHIVE: archivePath, STACKLIT_BINDIR: binDir },
}
);
} else {
execFileSync('unzip', ['-o', archivePath, 'stacklit.exe', '-d', binDir], { stdio: 'inherit' });
}
} else {
execFileSync('tar', ['-xzf', archivePath, '-C', binDir, 'stacklit'], { stdio: 'inherit' });
}

if (!fs.existsSync(binPath)) {
throw new Error(`extraction completed but ${binPath} is missing`);
}

if (os.platform() !== 'win32') {
fs.chmodSync(binPath, 0o755);
}
} finally {
if (fs.existsSync(archivePath)) {
try {
fs.unlinkSync(archivePath);
} catch (cleanupErr) {
// best-effort cleanup; warn but don't mask the original failure
console.warn(`Could not remove ${archivePath}: ${cleanupErr.message}`);
}
}
}

// Cleanup
fs.unlinkSync(archivePath);

console.log('stacklit installed successfully.');
}

install().catch((err) => {
console.error('Installation failed:', err.message);
console.error('You can install manually: go install github.com/glincker/stacklit/cmd/stacklit@latest');
// Surface the failure to npm so postinstall doesn't appear to succeed when
// the binary is actually missing or extraction broke.
process.exitCode = 1;
});
Loading