|
1 | | -# js-ai-driven-development-pipeline-template |
| 1 | +# set-process-name |
2 | 2 |
|
3 | | -A comprehensive template for AI-driven JavaScript/TypeScript development with full CI/CD pipeline support. |
| 3 | +Cross-platform, multi-runtime library to set the process name visible in system monitoring tools (top, ps, htop, Activity Monitor, Task Manager, etc.). |
4 | 4 |
|
5 | 5 | ## Features |
6 | 6 |
|
7 | | -- **Multi-runtime support**: Works with Bun, Node.js, and Deno |
8 | | -- **Universal testing**: Uses [test-anywhere](https://github.com/link-foundation/test-anywhere) for cross-runtime tests |
9 | | -- **Automated releases**: Changesets-based versioning with GitHub Actions |
10 | | -- **Code quality**: ESLint + Prettier with pre-commit hooks via Husky |
11 | | -- **Package manager agnostic**: Works with bun, npm, yarn, pnpm, and deno |
| 7 | +- **Multi-runtime support**: Works with Node.js, Bun, and Deno |
| 8 | +- **Cross-platform**: Supports Linux, macOS, and Windows |
| 9 | +- **Zero dependencies**: Pure JavaScript with optional FFI for enhanced Linux support |
| 10 | +- **TypeScript support**: Full type definitions included |
| 11 | +- **Comprehensive API**: Async and sync versions, getters, and capability detection |
| 12 | + |
| 13 | +## Installation |
| 14 | + |
| 15 | +```bash |
| 16 | +# npm |
| 17 | +npm install set-process-name |
| 18 | + |
| 19 | +# bun |
| 20 | +bun add set-process-name |
| 21 | + |
| 22 | +# deno |
| 23 | +deno add jsr:@link-foundation/set-process-name |
| 24 | +``` |
12 | 25 |
|
13 | 26 | ## Quick Start |
14 | 27 |
|
15 | | -### Using This Template |
| 28 | +```javascript |
| 29 | +import { setProcessName } from 'set-process-name'; |
16 | 30 |
|
17 | | -1. Click "Use this template" on GitHub to create a new repository |
18 | | -2. Clone your new repository |
19 | | -3. Update `package.json` with your package name and description |
20 | | -4. Update the `PACKAGE_NAME` constant in these scripts: |
21 | | - - `scripts/validate-changeset.mjs` |
22 | | - - `scripts/merge-changesets.mjs` |
23 | | - - `scripts/publish-to-npm.mjs` |
24 | | - - `scripts/format-release-notes.mjs` |
25 | | - - `scripts/create-manual-changeset.mjs` |
26 | | -5. Install dependencies: `bun install` |
27 | | -6. Start developing! |
| 31 | +// Set the process name |
| 32 | +await setProcessName('my-app'); |
28 | 33 |
|
29 | | -### Development |
| 34 | +// Now 'my-app' appears in top, ps, htop instead of 'node' or 'bun' |
| 35 | +``` |
30 | 36 |
|
31 | | -```bash |
32 | | -# Install dependencies |
33 | | -bun install |
| 37 | +## API Reference |
34 | 38 |
|
35 | | -# Run tests |
36 | | -bun test |
| 39 | +### `setProcessName(name: string): Promise<SetProcessNameResult>` |
37 | 40 |
|
38 | | -# Or with other runtimes: |
39 | | -npm test |
40 | | -deno test --allow-read |
| 41 | +Sets the process name visible in system monitoring tools. |
41 | 42 |
|
42 | | -# Lint code |
43 | | -bun run lint |
| 43 | +```javascript |
| 44 | +import { setProcessName } from 'set-process-name'; |
44 | 45 |
|
45 | | -# Format code |
46 | | -bun run format |
| 46 | +const result = await setProcessName('my-service'); |
47 | 47 |
|
48 | | -# Check all (lint + format + file size) |
49 | | -bun run check |
| 48 | +console.log(result); |
| 49 | +// { |
| 50 | +// success: true, |
| 51 | +// processTitle: true, // process.title was set successfully |
| 52 | +// prctl: true, // prctl was called successfully (Linux only) |
| 53 | +// runtime: 'node', // detected runtime |
| 54 | +// platform: 'linux' // detected platform |
| 55 | +// } |
50 | 56 | ``` |
51 | 57 |
|
52 | | -## Project Structure |
| 58 | +### `setProcessNameSync(name: string): SetProcessNameResult` |
| 59 | + |
| 60 | +Synchronous version. Note: On Bun runtime, prctl changes may not be applied (use async version for full functionality). |
53 | 61 |
|
| 62 | +```javascript |
| 63 | +import { setProcessNameSync } from 'set-process-name'; |
| 64 | + |
| 65 | +const result = setProcessNameSync('my-service'); |
54 | 66 | ``` |
55 | | -. |
56 | | -├── .changeset/ # Changeset configuration |
57 | | -├── .github/workflows/ # GitHub Actions CI/CD |
58 | | -├── .husky/ # Git hooks (pre-commit) |
59 | | -├── examples/ # Usage examples |
60 | | -├── scripts/ # Build and release scripts |
61 | | -├── src/ # Source code |
62 | | -│ ├── index.js # Main entry point |
63 | | -│ └── index.d.ts # TypeScript definitions |
64 | | -├── tests/ # Test files |
65 | | -├── .eslintrc.js # ESLint configuration |
66 | | -├── .prettierrc # Prettier configuration |
67 | | -├── bunfig.toml # Bun configuration |
68 | | -├── deno.json # Deno configuration |
69 | | -└── package.json # Node.js package manifest |
| 67 | + |
| 68 | +### `getProcessName(): string | null` |
| 69 | + |
| 70 | +Gets the current process name from `process.title`. |
| 71 | + |
| 72 | +```javascript |
| 73 | +import { getProcessName, setProcessName } from 'set-process-name'; |
| 74 | + |
| 75 | +await setProcessName('my-app'); |
| 76 | +console.log(getProcessName()); // 'my-app' |
70 | 77 | ``` |
71 | 78 |
|
72 | | -## Design Choices |
| 79 | +### `getCapabilities(): Capabilities` |
| 80 | + |
| 81 | +Returns information about what features are available on the current platform/runtime. |
73 | 82 |
|
74 | | -### Multi-Runtime Support |
| 83 | +```javascript |
| 84 | +import { getCapabilities } from 'set-process-name'; |
| 85 | + |
| 86 | +const caps = getCapabilities(); |
| 87 | +console.log(caps); |
| 88 | +// { |
| 89 | +// canSetTitle: true, // process.title can be set |
| 90 | +// canSetPrctl: true, // prctl is available (Linux only) |
| 91 | +// runtime: 'node', |
| 92 | +// platform: 'linux' |
| 93 | +// } |
| 94 | +``` |
75 | 95 |
|
76 | | -This template is designed to work seamlessly with all major JavaScript runtimes: |
| 96 | +### `detectRuntime(): 'node' | 'bun' | 'deno' | 'unknown'` |
77 | 97 |
|
78 | | -- **Bun**: Primary runtime with highest performance, uses native test support (`bun test`) |
79 | | -- **Node.js**: Alternative runtime, uses built-in test runner (`node --test`) |
80 | | -- **Deno**: Secure runtime with built-in TypeScript support (`deno test`) |
| 98 | +Detects the current JavaScript runtime. |
81 | 99 |
|
82 | | -The [test-anywhere](https://github.com/link-foundation/test-anywhere) framework provides a unified testing API that works identically across all runtimes. |
| 100 | +### `detectPlatform(): 'linux' | 'darwin' | 'win32' | 'unknown'` |
83 | 101 |
|
84 | | -### Package Manager Agnostic |
| 102 | +Detects the current operating system. |
85 | 103 |
|
86 | | -While `package.json` is the source of truth for dependencies, the template supports: |
| 104 | +## Platform-Specific Behavior |
87 | 105 |
|
88 | | -- **bun**: Primary choice, uses `bun.lockb` |
89 | | -- **npm**: Uses `package-lock.json` |
90 | | -- **yarn**: Uses `yarn.lock` |
91 | | -- **pnpm**: Uses `pnpm-lock.yaml` |
92 | | -- **deno**: Uses `deno.json` for configuration |
| 106 | +### Linux |
93 | 107 |
|
94 | | -Note: `package-lock.json` is not committed by default to allow any package manager. |
| 108 | +- Uses `process.title` (which internally uses `prctl` via libuv in Node.js) |
| 109 | +- On Bun/Deno: Uses FFI to call `prctl(PR_SET_NAME, name)` directly |
| 110 | +- Name is truncated to 15 characters (Linux kernel limitation for `/proc/<pid>/comm`) |
| 111 | +- Process name visible in `top`, `ps`, `htop`, and `/proc/<pid>/comm` |
95 | 112 |
|
96 | | -### Code Quality |
| 113 | +### macOS |
97 | 114 |
|
98 | | -- **ESLint**: Configured with recommended rules + Prettier integration |
99 | | -- **Prettier**: Consistent code formatting |
100 | | -- **Husky + lint-staged**: Pre-commit hooks ensure code quality |
101 | | -- **File size limit**: Scripts must stay under 1000 lines for maintainability |
| 115 | +- Uses `process.title` which works via libuv in Node.js |
| 116 | +- Process name visible in Activity Monitor and `ps` |
102 | 117 |
|
103 | | -### Release Workflow |
| 118 | +### Windows |
104 | 119 |
|
105 | | -The release workflow uses [Changesets](https://github.com/changesets/changesets) for version management: |
| 120 | +- Uses `process.title` for console title |
| 121 | +- Task Manager always shows executable name (cosmetic only) |
106 | 122 |
|
107 | | -1. **Creating a changeset**: Run `bun run changeset` to document changes |
108 | | -2. **PR validation**: CI checks for valid changeset in each PR |
109 | | -3. **Automated versioning**: Merging to `main` triggers version bump |
110 | | -4. **npm publishing**: Automated via OIDC trusted publishing (no tokens needed) |
111 | | -5. **GitHub releases**: Auto-created with formatted release notes |
| 123 | +## Runtime Support |
112 | 124 |
|
113 | | -#### Manual Releases |
| 125 | +| Runtime | process.title | prctl (Linux) | |
| 126 | +| ------- | ------------- | -------------- | |
| 127 | +| Node.js | ✅ | ✅ (via libuv) | |
| 128 | +| Bun | ✅ | ✅ (via FFI) | |
| 129 | +| Deno | ✅ | ✅ (via FFI) | |
114 | 130 |
|
115 | | -Two manual release modes are available via GitHub Actions: |
| 131 | +## Examples |
116 | 132 |
|
117 | | -- **Instant release**: Immediately bump version and publish |
118 | | -- **Changeset PR**: Create a PR with changeset for review |
| 133 | +### Basic Usage |
119 | 134 |
|
120 | | -### CI/CD Pipeline |
| 135 | +```javascript |
| 136 | +import { setProcessName, getProcessName } from 'set-process-name'; |
121 | 137 |
|
122 | | -The GitHub Actions workflow (`.github/workflows/release.yml`) provides: |
| 138 | +async function main() { |
| 139 | + console.log('Before:', getProcessName()); // 'node' |
123 | 140 |
|
124 | | -1. **Changeset check**: Validates PR has exactly one changeset (added by that PR) |
125 | | -2. **Lint & format**: Ensures code quality standards |
126 | | -3. **Test matrix**: 3 runtimes × 3 OS = 9 test combinations |
127 | | -4. **Changeset merge**: Combines multiple pending changesets at release time |
128 | | -5. **Release**: Automated versioning and npm publishing |
| 141 | + await setProcessName('my-daemon'); |
129 | 142 |
|
130 | | -#### Robust Changeset Handling |
| 143 | + console.log('After:', getProcessName()); // 'my-daemon' |
| 144 | +} |
131 | 145 |
|
132 | | -The CI/CD pipeline is designed to handle concurrent PRs gracefully: |
| 146 | +main(); |
| 147 | +``` |
133 | 148 |
|
134 | | -- **PR Validation**: Only validates changesets **added by the current PR**, not pre-existing ones from other merged PRs. This prevents false failures when multiple PRs merge before a release cycle completes. |
| 149 | +### With Capability Check |
135 | 150 |
|
136 | | -- **Release-time Merging**: If multiple changesets exist when releasing, they are automatically merged into a single changeset with: |
137 | | - - The highest version bump type (major > minor > patch) |
138 | | - - All descriptions preserved in chronological order |
| 151 | +```javascript |
| 152 | +import { setProcessName, getCapabilities } from 'set-process-name'; |
139 | 153 |
|
140 | | -This design decouples PR validation from the need to pull changes from the default branch, reducing conflicts and ensuring that even if CI/CD fails, all unpublished changesets will still get published when the error is resolved. |
| 154 | +const caps = getCapabilities(); |
141 | 155 |
|
142 | | -## Configuration |
| 156 | +if (caps.canSetPrctl) { |
| 157 | + console.log('Full Linux prctl support available'); |
| 158 | +} |
143 | 159 |
|
144 | | -### Updating Package Name |
| 160 | +const result = await setProcessName('worker-1'); |
145 | 161 |
|
146 | | -After creating a repository from this template, update the package name in: |
| 162 | +if (result.success) { |
| 163 | + console.log('Process name set successfully'); |
| 164 | +} else { |
| 165 | + console.log('Could not set process name (non-critical)'); |
| 166 | +} |
| 167 | +``` |
147 | 168 |
|
148 | | -1. `package.json`: `"name": "your-package-name"` |
149 | | -2. `.changeset/config.json`: Package references |
150 | | -3. Scripts that reference the package name (see Quick Start) |
| 169 | +### CLI Application |
151 | 170 |
|
152 | | -### ESLint Rules |
| 171 | +```javascript |
| 172 | +#!/usr/bin/env node |
| 173 | +import { setProcessName } from 'set-process-name'; |
153 | 174 |
|
154 | | -Customize ESLint in `eslint.config.js`. Current configuration: |
| 175 | +// Set process name at startup |
| 176 | +await setProcessName('my-cli'); |
155 | 177 |
|
156 | | -- ES Modules support |
157 | | -- Prettier integration |
158 | | -- No console restrictions (common in CLI tools) |
159 | | -- Strict equality enforcement |
160 | | -- Async/await best practices |
161 | | -- **Strict unused variables rule**: No exceptions - all unused variables, arguments, and caught errors must be removed (no `_` prefix exceptions) |
| 178 | +// Your CLI code here... |
| 179 | +``` |
162 | 180 |
|
163 | | -### Prettier Options |
| 181 | +## TypeScript |
164 | 182 |
|
165 | | -Configured in `.prettierrc`: |
| 183 | +Full TypeScript support with type definitions: |
166 | 184 |
|
167 | | -- Single quotes |
168 | | -- Semicolons |
169 | | -- 2-space indentation |
170 | | -- 80-character line width |
171 | | -- ES5 trailing commas |
172 | | -- LF line endings |
| 185 | +```typescript |
| 186 | +import { |
| 187 | + setProcessName, |
| 188 | + SetProcessNameResult, |
| 189 | + Capabilities, |
| 190 | + Runtime, |
| 191 | + Platform, |
| 192 | +} from 'set-process-name'; |
173 | 193 |
|
174 | | -## Scripts Reference |
| 194 | +const result: SetProcessNameResult = await setProcessName('typed-app'); |
| 195 | +``` |
175 | 196 |
|
176 | | -| Script | Description | |
177 | | -| ---------------------- | --------------------------------------- | |
178 | | -| `bun test` | Run tests with Bun | |
179 | | -| `bun run lint` | Check code with ESLint | |
180 | | -| `bun run lint:fix` | Fix ESLint issues automatically | |
181 | | -| `bun run format` | Format code with Prettier | |
182 | | -| `bun run format:check` | Check formatting without changing files | |
183 | | -| `bun run check` | Run all checks (lint + format) | |
184 | | -| `bun run changeset` | Create a new changeset | |
| 197 | +## Testing |
185 | 198 |
|
186 | | -## Contributing |
| 199 | +```bash |
| 200 | +# Node.js |
| 201 | +npm test |
| 202 | + |
| 203 | +# Bun |
| 204 | +bun test |
| 205 | + |
| 206 | +# Deno |
| 207 | +deno test --allow-read |
| 208 | +``` |
187 | 209 |
|
188 | | -1. Fork the repository |
189 | | -2. Create a feature branch: `git checkout -b feature/my-feature` |
190 | | -3. Make your changes |
191 | | -4. Create a changeset: `bun run changeset` |
192 | | -5. Commit your changes (pre-commit hooks will run automatically) |
193 | | -6. Push and create a Pull Request |
| 210 | +## How It Works |
| 211 | + |
| 212 | +1. **JavaScript Level**: Sets `process.title` and `process.argv0` |
| 213 | +2. **Node.js**: `process.title` setter uses libuv which internally calls `prctl` on Linux |
| 214 | +3. **Bun/Deno on Linux**: Uses FFI to call `prctl(PR_SET_NAME, name)` directly |
| 215 | +4. **macOS/Windows**: Relies on `process.title` for best-effort support |
| 216 | + |
| 217 | +## Comparison with Alternatives |
| 218 | + |
| 219 | +| Feature | set-process-name | process-title | process-name | |
| 220 | +| ------------------ | ---------------- | ------------- | ------------ | |
| 221 | +| Set process name | ✅ | ✅ | ❌ | |
| 222 | +| Linux prctl | ✅ | ❌ | ❌ | |
| 223 | +| Node.js | ✅ | ✅ | ✅ | |
| 224 | +| Bun | ✅ | ❌ | ❌ | |
| 225 | +| Deno | ✅ | ❌ | ❌ | |
| 226 | +| Zero dependencies | ✅ | ✅ | ❌ | |
| 227 | +| TypeScript support | ✅ | ❌ | ❌ | |
| 228 | +| Active maintenance | ✅ | ❌ | ❌ | |
194 | 229 |
|
195 | 230 | ## License |
196 | 231 |
|
|
0 commit comments