intent-cli-python 0.5.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zeng Deyang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,155 @@
1
+ Metadata-Version: 2.4
2
+ Name: intent-cli-python
3
+ Version: 0.5.0
4
+ Summary: Semantic history for agent-driven development. Records what you did and why.
5
+ Author: Zeng Deyang
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/dozybot001/Intent
8
+ Project-URL: Repository, https://github.com/dozybot001/Intent
9
+ Keywords: agent,git,semantic-history,intent,developer-tools
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Version Control :: Git
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Dynamic: license-file
24
+
25
+ English | [简体中文](https://github.com/dozybot001/Intent/blob/main/README.CN.md)
26
+
27
+ # Intent
28
+
29
+ > Git records code changes. Intent records why.
30
+
31
+ ## The Problem
32
+
33
+ Agent-driven development produces code fast, but reasoning disappears between sessions. Every new session starts from zero — the agent doesn't know what problem was being solved, what was tried, or why a path was chosen.
34
+
35
+ ## What's Missing
36
+
37
+ Git records *what* changed. Commit messages and comments add some context. But three things consistently fall through:
38
+
39
+ **Goal continuity.** Commits are isolated snapshots. There's no structure connecting five commits to one task, or saying "this is what we're trying to accomplish."
40
+
41
+ **Decision rationale.** Why JWT over cookies? Why 15-minute expiry? This rarely makes it into commit messages — and when it does, it's unstructured text that agents must parse and guess from.
42
+
43
+ **Work state.** `git status` can be clean while a task is half-done. The next session has no signal that work was interrupted or what comes next.
44
+
45
+ ## The Solution
46
+
47
+ Intent adds a `.intent/` directory to your repository — structured, machine-readable metadata that captures semantic history alongside code history.
48
+
49
+ ```
50
+ .git/ ← how code changed
51
+ .intent/ ← what you were doing and why
52
+ ```
53
+
54
+ Two objects: **intent** (the goal) and **snap** (a step taken, with rationale). All JSON. Any agent platform can read it.
55
+
56
+ ### What changes
57
+
58
+ **Without `.intent/`** — new agent session opens. It reads `git log` and source code. Understands what the code does *now*, but doesn't know the JWT migration was for compliance (might revert it), doesn't know the refresh token is intentionally incomplete, can't tell there's unfinished work. Asks: *"What would you like me to do?"*
59
+
60
+ **With `.intent/`** — new agent session opens. Runs `itt inspect`. Sees an active intent ("Migrate auth to JWT"), last snap ("Add refresh token — incomplete"), and rationale ("token rotation not done, security priority"). Says: *"I'll implement the token rotation next."*
61
+
62
+ The difference: 10 seconds of reading structured metadata vs. minutes of re-explaining context.
63
+
64
+ ## Core Loop
65
+
66
+ ```
67
+ start → snap → done
68
+ ```
69
+
70
+ - `start` — open an intent (what problem you're solving)
71
+ - `snap` — record a snap (what you did and why)
72
+ - `done` — close when complete
73
+
74
+ ## Example
75
+
76
+ ```bash
77
+ pipx install intent-cli-python
78
+ itt init # creates .intent/
79
+ itt start "Fix login timeout"
80
+ itt snap "Increase timeout to 30s" -m "5s too short for slow networks"
81
+ git add . && git commit -m "fix timeout"
82
+ itt done
83
+ ```
84
+
85
+ ## Why Not Just…
86
+
87
+ | Approach | What it does well | What falls through |
88
+ | --- | --- | --- |
89
+ | **Git commit messages** | Records what changed per commit | No goal structure across commits; rationale is afterthought; no work-in-progress state |
90
+ | **CLAUDE.md / .cursorrules** | Gives agents project-level instructions | Static — doesn't track active tasks, decisions, or progress; must be manually maintained |
91
+ | **TODO comments** | Marks incomplete work in-place | Scattered across files; no lifecycle; no rationale; agents must grep and guess priority |
92
+ | **Notion / Linear / Jira** | Rich project tracking for humans | External to the repo; agents can't read them without API integration; overhead is high for solo/agent workflows |
93
+ | **Agent memory** (e.g. Claude Code memory) | Persists user preferences across sessions | Tied to one platform; not versioned with code; not shareable across agents or teammates |
94
+ | **Ad-hoc context files** (e.g. `context.md`) | Quick, zero-tooling setup | No schema — every project invents its own format; no lifecycle management; grows stale silently |
95
+
96
+ **Intent occupies a specific gap**: structured, versioned, task-scoped context that lives *in the repo* and works across any agent platform.
97
+
98
+ - **Structured** — JSON objects with defined schema, not free text an agent must interpret
99
+ - **Task-scoped** — an intent has a lifecycle (`open → done`); snaps are ordered steps, not a pile of notes
100
+ - **Versioned** — `.intent/` is committed alongside code; `git blame` works on your decisions too
101
+ - **Platform-agnostic** — any agent that reads JSON can use it; no vendor lock-in
102
+ - **Minimal** — two objects (intent, snap), one CLI, zero dependencies; adds seconds to a workflow, not minutes
103
+
104
+ The closest alternative is writing a `context.md` by hand. Intent trades that flexibility for consistency: a schema agents can rely on without per-project prompt engineering.
105
+
106
+ ## Where This Is Going
107
+
108
+ `.intent/` is a protocol, not just a tool.
109
+
110
+ 1. **Agent memory** — agents read `.intent/` on startup, recover last session's context in seconds
111
+ 2. **Context exchange** — `.intent/` becomes the standard way to hand off work between agent platforms
112
+ 3. **Network effects** — when enough repos contain `.intent/`, new tooling emerges: intent-aware review, decision archaeology, semantic dashboards
113
+
114
+ ## Install
115
+
116
+ **Users:**
117
+
118
+ ```bash
119
+ pipx install intent-cli-python
120
+ ```
121
+
122
+ **Configure your agent:** Install the Intent skill so your agent knows the workflow:
123
+
124
+ ```bash
125
+ npx skills add dozybot001/Intent
126
+ ```
127
+
128
+ **Contributors:**
129
+
130
+ ```bash
131
+ git clone https://github.com/dozybot001/Intent.git
132
+ cd Intent
133
+ python3 ./itt # dev entry point, no install needed
134
+ ```
135
+
136
+ ## Commands
137
+
138
+ | Command | Purpose |
139
+ | --- | --- |
140
+ | `itt init` | Initialize `.intent/` |
141
+ | `itt start <title>` | Open an intent |
142
+ | `itt snap <title> [-m why]` | Record a snap |
143
+ | `itt done` | Close the active intent |
144
+ | `itt inspect` | Machine-readable workspace snapshot |
145
+ | `itt list <intent\|snap>` | List objects |
146
+ | `itt show <id>` | Show a single object |
147
+ | `itt suspend` | Suspend the active intent |
148
+ | `itt resume [id]` | Resume a suspended intent |
149
+ | `itt adopt [id]` | Adopt a candidate snap |
150
+ | `itt revert` | Revert the latest snap |
151
+
152
+ ## Documentation
153
+
154
+ - [CLI spec](https://github.com/dozybot001/Intent/blob/main/docs/cli.EN.md) — objects, commands, JSON output contract
155
+ - [Dogfooding](https://github.com/dozybot001/Intent/blob/main/docs/dogfooding.md) — how we built Intent with Intent
@@ -0,0 +1,131 @@
1
+ English | [简体中文](https://github.com/dozybot001/Intent/blob/main/README.CN.md)
2
+
3
+ # Intent
4
+
5
+ > Git records code changes. Intent records why.
6
+
7
+ ## The Problem
8
+
9
+ Agent-driven development produces code fast, but reasoning disappears between sessions. Every new session starts from zero — the agent doesn't know what problem was being solved, what was tried, or why a path was chosen.
10
+
11
+ ## What's Missing
12
+
13
+ Git records *what* changed. Commit messages and comments add some context. But three things consistently fall through:
14
+
15
+ **Goal continuity.** Commits are isolated snapshots. There's no structure connecting five commits to one task, or saying "this is what we're trying to accomplish."
16
+
17
+ **Decision rationale.** Why JWT over cookies? Why 15-minute expiry? This rarely makes it into commit messages — and when it does, it's unstructured text that agents must parse and guess from.
18
+
19
+ **Work state.** `git status` can be clean while a task is half-done. The next session has no signal that work was interrupted or what comes next.
20
+
21
+ ## The Solution
22
+
23
+ Intent adds a `.intent/` directory to your repository — structured, machine-readable metadata that captures semantic history alongside code history.
24
+
25
+ ```
26
+ .git/ ← how code changed
27
+ .intent/ ← what you were doing and why
28
+ ```
29
+
30
+ Two objects: **intent** (the goal) and **snap** (a step taken, with rationale). All JSON. Any agent platform can read it.
31
+
32
+ ### What changes
33
+
34
+ **Without `.intent/`** — new agent session opens. It reads `git log` and source code. Understands what the code does *now*, but doesn't know the JWT migration was for compliance (might revert it), doesn't know the refresh token is intentionally incomplete, can't tell there's unfinished work. Asks: *"What would you like me to do?"*
35
+
36
+ **With `.intent/`** — new agent session opens. Runs `itt inspect`. Sees an active intent ("Migrate auth to JWT"), last snap ("Add refresh token — incomplete"), and rationale ("token rotation not done, security priority"). Says: *"I'll implement the token rotation next."*
37
+
38
+ The difference: 10 seconds of reading structured metadata vs. minutes of re-explaining context.
39
+
40
+ ## Core Loop
41
+
42
+ ```
43
+ start → snap → done
44
+ ```
45
+
46
+ - `start` — open an intent (what problem you're solving)
47
+ - `snap` — record a snap (what you did and why)
48
+ - `done` — close when complete
49
+
50
+ ## Example
51
+
52
+ ```bash
53
+ pipx install intent-cli-python
54
+ itt init # creates .intent/
55
+ itt start "Fix login timeout"
56
+ itt snap "Increase timeout to 30s" -m "5s too short for slow networks"
57
+ git add . && git commit -m "fix timeout"
58
+ itt done
59
+ ```
60
+
61
+ ## Why Not Just…
62
+
63
+ | Approach | What it does well | What falls through |
64
+ | --- | --- | --- |
65
+ | **Git commit messages** | Records what changed per commit | No goal structure across commits; rationale is afterthought; no work-in-progress state |
66
+ | **CLAUDE.md / .cursorrules** | Gives agents project-level instructions | Static — doesn't track active tasks, decisions, or progress; must be manually maintained |
67
+ | **TODO comments** | Marks incomplete work in-place | Scattered across files; no lifecycle; no rationale; agents must grep and guess priority |
68
+ | **Notion / Linear / Jira** | Rich project tracking for humans | External to the repo; agents can't read them without API integration; overhead is high for solo/agent workflows |
69
+ | **Agent memory** (e.g. Claude Code memory) | Persists user preferences across sessions | Tied to one platform; not versioned with code; not shareable across agents or teammates |
70
+ | **Ad-hoc context files** (e.g. `context.md`) | Quick, zero-tooling setup | No schema — every project invents its own format; no lifecycle management; grows stale silently |
71
+
72
+ **Intent occupies a specific gap**: structured, versioned, task-scoped context that lives *in the repo* and works across any agent platform.
73
+
74
+ - **Structured** — JSON objects with defined schema, not free text an agent must interpret
75
+ - **Task-scoped** — an intent has a lifecycle (`open → done`); snaps are ordered steps, not a pile of notes
76
+ - **Versioned** — `.intent/` is committed alongside code; `git blame` works on your decisions too
77
+ - **Platform-agnostic** — any agent that reads JSON can use it; no vendor lock-in
78
+ - **Minimal** — two objects (intent, snap), one CLI, zero dependencies; adds seconds to a workflow, not minutes
79
+
80
+ The closest alternative is writing a `context.md` by hand. Intent trades that flexibility for consistency: a schema agents can rely on without per-project prompt engineering.
81
+
82
+ ## Where This Is Going
83
+
84
+ `.intent/` is a protocol, not just a tool.
85
+
86
+ 1. **Agent memory** — agents read `.intent/` on startup, recover last session's context in seconds
87
+ 2. **Context exchange** — `.intent/` becomes the standard way to hand off work between agent platforms
88
+ 3. **Network effects** — when enough repos contain `.intent/`, new tooling emerges: intent-aware review, decision archaeology, semantic dashboards
89
+
90
+ ## Install
91
+
92
+ **Users:**
93
+
94
+ ```bash
95
+ pipx install intent-cli-python
96
+ ```
97
+
98
+ **Configure your agent:** Install the Intent skill so your agent knows the workflow:
99
+
100
+ ```bash
101
+ npx skills add dozybot001/Intent
102
+ ```
103
+
104
+ **Contributors:**
105
+
106
+ ```bash
107
+ git clone https://github.com/dozybot001/Intent.git
108
+ cd Intent
109
+ python3 ./itt # dev entry point, no install needed
110
+ ```
111
+
112
+ ## Commands
113
+
114
+ | Command | Purpose |
115
+ | --- | --- |
116
+ | `itt init` | Initialize `.intent/` |
117
+ | `itt start <title>` | Open an intent |
118
+ | `itt snap <title> [-m why]` | Record a snap |
119
+ | `itt done` | Close the active intent |
120
+ | `itt inspect` | Machine-readable workspace snapshot |
121
+ | `itt list <intent\|snap>` | List objects |
122
+ | `itt show <id>` | Show a single object |
123
+ | `itt suspend` | Suspend the active intent |
124
+ | `itt resume [id]` | Resume a suspended intent |
125
+ | `itt adopt [id]` | Adopt a candidate snap |
126
+ | `itt revert` | Revert the latest snap |
127
+
128
+ ## Documentation
129
+
130
+ - [CLI spec](https://github.com/dozybot001/Intent/blob/main/docs/cli.EN.md) — objects, commands, JSON output contract
131
+ - [Dogfooding](https://github.com/dozybot001/Intent/blob/main/docs/dogfooding.md) — how we built Intent with Intent
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "intent-cli-python"
7
+ version = "0.5.0"
8
+ description = "Semantic history for agent-driven development. Records what you did and why."
9
+ requires-python = ">=3.9"
10
+ readme = "README.md"
11
+ license = "MIT"
12
+ authors = [
13
+ { name = "Zeng Deyang" },
14
+ ]
15
+ keywords = ["agent", "git", "semantic-history", "intent", "developer-tools"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Developers",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: Software Development :: Version Control :: Git",
27
+ ]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/dozybot001/Intent"
31
+ Repository = "https://github.com/dozybot001/Intent"
32
+
33
+ [project.scripts]
34
+ itt = "intent_cli.cli:main"
35
+
36
+ [tool.setuptools]
37
+ package-dir = {"" = "src"}
38
+
39
+ [tool.setuptools.packages.find]
40
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,29 @@
1
+ """Intent CLI package."""
2
+
3
+ from importlib import metadata
4
+ from pathlib import Path
5
+ import re
6
+ from typing import Optional
7
+
8
+
9
+ PACKAGE_NAME = "intent-cli-python"
10
+ REPO_ROOT = Path(__file__).resolve().parents[2]
11
+ PYPROJECT_PATH = REPO_ROOT / "pyproject.toml"
12
+ VERSION_PATTERN = re.compile(r'^version\s*=\s*"([^"]+)"\s*$', re.MULTILINE)
13
+
14
+
15
+ def version_from_checkout() -> Optional[str]:
16
+ if not PYPROJECT_PATH.exists():
17
+ return None
18
+ match = VERSION_PATTERN.search(PYPROJECT_PATH.read_text(encoding="utf-8"))
19
+ if not match:
20
+ return None
21
+ return match.group(1)
22
+
23
+
24
+ __version__ = version_from_checkout()
25
+ if __version__ is None:
26
+ try:
27
+ __version__ = metadata.version(PACKAGE_NAME)
28
+ except metadata.PackageNotFoundError:
29
+ __version__ = "0.4.0"
@@ -0,0 +1,5 @@
1
+ from .cli import main
2
+
3
+
4
+ if __name__ == "__main__":
5
+ raise SystemExit(main())
@@ -0,0 +1,162 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ from pathlib import Path
6
+ from typing import Any, Dict, Optional
7
+
8
+ from . import __version__
9
+ from .constants import EXIT_GENERAL_FAILURE, EXIT_SUCCESS
10
+ from .core import IntentRepository
11
+ from .errors import IntentError
12
+
13
+
14
+ def emit(payload: Dict[str, Any]) -> None:
15
+ print(json.dumps(payload, indent=2))
16
+
17
+
18
+ def ok(action: str, result: Any, **extra: Any) -> Dict[str, Any]:
19
+ payload: Dict[str, Any] = {"ok": True, "action": action, "result": result}
20
+ payload.update(extra)
21
+ return payload
22
+
23
+
24
+ def build_parser() -> argparse.ArgumentParser:
25
+ parser = argparse.ArgumentParser(
26
+ prog="itt",
27
+ description="Intent CLI — semantic history for agents.",
28
+ )
29
+ parser.add_argument("--version", action="version", version=f"intent-cli {__version__}")
30
+ sub = parser.add_subparsers(dest="command", required=True, title="commands")
31
+
32
+ sub.add_parser("version", help="Show version")
33
+
34
+ sub.add_parser("init", help="Initialize Intent in the current Git repository")
35
+
36
+ start_p = sub.add_parser("start", help="Create and activate an intent")
37
+ start_p.add_argument("title")
38
+
39
+ snap_p = sub.add_parser("snap", help="Record a snap (adopted by default)")
40
+ snap_p.add_argument("title")
41
+ snap_p.add_argument("-m", "--message", help="Rationale for this snap")
42
+ snap_p.add_argument("--candidate", action="store_true", help="Record as candidate without adopting")
43
+
44
+ adopt_p = sub.add_parser("adopt", help="Adopt a candidate snap")
45
+ adopt_p.add_argument("snap_id", nargs="?")
46
+ adopt_p.add_argument("-m", "--message", help="Rationale for adoption")
47
+
48
+ revert_p = sub.add_parser("revert", help="Revert the latest adopted snap")
49
+ revert_p.add_argument("-m", "--message", help="Rationale for revert")
50
+
51
+ sub.add_parser("suspend", help="Suspend the active intent")
52
+
53
+ resume_p = sub.add_parser("resume", help="Resume a suspended intent")
54
+ resume_p.add_argument("intent_id", nargs="?")
55
+
56
+ done_p = sub.add_parser("done", help="Close the active intent")
57
+ done_p.add_argument("intent_id", nargs="?")
58
+
59
+ sub.add_parser("inspect", help="Machine-readable workspace snapshot")
60
+
61
+ list_p = sub.add_parser("list", help="List objects")
62
+ list_p.add_argument("type", choices=["intent", "snap"])
63
+ list_p.add_argument("--intent", dest="intent_id", help="Filter snaps by intent ID")
64
+
65
+ show_p = sub.add_parser("show", help="Show a single object by ID")
66
+ show_p.add_argument("id")
67
+
68
+ return parser
69
+
70
+
71
+ def main(argv: Optional[list[str]] = None) -> int:
72
+ parser = build_parser()
73
+ args = parser.parse_args(argv)
74
+ repo = IntentRepository(Path.cwd())
75
+
76
+ try:
77
+ if args.command == "version":
78
+ emit(ok("version", {"version": __version__}))
79
+ return EXIT_SUCCESS
80
+
81
+ if args.command == "init":
82
+ repo.ensure_git()
83
+ config, state = repo.init_workspace()
84
+ emit(ok("init", {"config": config, "state": state}))
85
+ return EXIT_SUCCESS
86
+
87
+ if args.command == "start":
88
+ intent, warnings = repo.create_intent(args.title)
89
+ emit(ok("start", intent, warnings=warnings))
90
+ return EXIT_SUCCESS
91
+
92
+ if args.command == "snap":
93
+ snap, warnings = repo.create_snap(
94
+ args.title,
95
+ rationale=args.message,
96
+ candidate=args.candidate,
97
+ )
98
+ emit(ok("snap", snap, warnings=warnings))
99
+ return EXIT_SUCCESS
100
+
101
+ if args.command == "adopt":
102
+ snap, warnings = repo.adopt_snap(
103
+ snap_id=args.snap_id,
104
+ rationale=args.message,
105
+ )
106
+ emit(ok("adopt", snap, warnings=warnings))
107
+ return EXIT_SUCCESS
108
+
109
+ if args.command == "revert":
110
+ snap, warnings = repo.revert_snap(rationale=args.message)
111
+ emit(ok("revert", snap, warnings=warnings))
112
+ return EXIT_SUCCESS
113
+
114
+ if args.command == "suspend":
115
+ intent, warnings = repo.suspend_intent()
116
+ emit(ok("suspend", intent, warnings=warnings))
117
+ return EXIT_SUCCESS
118
+
119
+ if args.command == "resume":
120
+ intent, warnings = repo.resume_intent(intent_id=args.intent_id)
121
+ emit(ok("resume", intent, warnings=warnings))
122
+ return EXIT_SUCCESS
123
+
124
+ if args.command == "done":
125
+ intent, warnings = repo.close_intent(intent_id=args.intent_id)
126
+ emit(ok("done", intent, warnings=warnings))
127
+ return EXIT_SUCCESS
128
+
129
+ if args.command == "inspect":
130
+ emit(repo.inspect())
131
+ return EXIT_SUCCESS
132
+
133
+ if args.command == "list":
134
+ items = repo.list_objects(args.type, intent_id=getattr(args, "intent_id", None))
135
+ emit(ok("list", items, count=len(items)))
136
+ return EXIT_SUCCESS
137
+
138
+ if args.command == "show":
139
+ obj = repo.show_object(args.id)
140
+ emit(ok("show", obj))
141
+ return EXIT_SUCCESS
142
+
143
+ parser.error("unknown command")
144
+ return 2
145
+
146
+ except IntentError as error:
147
+ emit(error.to_json())
148
+ return error.exit_code
149
+ except Exception as error:
150
+ emit({
151
+ "ok": False,
152
+ "error": {
153
+ "code": "INTERNAL_ERROR",
154
+ "message": str(error),
155
+ "details": {},
156
+ },
157
+ })
158
+ return EXIT_GENERAL_FAILURE
159
+
160
+
161
+ if __name__ == "__main__":
162
+ raise SystemExit(main())
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ SCHEMA_VERSION = "0.2"
4
+
5
+ EXIT_SUCCESS = 0
6
+ EXIT_GENERAL_FAILURE = 1
7
+ EXIT_INVALID_INPUT = 2
8
+ EXIT_STATE_CONFLICT = 3
9
+ EXIT_OBJECT_NOT_FOUND = 4
10
+
11
+ DIR_NAMES = {
12
+ "intent": "intents",
13
+ "snap": "snaps",
14
+ }
15
+
16
+ ID_PREFIXES = {
17
+ "intent": "intent",
18
+ "snap": "snap",
19
+ }