termi-gotchi 1.0.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/dist/app.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ type Props = {
3
+ name: string | undefined;
4
+ };
5
+ export default function App({ name }: Props): React.JSX.Element;
6
+ export {};
package/dist/app.js ADDED
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { Text } from 'ink';
3
+ export default function App({ name = 'Stranger' }) {
4
+ return (React.createElement(Text, null,
5
+ "Hello, ",
6
+ React.createElement(Text, { color: "green" }, name)));
7
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,78 @@
1
+ import React from 'react';
2
+ import { render } from 'ink';
3
+ import meow from 'meow';
4
+ import { App } from './ui.js';
5
+ import { getPet, feedPet } from './logic.js';
6
+ import { simpleGit } from 'simple-git';
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ const cli = meow(`
10
+ Usage
11
+ $ termi-gotchi
12
+
13
+ Commands
14
+ feed Feed the pet (runs automatically by git hook)
15
+ init Install the git hook
16
+
17
+ Examples
18
+ $ termi-gotchi
19
+ $ termi-gotchi init
20
+ `, {
21
+ importMeta: import.meta,
22
+ });
23
+ const run = async () => {
24
+ const command = cli.input[0];
25
+ if (command === 'init') {
26
+ const gitHookPath = path.resolve(process.cwd(), '.git/hooks/post-commit');
27
+ // Check if .git exists
28
+ if (!fs.existsSync(path.resolve(process.cwd(), '.git'))) {
29
+ console.error('Error: Not a git repository. Run "git init" first.');
30
+ process.exit(1);
31
+ }
32
+ const hookScript = `#!/bin/sh
33
+ # Run termi-gotchi after every commit
34
+ termi-gotchi feed
35
+ `;
36
+ fs.writeFileSync(gitHookPath, hookScript);
37
+ fs.chmodSync(gitHookPath, '755');
38
+ console.log("Git Hook Installed! Your pet is watching...");
39
+ return;
40
+ }
41
+ if (command === 'feed') {
42
+ const git = simpleGit();
43
+ try {
44
+ // Try to get diff from last commit
45
+ // If it's the first commit, HEAD^ might fail.
46
+ // basic try-catch for now.
47
+ let insertions = 0;
48
+ let deletions = 0;
49
+ try {
50
+ const diff = await git.diffSummary(['HEAD^', 'HEAD']);
51
+ insertions = diff.insertions;
52
+ deletions = diff.deletions;
53
+ }
54
+ catch (e) {
55
+ // Fallback for first commit or other errors
56
+ // Maybe list files? For now, just give some default xp
57
+ insertions = 10;
58
+ }
59
+ const result = feedPet(insertions, deletions);
60
+ // We could just print a message, but rendering the App is cooler.
61
+ // Ideally we render it and then exit after a few seconds?
62
+ // Ink apps run until unmounted.
63
+ // We can just render it and let the user Ctrl+C or we can exit automatically.
64
+ // For post-commit hook, we probably want it to exit automatically.
65
+ // Let's pass a prop to App to auto-exit? Or just handle it here.
66
+ const { unmount } = render(React.createElement(App, { pet: result }));
67
+ setTimeout(() => unmount(), 2500);
68
+ return;
69
+ }
70
+ catch (e) {
71
+ console.error("Error feeding pet:", e);
72
+ }
73
+ }
74
+ // Default: Show status
75
+ const pet = getPet();
76
+ render(React.createElement(App, { pet: pet }));
77
+ };
78
+ run();
@@ -0,0 +1,19 @@
1
+ export interface PetState {
2
+ name: string;
3
+ level: number;
4
+ xp: number;
5
+ health: number;
6
+ lastFed: string;
7
+ poopCount: number;
8
+ event?: string;
9
+ }
10
+ export declare const getPet: () => PetState;
11
+ export declare const feedPet: (linesAdded: number, linesDeleted: number) => {
12
+ event: string;
13
+ name: string;
14
+ level: number;
15
+ xp: number;
16
+ health: number;
17
+ lastFed: string;
18
+ poopCount: number;
19
+ };
package/dist/logic.js ADDED
@@ -0,0 +1,30 @@
1
+ import Conf from 'conf';
2
+ const config = new Conf({
3
+ projectName: 'termi-gotchi',
4
+ defaults: {
5
+ name: 'Git-Mon',
6
+ level: 1,
7
+ xp: 0,
8
+ health: 100,
9
+ lastFed: new Date().toISOString(),
10
+ poopCount: 0
11
+ }
12
+ });
13
+ export const getPet = () => config.store;
14
+ export const feedPet = (linesAdded, linesDeleted) => {
15
+ const pet = getPet();
16
+ // Logic: deletions are better (refactoring)
17
+ const nutrition = (linesAdded * 0.1) + (linesDeleted * 0.5);
18
+ pet.xp += nutrition;
19
+ pet.health = Math.min(100, pet.health + 10);
20
+ pet.lastFed = new Date().toISOString();
21
+ let event = 'EATING';
22
+ // Level up logic
23
+ if (pet.xp > pet.level * 50) {
24
+ pet.level++;
25
+ pet.xp = 0;
26
+ event = 'LEVEL_UP';
27
+ }
28
+ config.set(pet);
29
+ return { ...pet, event };
30
+ };
package/dist/ui.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import { PetState } from './logic.js';
3
+ export declare const App: ({ pet }: {
4
+ pet: PetState;
5
+ }) => React.JSX.Element;
package/dist/ui.js ADDED
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import { Box, Text } from 'ink';
3
+ import Gradient from 'ink-gradient';
4
+ import BigText from 'ink-big-text';
5
+ const PetAvatar = ({ mood }) => {
6
+ if (mood === 'happy') {
7
+ return (React.createElement(Box, { borderStyle: "round", borderColor: "green", padding: 1 },
8
+ React.createElement(Text, null,
9
+ "( ^_^) ",
10
+ "\n",
11
+ "( ",
12
+ '>',
13
+ "\u2615",
14
+ '<',
15
+ " )")));
16
+ }
17
+ if (mood === 'hungry') {
18
+ return (React.createElement(Box, { borderStyle: "double", borderColor: "red", padding: 1 },
19
+ React.createElement(Text, null,
20
+ "( 0_0 ) ",
21
+ "\n",
22
+ "( ",
23
+ '>',
24
+ "\uD83C\uDF55",
25
+ '<',
26
+ " ) ?")));
27
+ }
28
+ return React.createElement(Text, null, "( -_- ) Zzz...");
29
+ };
30
+ export const App = ({ pet }) => {
31
+ const now = new Date();
32
+ const lastFedDate = new Date(pet.lastFed);
33
+ const diffHours = (now.getTime() - lastFedDate.getTime()) / (1000 * 60 * 60);
34
+ const mood = diffHours > 4 ? 'hungry' : 'happy';
35
+ return (React.createElement(Box, { flexDirection: "column", alignItems: "center" },
36
+ React.createElement(Gradient, { name: "pastel" },
37
+ React.createElement(BigText, { text: "Termi-Gotchi" })),
38
+ React.createElement(PetAvatar, { mood: mood }),
39
+ React.createElement(Box, { marginTop: 1, flexDirection: "column", alignItems: "center" },
40
+ React.createElement(Text, { color: "green" },
41
+ "Lvl ",
42
+ pet.level,
43
+ " ",
44
+ pet.name),
45
+ React.createElement(Text, null,
46
+ "XP: ",
47
+ pet.xp.toFixed(1),
48
+ " / ",
49
+ pet.level * 50),
50
+ React.createElement(Text, { color: mood === 'hungry' ? 'red' : 'green' },
51
+ "Status: ",
52
+ mood.toUpperCase()),
53
+ React.createElement(Text, null,
54
+ "Health: ",
55
+ pet.health,
56
+ "%"))));
57
+ };
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "termi-gotchi",
3
+ "version": "1.0.0",
4
+ "description": "A CLI Tamagotchi that eats your code commits",
5
+ "license": "MIT",
6
+ "author": "MdShahAmanPatwary",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/TAIJULAMAN/Termi-Gotchi"
10
+ },
11
+ "keywords": [
12
+ "cli",
13
+ "tamagotchi",
14
+ "git",
15
+ "gamification",
16
+ "ink"
17
+ ],
18
+ "bin": "dist/cli.js",
19
+ "type": "module",
20
+ "engines": {
21
+ "node": ">=16"
22
+ },
23
+ "scripts": {
24
+ "build": "tsc",
25
+ "dev": "tsc --watch",
26
+ "test": "prettier --check . && xo && ava"
27
+ },
28
+ "files": [
29
+ "dist"
30
+ ],
31
+ "dependencies": {
32
+ "conf": "^15.1.0",
33
+ "ink": "^4.1.0",
34
+ "ink-big-text": "^2.0.0",
35
+ "ink-gradient": "^4.0.0",
36
+ "meow": "^11.0.0",
37
+ "react": "^18.2.0",
38
+ "simple-git": "^3.30.0"
39
+ },
40
+ "devDependencies": {
41
+ "@sindresorhus/tsconfig": "^3.0.1",
42
+ "@types/node": "^25.2.2",
43
+ "@types/react": "^18.0.32",
44
+ "@vdemedes/prettier-config": "^2.0.1",
45
+ "ava": "^5.2.0",
46
+ "chalk": "^5.6.2",
47
+ "eslint-config-xo-react": "^0.27.0",
48
+ "eslint-plugin-react": "^7.32.2",
49
+ "eslint-plugin-react-hooks": "^4.6.0",
50
+ "ink-testing-library": "^3.0.0",
51
+ "prettier": "^2.8.7",
52
+ "ts-node": "^10.9.1",
53
+ "typescript": "^5.0.3",
54
+ "xo": "^0.53.1"
55
+ },
56
+ "ava": {
57
+ "extensions": {
58
+ "ts": "module",
59
+ "tsx": "module"
60
+ },
61
+ "nodeArguments": [
62
+ "--loader=ts-node/esm"
63
+ ]
64
+ },
65
+ "xo": {
66
+ "extends": "xo-react",
67
+ "prettier": true,
68
+ "rules": {
69
+ "react/prop-types": "off"
70
+ }
71
+ },
72
+ "prettier": "@vdemedes/prettier-config"
73
+ }
package/readme.md ADDED
@@ -0,0 +1,57 @@
1
+ # Termi-Gotchi
2
+
3
+ A CLI Tamagotchi that lives in your terminal and eats your code commits!
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # Clone the repository
9
+ git clone <repo-url>
10
+ cd termi-gotchi
11
+
12
+ # Install dependencies
13
+ npm install
14
+
15
+ # Build the project
16
+ npm run build
17
+
18
+ # Link globally (optional, but recommended for CLI usage)
19
+ npm link
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ### 1. Initialize Git Hook
25
+ Run this in any git repository where you want your pet to live:
26
+
27
+ ```bash
28
+ termi-gotchi init
29
+ ```
30
+
31
+ This installs a `post-commit` hook that will feed your pet automatically.
32
+
33
+ ### 2. Feed Your Pet
34
+ Just commit code!
35
+
36
+ ```bash
37
+ git commit -m "Fix bug"
38
+ ```
39
+
40
+ Your pet will appear briefly, eat the commit, and gain XP based on lines added/deleted. Refactoring (deleting lines) gives more XP!
41
+
42
+ ### 3. Check Status manually
43
+ You can check on your pet anytime:
44
+
45
+ ```bash
46
+ termi-gotchi
47
+ ```
48
+
49
+ ## Features
50
+ - **Hunger System**: Your pet gets hungry if you don't commit for 4 hours.
51
+ - **Level Up**: Gain XP to level up your pet.
52
+ - **Moods**: Happy, Hungry, Sleeping.
53
+
54
+ ## Technologies
55
+ - [Ink](https://github.com/vadimdemedes/ink) (React for CLI)
56
+ - `conf` for state persistence
57
+ - `simple-git` for git integration